Home | History | Annotate | Download | only in md
      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /*
      3  * The contents of this file are subject to the Mozilla Public
      4  * License Version 1.1 (the "License"); you may not use this file
      5  * except in compliance with the License. You may obtain a copy of
      6  * the License at http://www.mozilla.org/MPL/
      7  *
      8  * Software distributed under the License is distributed on an "AS
      9  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
     10  * implied. See the License for the specific language governing
     11  * rights and limitations under the License.
     12  *
     13  * The Original Code is the Netscape Portable Runtime (NSPR).
     14  *
     15  * The Initial Developer of the Original Code is Netscape
     16  * Communications Corporation.  Portions created by Netscape are
     17  * Copyright (C) 1998-2000 Netscape Communications Corporation.  All
     18  * Rights Reserved.
     19  *
     20  * Contributor(s):
     21  *
     22  * Alternatively, the contents of this file may be used under the
     23  * terms of the GNU General Public License Version 2 or later (the
     24  * "GPL"), in which case the provisions of the GPL are applicable
     25  * instead of those above.  If you wish to allow use of your
     26  * version of this file only under the terms of the GPL and not to
     27  * allow others to use your version of this file under the MPL,
     28  * indicate your decision by deleting the provisions above and
     29  * replace them with the notice and other provisions required by
     30  * the GPL.  If you do not delete the provisions above, a recipient
     31  * may use your version of this file under either the MPL or the
     32  * GPL.
     33  */
     34 
     35 #ifndef nspr_irix_defs_h___
     36 #define nspr_irix_defs_h___
     37 
     38 #define _PR_HAVE_ATOMIC_CAS
     39 
     40 /*
     41  * MipsPro assembler defines _LANGUAGE_ASSEMBLY
     42  */
     43 #ifndef _LANGUAGE_ASSEMBLY
     44 
     45 #include "prclist.h"
     46 #include "prthread.h"
     47 #include <sys/ucontext.h>
     48 
     49 /*
     50  * Internal configuration macros
     51  */
     52 
     53 #define PR_LINKER_ARCH          "irix"
     54 #define _PR_SI_SYSNAME          "IRIX"
     55 #define _PR_SI_ARCHITECTURE     "mips"
     56 #define PR_DLL_SUFFIX		".so"
     57 
     58 #define _PR_VMBASE              0x30000000
     59 #define _PR_STACK_VMBASE        0x50000000
     60 #define _PR_NUM_GCREGS          9
     61 #define _MD_MMAP_FLAGS          MAP_PRIVATE
     62 
     63 #define _MD_DEFAULT_STACK_SIZE  65536L
     64 #define _MD_MIN_STACK_SIZE      16384L
     65 
     66 #undef  HAVE_STACK_GROWING_UP
     67 #define HAVE_WEAK_IO_SYMBOLS
     68 #define HAVE_WEAK_MALLOC_SYMBOLS
     69 #define HAVE_DLL
     70 #define USE_DLFCN
     71 #define _PR_HAVE_ATOMIC_OPS
     72 #define _PR_POLL_AVAILABLE
     73 #define _PR_USE_POLL
     74 #define _PR_STAT_HAS_ST_ATIM
     75 #define _PR_HAVE_OFF64_T
     76 #define HAVE_POINTER_LOCALTIME_R
     77 #define _PR_HAVE_POSIX_SEMAPHORES
     78 #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY
     79 #define _PR_ACCEPT_INHERIT_NONBLOCK
     80 
     81 #ifdef _PR_INET6
     82 #define _PR_HAVE_INET_NTOP
     83 #define _PR_HAVE_GETIPNODEBYNAME
     84 #define _PR_HAVE_GETIPNODEBYADDR
     85 #define _PR_HAVE_GETADDRINFO
     86 #endif
     87 
     88 /* Initialization entry points */
     89 NSPR_API(void) _MD_EarlyInit(void);
     90 #define _MD_EARLY_INIT _MD_EarlyInit
     91 
     92 NSPR_API(void) _MD_IrixInit(void);
     93 #define _MD_FINAL_INIT _MD_IrixInit
     94 
     95 #define _MD_INIT_IO()
     96 
     97 /* Timer operations */
     98 NSPR_API(PRIntervalTime) _MD_IrixGetInterval(void);
     99 #define _MD_GET_INTERVAL _MD_IrixGetInterval
    100 
    101 NSPR_API(PRIntervalTime) _MD_IrixIntervalPerSec(void);
    102 #define _MD_INTERVAL_PER_SEC _MD_IrixIntervalPerSec
    103 
    104 /* GC operations */
    105 NSPR_API(void *) _MD_GetSP(PRThread *thread);
    106 #define    _MD_GET_SP _MD_GetSP
    107 
    108 /* The atomic operations */
    109 #include <mutex.h>
    110 #define _MD_INIT_ATOMIC()
    111 #define _MD_ATOMIC_INCREMENT(val) add_then_test((unsigned long*)val, 1)
    112 #define _MD_ATOMIC_ADD(ptr, val) add_then_test((unsigned long*)ptr, (unsigned long)val)
    113 #define _MD_ATOMIC_DECREMENT(val) add_then_test((unsigned long*)val, 0xffffffff)
    114 #define _MD_ATOMIC_SET(val, newval) test_and_set((unsigned long*)val, newval)
    115 
    116 #if defined(_PR_PTHREADS)
    117 #else /* defined(_PR_PTHREADS) */
    118 
    119 /************************************************************************/
    120 
    121 #include <setjmp.h>
    122 #include <errno.h>
    123 #include <unistd.h>
    124 #include <bstring.h>
    125 #include <sys/time.h>
    126 #include <ulocks.h>
    127 #include <sys/prctl.h>
    128 
    129 
    130 /*
    131  * Data region private to each sproc. This region is setup by calling
    132  * mmap(...,MAP_LOCAL,...). The private data is mapped at the same
    133  * address in every sproc, but every sproc gets a private mapping.
    134  *
    135  * Just make sure that this structure fits in a page, as only one page
    136  * is allocated for the private region.
    137  */
    138 struct sproc_private_data {
    139     struct PRThread *me;
    140     struct _PRCPU *cpu;
    141     struct PRThread *last;
    142     PRUintn intsOff;
    143 	int		sproc_pid;
    144 };
    145 
    146 extern char *_nspr_sproc_private;
    147 
    148 #define _PR_PRDA() ((struct sproc_private_data *) _nspr_sproc_private)
    149 #define _MD_SET_CURRENT_THREAD(_thread) _PR_PRDA()->me = (_thread)
    150 #define _MD_THIS_THREAD() (_PR_PRDA()->me)
    151 #define _MD_LAST_THREAD() (_PR_PRDA()->last)
    152 #define _MD_SET_LAST_THREAD(_thread) _PR_PRDA()->last = (_thread)
    153 #define _MD_CURRENT_CPU() (_PR_PRDA()->cpu)
    154 #define _MD_SET_CURRENT_CPU(_cpu) _PR_PRDA()->cpu = (_cpu)
    155 #define _MD_SET_INTSOFF(_val) (_PR_PRDA()->intsOff = _val)
    156 #define _MD_GET_INTSOFF() (_PR_PRDA()->intsOff)
    157 
    158 #define _MD_SET_SPROC_PID(_val) (_PR_PRDA()->sproc_pid = _val)
    159 #define _MD_GET_SPROC_PID() (_PR_PRDA()->sproc_pid)
    160 
    161 NSPR_API(struct PRThread*) _MD_get_attached_thread(void);
    162 NSPR_API(struct PRThread*) _MD_get_current_thread(void);
    163 #define _MD_GET_ATTACHED_THREAD()	_MD_get_attached_thread()
    164 #define _MD_CURRENT_THREAD()	_MD_get_current_thread()
    165 
    166 #define _MD_CHECK_FOR_EXIT() {					\
    167 		if (_pr_irix_exit_now) {				\
    168 			_PR_POST_SEM(_pr_irix_exit_sem);	\
    169 			_MD_Wakeup_CPUs();					\
    170 			_exit(0);							\
    171 		}										\
    172 	}
    173 
    174 #define _MD_ATTACH_THREAD(threadp)
    175 
    176 #define _MD_SAVE_ERRNO(_thread)			(_thread)->md.errcode = errno;
    177 #define _MD_RESTORE_ERRNO(_thread)		errno = (_thread)->md.errcode;
    178 
    179 extern struct _PRCPU  *_pr_primordialCPU;
    180 extern usema_t *_pr_irix_exit_sem;
    181 extern PRInt32 _pr_irix_exit_now;
    182 extern int _pr_irix_primoridal_cpu_fd[];
    183 extern PRInt32 _pr_irix_process_exit;
    184 extern PRInt32 _pr_irix_process_exit_code;
    185 
    186 /* Thread operations */
    187 #define _PR_LOCK_HEAP()	{						\
    188 			PRIntn _is;					\
    189 				if (_pr_primordialCPU) {		\
    190 				if (_MD_GET_ATTACHED_THREAD() && 		\
    191 					!_PR_IS_NATIVE_THREAD( 		\
    192 					_MD_GET_ATTACHED_THREAD()))	\
    193 						_PR_INTSOFF(_is); 	\
    194 					_PR_LOCK(_pr_heapLock);		\
    195 				}
    196 
    197 #define _PR_UNLOCK_HEAP() 	if (_pr_primordialCPU)	{		\
    198 					_PR_UNLOCK(_pr_heapLock);	\
    199 				if (_MD_GET_ATTACHED_THREAD() && 		\
    200 					!_PR_IS_NATIVE_THREAD( 		\
    201 					_MD_GET_ATTACHED_THREAD()))	\
    202 						_PR_INTSON(_is);	\
    203 				}					\
    204 			  }
    205 
    206 #define _PR_OPEN_POLL_SEM(_sem)  usopenpollsema(_sem, 0666)
    207 #define _PR_WAIT_SEM(_sem) uspsema(_sem)
    208 #define _PR_POST_SEM(_sem) usvsema(_sem)
    209 
    210 #define _MD_CVAR_POST_SEM(threadp)	usvsema((threadp)->md.cvar_pollsem)
    211 
    212 #define _MD_IOQ_LOCK()
    213 #define _MD_IOQ_UNLOCK()
    214 
    215 struct _MDLock {
    216     ulock_t lock;
    217 	usptr_t *arena;
    218 };
    219 
    220 /*
    221  * disable pre-emption for the LOCAL threads when calling the arena lock
    222  * routines
    223  */
    224 
    225 #define _PR_LOCK(lock) {						\
    226 		PRIntn _is;						\
    227 		PRThread *me = _MD_GET_ATTACHED_THREAD();			\
    228 		if (me && !_PR_IS_NATIVE_THREAD(me))			\
    229 			_PR_INTSOFF(_is); 				\
    230 		ussetlock(lock);					\
    231 		if (me && !_PR_IS_NATIVE_THREAD(me))			\
    232 			_PR_FAST_INTSON(_is); 				\
    233 	}
    234 
    235 #define _PR_UNLOCK(lock) {						\
    236 		PRIntn _is;						\
    237 		PRThread *me = _MD_GET_ATTACHED_THREAD();			\
    238 		if (me && !_PR_IS_NATIVE_THREAD(me))			\
    239 			_PR_INTSOFF(_is); 				\
    240 		usunsetlock(lock);					\
    241 		if (me && !_PR_IS_NATIVE_THREAD(me))			\
    242 			_PR_FAST_INTSON(_is); 				\
    243 	}
    244 
    245 NSPR_API(PRStatus) _MD_NEW_LOCK(struct _MDLock *md);
    246 NSPR_API(void) _MD_FREE_LOCK(struct _MDLock *lockp);
    247 
    248 #define _MD_LOCK(_lockp) _PR_LOCK((_lockp)->lock)
    249 #define _MD_UNLOCK(_lockp) _PR_UNLOCK((_lockp)->lock)
    250 #define _MD_TEST_AND_LOCK(_lockp) (uscsetlock((_lockp)->lock, 1) == 0)
    251 
    252 extern ulock_t _pr_heapLock;
    253 
    254 struct _MDThread {
    255     jmp_buf jb;
    256     usptr_t     *pollsem_arena;
    257     usema_t     *cvar_pollsem;
    258     PRInt32     cvar_pollsemfd;
    259     PRInt32     cvar_pollsem_select;    /* acquire sem by calling select */
    260     PRInt32     cvar_wait;              /* if 1, thread is waiting on cvar Q */
    261     PRInt32	id;
    262     PRInt32	suspending_id;
    263     int errcode;
    264 };
    265 
    266 struct _MDThreadStack {
    267     PRInt8 notused;
    268 };
    269 
    270 struct _MDSemaphore {
    271     usema_t *sem;
    272 };
    273 
    274 struct _MDCVar {
    275     ulock_t mdcvar_lock;
    276 };
    277 
    278 struct _MDSegment {
    279     PRInt8 notused;
    280 };
    281 
    282 /*
    283  * md-specific cpu structure field
    284  */
    285 #define _PR_MD_MAX_OSFD FD_SETSIZE
    286 
    287 struct _MDCPU_Unix {
    288     PRCList ioQ;
    289     PRUint32 ioq_timeout;
    290     PRInt32 ioq_max_osfd;
    291     PRInt32 ioq_osfd_cnt;
    292 #ifndef _PR_USE_POLL
    293     fd_set fd_read_set, fd_write_set, fd_exception_set;
    294     PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
    295 				fd_exception_cnt[_PR_MD_MAX_OSFD];
    296 #else
    297 	struct pollfd *ioq_pollfds;
    298 	int ioq_pollfds_size;
    299 #endif	/* _PR_USE_POLL */
    300 };
    301 
    302 #define _PR_IOQ(_cpu)			((_cpu)->md.md_unix.ioQ)
    303 #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
    304 #define _PR_FD_READ_SET(_cpu)		((_cpu)->md.md_unix.fd_read_set)
    305 #define _PR_FD_READ_CNT(_cpu)		((_cpu)->md.md_unix.fd_read_cnt)
    306 #define _PR_FD_WRITE_SET(_cpu)		((_cpu)->md.md_unix.fd_write_set)
    307 #define _PR_FD_WRITE_CNT(_cpu)		((_cpu)->md.md_unix.fd_write_cnt)
    308 #define _PR_FD_EXCEPTION_SET(_cpu)	((_cpu)->md.md_unix.fd_exception_set)
    309 #define _PR_FD_EXCEPTION_CNT(_cpu)	((_cpu)->md.md_unix.fd_exception_cnt)
    310 #define _PR_IOQ_TIMEOUT(_cpu)		((_cpu)->md.md_unix.ioq_timeout)
    311 #define _PR_IOQ_MAX_OSFD(_cpu)		((_cpu)->md.md_unix.ioq_max_osfd)
    312 #define _PR_IOQ_OSFD_CNT(_cpu)		((_cpu)->md.md_unix.ioq_osfd_cnt)
    313 #define _PR_IOQ_POLLFDS(_cpu)		((_cpu)->md.md_unix.ioq_pollfds)
    314 #define _PR_IOQ_POLLFDS_SIZE(_cpu)	((_cpu)->md.md_unix.ioq_pollfds_size)
    315 
    316 #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu)	32
    317 
    318 
    319 struct _MDCPU {
    320     PRInt32 id;
    321     PRInt32 suspending_id;
    322     struct _MDCPU_Unix md_unix;
    323 };
    324 
    325 /*
    326 ** Initialize the thread context preparing it to execute _main.
    327 */
    328 #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)	      \
    329     PR_BEGIN_MACRO				      \
    330 	int *jb = (_thread)->md.jb;		      \
    331     *status = PR_TRUE;              \
    332 	(void) setjmp(jb);			      \
    333 	(_thread)->md.jb[JB_SP] = (int) ((_sp) - 64); \
    334 	(_thread)->md.jb[JB_PC] = (int) _main;	      \
    335 	_thread->no_sched = 0; \
    336     PR_END_MACRO
    337 
    338 /*
    339 ** Switch away from the current thread context by saving its state and
    340 ** calling the thread scheduler. Reload cpu when we come back from the
    341 ** context switch because it might have changed.
    342 *
    343 *  XXX RUNQ lock needed before clearing _PR_NO_SCHED flag, because the
    344 *      thread may be unr RUNQ?
    345 */
    346 #define _MD_SWITCH_CONTEXT(_thread) \
    347     PR_BEGIN_MACRO    \
    348     PR_ASSERT(_thread->no_sched); \
    349     if (!setjmp(_thread->md.jb)) { \
    350         _MD_SAVE_ERRNO(_thread) \
    351         _MD_SET_LAST_THREAD(_thread); \
    352         _PR_Schedule(); \
    353     } else {      \
    354         PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \
    355             _MD_LAST_THREAD()->no_sched = 0;			\
    356     }             \
    357     PR_END_MACRO
    358 
    359 /*
    360 ** Restore a thread context that was saved by _MD_SWITCH_CONTEXT or
    361 ** initialized by _MD_INIT_CONTEXT.
    362 */
    363 #define _MD_RESTORE_CONTEXT(_newThread) \
    364     PR_BEGIN_MACRO \
    365     int *jb = (_newThread)->md.jb; \
    366     _MD_RESTORE_ERRNO(_newThread) \
    367     _MD_SET_CURRENT_THREAD(_newThread); \
    368     _newThread->no_sched = 1;		\
    369     longjmp(jb, 1); \
    370     PR_END_MACRO
    371 
    372 NSPR_API(PRStatus) _MD_InitThread(struct PRThread *thread,
    373 								PRBool wakeup_parent);
    374 NSPR_API(PRStatus) _MD_InitAttachedThread(struct PRThread *thread,
    375 									PRBool wakeup_parent);
    376 #define _MD_INIT_THREAD(thread) 			_MD_InitThread(thread, PR_TRUE)
    377 #define _MD_INIT_ATTACHED_THREAD(thread)		\
    378 						_MD_InitAttachedThread(thread, PR_FALSE)
    379 
    380 NSPR_API(void) _MD_ExitThread(struct PRThread *thread);
    381 #define _MD_EXIT_THREAD _MD_ExitThread
    382 
    383 NSPR_API(void) _MD_SuspendThread(struct PRThread *thread);
    384 #define _MD_SUSPEND_THREAD _MD_SuspendThread
    385 
    386 NSPR_API(void) _MD_ResumeThread(struct PRThread *thread);
    387 #define _MD_RESUME_THREAD _MD_ResumeThread
    388 
    389 NSPR_API(void) _MD_SuspendCPU(struct _PRCPU *thread);
    390 #define _MD_SUSPEND_CPU _MD_SuspendCPU
    391 
    392 NSPR_API(void) _MD_ResumeCPU(struct _PRCPU *thread);
    393 #define _MD_RESUME_CPU _MD_ResumeCPU
    394 
    395 #define _MD_BEGIN_SUSPEND_ALL()
    396 #define _MD_END_SUSPEND_ALL()
    397 #define _MD_BEGIN_RESUME_ALL()
    398 #define _MD_END_RESUME_ALL()
    399 
    400 NSPR_API(void) _MD_InitLocks(void);
    401 #define _MD_INIT_LOCKS _MD_InitLocks
    402 
    403 NSPR_API(void) _MD_CleanThread(struct PRThread *thread);
    404 #define _MD_CLEAN_THREAD _MD_CleanThread
    405 
    406 #define _MD_YIELD()    sginap(0)
    407 
    408 /* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and
    409  * awaken a thread which is waiting on a lock or cvar.
    410  */
    411 NSPR_API(PRStatus) _MD_wait(struct PRThread *, PRIntervalTime timeout);
    412 #define _MD_WAIT _MD_wait
    413 
    414 NSPR_API(void) _PR_MD_primordial_cpu();
    415 NSPR_API(void) _PR_MD_WAKEUP_PRIMORDIAL_CPU();
    416 
    417 NSPR_API(PRStatus) _MD_WakeupWaiter(struct PRThread *);
    418 #define _MD_WAKEUP_WAITER _MD_WakeupWaiter
    419 
    420 NSPR_API(void ) _MD_exit(PRIntn status);
    421 #define _MD_EXIT	_MD_exit
    422 
    423 #include "prthread.h"
    424 
    425 NSPR_API(void) _MD_SetPriority(struct _MDThread *thread,
    426 	PRThreadPriority newPri);
    427 #define _MD_SET_PRIORITY _MD_SetPriority
    428 
    429 NSPR_API(PRStatus) _MD_CreateThread(
    430                         struct PRThread *thread,
    431                         void (*start) (void *),
    432                         PRThreadPriority priority,
    433                         PRThreadScope scope,
    434                         PRThreadState state,
    435                         PRUint32 stackSize);
    436 #define _MD_CREATE_THREAD _MD_CreateThread
    437 
    438 extern void _MD_CleanupBeforeExit(void);
    439 #define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit
    440 
    441 NSPR_API(void) _PR_MD_PRE_CLEANUP(PRThread *me);
    442 
    443 
    444 /* The following defines the unwrapped versions of select() and poll(). */
    445 extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
    446 	fd_set *exceptfds, struct timeval *timeout);
    447 #define _MD_SELECT	_select
    448 
    449 #include <stropts.h>
    450 #include <poll.h>
    451 #define _MD_POLL _poll
    452 extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
    453 
    454 
    455 #define HAVE_THREAD_AFFINITY 1
    456 
    457 NSPR_API(PRInt32) _MD_GetThreadAffinityMask(PRThread *unused, PRUint32 *mask);
    458 #define _MD_GETTHREADAFFINITYMASK _MD_GetThreadAffinityMask
    459 
    460 NSPR_API(void) _MD_InitRunningCPU(struct _PRCPU *cpu);
    461 #define    _MD_INIT_RUNNING_CPU _MD_InitRunningCPU
    462 
    463 #endif  /* defined(_PR_PTHREADS) */
    464 
    465 #endif /* _LANGUAGE_ASSEMBLY */
    466 
    467 #endif /* nspr_irix_defs_h___ */
    468