home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / nspr30-e.zip / nspr30-e / include / md / _solaris.h < prev    next >
C/C++ Source or Header  |  1998-11-02  |  21KB  |  710 lines

  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 Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #ifndef nspr_solaris_defs_h___
  20. #define nspr_solaris_defs_h___
  21.  
  22. /*
  23.  * Internal configuration macros
  24.  */
  25.  
  26. #define PR_LINKER_ARCH    "solaris"
  27. #define _PR_SI_SYSNAME    "SOLARIS"
  28. #define _PR_SI_ARCHITECTURE    "sparc"
  29. #define PR_DLL_SUFFIX        ".so"
  30.  
  31. #define _PR_VMBASE        0x30000000
  32. #define _PR_STACK_VMBASE    0x50000000
  33. #define _MD_DEFAULT_STACK_SIZE    (2*65536L)
  34. #define _MD_MMAP_FLAGS          MAP_SHARED
  35.  
  36. #undef  HAVE_STACK_GROWING_UP
  37.  
  38. #ifndef HAVE_WEAK_IO_SYMBOLS
  39. #define    HAVE_WEAK_IO_SYMBOLS
  40. #endif
  41.  
  42. #undef    HAVE_WEAK_MALLOC_SYMBOLS
  43. #define    HAVE_DLL
  44. #define    USE_DLFCN
  45. #define NEED_STRFTIME_LOCK
  46.  
  47. #ifdef _PR_LOCAL_THREADS_ONLY
  48. #undef _PR_HAVE_ATOMIC_OPS
  49. #else
  50. #define _PR_HAVE_ATOMIC_OPS
  51. #define _PR_HAVE_ATOMIC_CAS
  52. #endif
  53.  
  54. #define _PR_POLL_AVAILABLE
  55. #define _PR_USE_POLL
  56. #define _PR_STAT_HAS_ST_ATIM
  57.  
  58. #include "prinrval.h"
  59. PR_EXTERN(PRIntervalTime) _MD_Solaris_GetInterval(void);
  60. #define _MD_GET_INTERVAL                  _MD_Solaris_GetInterval
  61. PR_EXTERN(PRIntervalTime) _MD_Solaris_TicksPerSecond(void);
  62. #define _MD_INTERVAL_PER_SEC              _MD_Solaris_TicksPerSecond
  63.  
  64. #if defined(_PR_HAVE_ATOMIC_OPS)
  65. /*
  66. ** Atomic Operations
  67. */
  68. #define _MD_INIT_ATOMIC()
  69.  
  70. PR_EXTERN(PRInt32) _MD_AtomicIncrement(PRInt32 *val);
  71. #define _MD_ATOMIC_INCREMENT _MD_AtomicIncrement
  72.  
  73. PR_EXTERN(PRInt32) _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val);
  74. #define _MD_ATOMIC_ADD _MD_AtomicAdd
  75.  
  76. PR_EXTERN(PRInt32) _MD_AtomicDecrement(PRInt32 *val);
  77. #define _MD_ATOMIC_DECREMENT _MD_AtomicDecrement
  78.  
  79. PR_EXTERN(PRInt32) _MD_AtomicSet(PRInt32 *val, PRInt32 newval);
  80. #define _MD_ATOMIC_SET _MD_AtomicSet
  81. #endif /* _PR_HAVE_ATOMIC_OPS */
  82.  
  83. #if defined(_PR_PTHREADS)
  84.  
  85. PR_EXTERN(void)        _MD_EarlyInit(void);
  86.  
  87. #define _MD_EARLY_INIT        _MD_EarlyInit
  88. #define _MD_FINAL_INIT        _PR_UnixInit
  89.  
  90. #elif defined(_PR_GLOBAL_THREADS_ONLY)
  91.  
  92. #include "prthread.h"
  93.  
  94. #include <ucontext.h>
  95.  
  96. /*
  97. ** Iinitialization Related definitions
  98. */
  99.  
  100. PR_EXTERN(void)        _MD_EarlyInit(void);
  101.  
  102. #define _MD_EARLY_INIT        _MD_EarlyInit
  103. #define _MD_FINAL_INIT        _PR_UnixInit
  104.  
  105. #define _MD_GET_SP(threadp)    threadp->md.sp
  106.  
  107. /*
  108. ** Clean-up the thread machine dependent data structure
  109. */
  110. #define    _MD_INIT_THREAD                _MD_InitializeThread
  111. #define    _MD_INIT_ATTACHED_THREAD    _MD_InitializeThread
  112.  
  113. PR_EXTERN(PRStatus) _MD_CreateThread(PRThread *thread, 
  114.                     void (*start)(void *), 
  115.                     PRThreadPriority priority,
  116.                     PRThreadScope scope, 
  117.                     PRThreadState state, 
  118.                     PRUint32 stackSize);
  119. #define _MD_CREATE_THREAD _MD_CreateThread
  120.  
  121. #define    _PR_CONTEXT_TYPE    ucontext_t
  122.  
  123. #define CONTEXT(_thread) (&(_thread)->md.context)
  124.  
  125. #include <thread.h>
  126. #include <sys/lwp.h>
  127. #include <synch.h>
  128.  
  129. extern struct PRLock *_pr_schedLock;
  130.  
  131. /*
  132. ** Thread Local Storage 
  133. */
  134.  
  135. #define THREAD_KEY_T thread_key_t
  136.  
  137. extern struct PRThread *_pr_current_thread_tls();
  138. extern struct _PRCPU *_pr_current_cpu_tls();
  139. extern struct PRThread *_pr_last_thread_tls();
  140.  
  141. extern THREAD_KEY_T threadid_key;
  142. extern THREAD_KEY_T cpuid_key;
  143. extern THREAD_KEY_T last_thread_key;
  144.  
  145. #define _MD_CURRENT_THREAD() _pr_current_thread_tls()
  146. #define _MD_CURRENT_CPU() _pr_current_cpu_tls()
  147. #define _MD_LAST_THREAD() _pr_last_thread_tls()
  148.     
  149. #define _MD_SET_CURRENT_THREAD(newval)             \
  150.     PR_BEGIN_MACRO                    \
  151.     thr_setspecific(threadid_key, (void *)newval);    \
  152.     PR_END_MACRO
  153.  
  154. #define _MD_SET_CURRENT_CPU(newval)             \
  155.     PR_BEGIN_MACRO                    \
  156.     thr_setspecific(cpuid_key, (void *)newval);    \
  157.     PR_END_MACRO
  158.  
  159. #define _MD_SET_LAST_THREAD(newval)                 \
  160.     PR_BEGIN_MACRO                        \
  161.     thr_setspecific(last_thread_key, (void *)newval);    \
  162.     PR_END_MACRO
  163.     
  164. #define    _MD_CLEAN_THREAD(_thread)    _MD_cleanup_thread(_thread)
  165. extern void _MD_exit_thread(PRThread *thread);
  166. #define _MD_EXIT_THREAD(thread)        _MD_exit_thread(thread)
  167.  
  168. #define    _MD_SUSPEND_THREAD(thread)    _MD_Suspend(thread)
  169. #define    _MD_RESUME_THREAD(thread)    thr_continue((thread)->md.handle)
  170.  
  171. /* XXXX Needs to be defined - Prashant */
  172. #define _MD_SUSPEND_CPU(cpu)
  173. #define _MD_RESUME_CPU(cpu)
  174.  
  175. extern void _MD_Begin_SuspendAll(void);
  176. extern void _MD_End_SuspendAll(void);
  177. extern void _MD_End_ResumeAll(void);
  178. #define _MD_BEGIN_SUSPEND_ALL()        _MD_Begin_SuspendAll()
  179. #define _MD_BEGIN_RESUME_ALL()        
  180. #define    _MD_END_SUSPEND_ALL()        _MD_End_SuspendAll()
  181. #define    _MD_END_RESUME_ALL()        _MD_End_ResumeAll()
  182.  
  183. #define _MD_INIT_LOCKS()
  184. #define _MD_NEW_LOCK(md_lockp) (mutex_init(&((md_lockp)->lock),USYNC_THREAD,NULL) ? PR_FAILURE : PR_SUCCESS)
  185. #define _MD_FREE_LOCK(md_lockp) mutex_destroy(&((md_lockp)->lock))
  186. #define _MD_UNLOCK(md_lockp) mutex_unlock(&((md_lockp)->lock))
  187. #define _MD_TEST_AND_LOCK(md_lockp) mutex_trylock(&((md_lockp)->lock))
  188. struct _MDLock;
  189. PR_EXTERN(void) _MD_lock(struct _MDLock *md_lock);
  190. #undef PROFILE_LOCKS
  191. #ifndef PROFILE_LOCKS
  192. #define _MD_LOCK(md_lockp) _MD_lock(md_lockp)
  193. #else
  194. #define _MD_LOCK(md_lockp)                 \
  195.     PR_BEGIN_MACRO \
  196.     int rv = _MD_TEST_AND_LOCK(md_lockp); \
  197.     if (rv == 0) { \
  198.         (md_lockp)->hitcount++; \
  199.     } else { \
  200.         (md_lockp)->misscount++; \
  201.         _MD_lock(md_lockp); \
  202.     } \
  203.     PR_END_MACRO
  204. #endif
  205.  
  206. #define _PR_LOCK_HEAP() if (_pr_heapLock) _MD_LOCK(&_pr_heapLock->md)
  207. #define _PR_UNLOCK_HEAP() if (_pr_heapLock) _MD_UNLOCK(&_pr_heapLock->md)
  208.  
  209. #define _MD_ATTACH_THREAD(threadp)
  210.  
  211.  
  212. #define THR_KEYCREATE thr_keycreate
  213. #define THR_SELF thr_self
  214. #define _MD_NEW_CV(condp) cond_init(&((condp)->cv), USYNC_THREAD, 0)
  215. #define COND_WAIT(condp, mutexp) cond_wait(condp, mutexp)
  216. #define COND_TIMEDWAIT(condp, mutexp, tspec) \
  217.                                      cond_timedwait(condp, mutexp, tspec)
  218. #define _MD_NOTIFY_CV(condp, lockp) cond_signal(&((condp)->cv))
  219. #define _MD_NOTIFYALL_CV(condp,unused) cond_broadcast(&((condp)->cv))    
  220. #define _MD_FREE_CV(condp) cond_destroy(&((condp)->cv))
  221. #define _MD_YIELD() thr_yield()
  222. #include <time.h>
  223. /* 
  224.  * Because clock_gettime() on Solaris/x86 2.4 always generates a
  225.  * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(),
  226.  * which is implemented using gettimeofday().
  227.  */
  228. #if defined(i386) && defined(SOLARIS2_4)
  229. extern int _pr_solx86_clock_gettime(clockid_t clock_id, struct timespec *tp);
  230. #define GETTIME(tt) _pr_solx86_clock_gettime(CLOCK_REALTIME, (tt))
  231. #else
  232. #define GETTIME(tt) clock_gettime(CLOCK_REALTIME, (tt))
  233. #endif  /* i386 && SOLARIS2_4 */
  234.  
  235. #define MUTEX_T mutex_t
  236. #define COND_T cond_t
  237.  
  238. #define _MD_NEW_SEM(md_semp,_val)  sema_init(&((md_semp)->sem),_val,USYNC_THREAD,NULL)
  239. #define _MD_DESTROY_SEM(md_semp) sema_destroy(&((md_semp)->sem))
  240. #define _MD_WAIT_SEM(md_semp) sema_wait(&((md_semp)->sem))
  241. #define _MD_POST_SEM(md_semp) sema_post(&((md_semp)->sem))
  242.  
  243. #define _MD_SAVE_ERRNO(_thread)
  244. #define _MD_RESTORE_ERRNO(_thread)
  245. #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
  246.  
  247. extern struct _MDLock _pr_ioq_lock;
  248. #define _MD_IOQ_LOCK()        _MD_LOCK(&_pr_ioq_lock)
  249. #define _MD_IOQ_UNLOCK()    _MD_UNLOCK(&_pr_ioq_lock)
  250.  
  251. extern PRStatus _MD_wait(struct PRThread *, PRIntervalTime timeout);
  252. #define _MD_WAIT _MD_wait
  253.  
  254. extern PRStatus _MD_WakeupWaiter(struct PRThread *);
  255. #define _MD_WAKEUP_WAITER _MD_WakeupWaiter
  256.  
  257. PR_EXTERN(void) _MD_InitIO(void);
  258. #define _MD_INIT_IO _MD_InitIO
  259.  
  260. #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)
  261. #define _MD_SWITCH_CONTEXT(_thread)
  262. #define _MD_RESTORE_CONTEXT(_newThread)
  263.  
  264. struct _MDLock {
  265.     MUTEX_T lock;
  266. #ifdef PROFILE_LOCKS
  267.     PRInt32 hitcount;
  268.     PRInt32 misscount;
  269. #endif
  270. };
  271.  
  272. struct _MDCVar {
  273.     COND_T cv;
  274. };
  275.  
  276. struct _MDSemaphore {
  277.     sema_t sem;
  278. };
  279.  
  280. struct _MDThread {
  281.     _PR_CONTEXT_TYPE context;
  282.     thread_t handle;
  283.     lwpid_t lwpid;
  284.     uint_t sp;        /* stack pointer */
  285.     uint_t threadID;    /* ptr to solaris-internal thread id structures */
  286.     struct _MDSemaphore waiter_sem;
  287. };
  288.  
  289. struct _MDThreadStack {
  290.     PRInt8 notused;
  291. };
  292.  
  293. struct _MDSegment {
  294.     PRInt8 notused;
  295. };
  296.  
  297. /*
  298.  * md-specific cpu structure field, common to all Unix platforms
  299.  */
  300. #define _PR_MD_MAX_OSFD FD_SETSIZE
  301.  
  302. struct _MDCPU_Unix {
  303.     PRCList ioQ;
  304.     PRUint32 ioq_timeout;
  305.     PRInt32 ioq_max_osfd;
  306.     PRInt32 ioq_osfd_cnt;
  307. #ifndef _PR_USE_POLL
  308.     fd_set fd_read_set, fd_write_set, fd_exception_set;
  309.     PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
  310.                 fd_exception_cnt[_PR_MD_MAX_OSFD];
  311. #else
  312.     struct pollfd *ioq_pollfds;
  313.     int ioq_pollfds_size;
  314. #endif    /* _PR_USE_POLL */
  315. };
  316.  
  317. #define _PR_IOQ(_cpu)            ((_cpu)->md.md_unix.ioQ)
  318. #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
  319. #define _PR_FD_READ_SET(_cpu)        ((_cpu)->md.md_unix.fd_read_set)
  320. #define _PR_FD_READ_CNT(_cpu)        ((_cpu)->md.md_unix.fd_read_cnt)
  321. #define _PR_FD_WRITE_SET(_cpu)        ((_cpu)->md.md_unix.fd_write_set)
  322. #define _PR_FD_WRITE_CNT(_cpu)        ((_cpu)->md.md_unix.fd_write_cnt)
  323. #define _PR_FD_EXCEPTION_SET(_cpu)    ((_cpu)->md.md_unix.fd_exception_set)
  324. #define _PR_FD_EXCEPTION_CNT(_cpu)    ((_cpu)->md.md_unix.fd_exception_cnt)
  325. #define _PR_IOQ_TIMEOUT(_cpu)        ((_cpu)->md.md_unix.ioq_timeout)
  326. #define _PR_IOQ_MAX_OSFD(_cpu)        ((_cpu)->md.md_unix.ioq_max_osfd)
  327. #define _PR_IOQ_OSFD_CNT(_cpu)        ((_cpu)->md.md_unix.ioq_osfd_cnt)
  328. #define _PR_IOQ_POLLFDS(_cpu)        ((_cpu)->md.md_unix.ioq_pollfds)
  329. #define _PR_IOQ_POLLFDS_SIZE(_cpu)    ((_cpu)->md.md_unix.ioq_pollfds_size)
  330.  
  331. #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu)    32
  332.  
  333.  
  334. struct _MDCPU {
  335.     struct _MDCPU_Unix md_unix;
  336. };
  337.  
  338. /* The following defines the unwrapped versions of select() and poll(). */
  339. extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
  340.     fd_set *exceptfds, struct timeval *timeout);
  341. #define _MD_SELECT    _select
  342.  
  343. #include <poll.h>
  344. #define _MD_POLL _poll
  345. extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
  346.  
  347. PR_BEGIN_EXTERN_C
  348.  
  349. /*
  350. ** Missing function prototypes
  351. */
  352. extern int gethostname (char *name, int namelen);
  353.  
  354. PR_END_EXTERN_C
  355.  
  356. #else /* _PR_GLOBAL_THREADS_ONLY */
  357.  
  358. /*
  359.  * LOCAL_THREADS_ONLY implementation on Solaris
  360.  */
  361.  
  362. #include "prthread.h"
  363.  
  364. #include <errno.h>
  365. #include <ucontext.h>
  366. #include <sys/stack.h>
  367. #include <synch.h>
  368.  
  369. /*
  370. ** Iinitialization Related definitions
  371. */
  372.  
  373. PR_EXTERN(void)                _MD_EarlyInit(void);
  374. PR_EXTERN(void)                _MD_SolarisInit();
  375. #define _MD_EARLY_INIT        _MD_EarlyInit
  376. #define _MD_FINAL_INIT        _MD_SolarisInit
  377. #define    _MD_INIT_THREAD        _MD_InitializeThread
  378.  
  379. #ifdef USE_SETJMP
  380.  
  381. #include <setjmp.h>
  382.  
  383. #define _PR_CONTEXT_TYPE    jmp_buf
  384.  
  385. #ifdef sparc
  386. #define _MD_GET_SP(_t)        (_t)->md.context[2]
  387. #else
  388. #define _MD_GET_SP(_t)        (_t)->md.context[4]
  389. #endif
  390.  
  391. #define PR_NUM_GCREGS        _JBLEN
  392. #define CONTEXT(_thread)    (_thread)->md.context
  393.  
  394. #else  /* ! USE_SETJMP */
  395.  
  396. #ifdef sparc
  397. #define    _PR_CONTEXT_TYPE    ucontext_t
  398. #define _MD_GET_SP(_t)        (_t)->md.context.uc_mcontext.gregs[REG_SP]
  399. /*
  400. ** Sparc's use register windows. the _MD_GetRegisters for the sparc's
  401. ** doesn't actually store anything into the argument buffer; instead the
  402. ** register windows are homed to the stack. I assume that the stack
  403. ** always has room for the registers to spill to...
  404. */
  405. #define PR_NUM_GCREGS        0
  406. #else
  407. #define _PR_CONTEXT_TYPE    unsigned int edi; sigset_t oldMask, blockMask; ucontext_t
  408. #define _MD_GET_SP(_t)        (_t)->md.context.uc_mcontext.gregs[USP]
  409. #define PR_NUM_GCREGS        _JBLEN
  410. #endif
  411.  
  412. #define CONTEXT(_thread)    (&(_thread)->md.context)
  413.  
  414. #endif /* ! USE_SETJMP */
  415.  
  416. #include <time.h>
  417. /* 
  418.  * Because clock_gettime() on Solaris/x86 always generates a
  419.  * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(),
  420.  * which is implemented using gettimeofday().
  421.  */
  422. #ifdef i386
  423. #define GETTIME(tt) _pr_solx86_clock_gettime(CLOCK_REALTIME, (tt))
  424. #else
  425. #define GETTIME(tt) clock_gettime(CLOCK_REALTIME, (tt))
  426. #endif  /* i386 */
  427.  
  428. #define _MD_SAVE_ERRNO(_thread)            (_thread)->md.errcode = errno;
  429. #define _MD_RESTORE_ERRNO(_thread)        errno = (_thread)->md.errcode;
  430.  
  431. #ifdef sparc
  432.  
  433. #ifdef USE_SETJMP
  434. #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)          \
  435.     PR_BEGIN_MACRO                      \
  436.     int *context = (_thread)->md.context;          \
  437.     *status = PR_TRUE;              \
  438.     (void) setjmp(context);                  \
  439.     (_thread)->md.context[1] = (int) ((_sp) - 64); \
  440.     (_thread)->md.context[2] = (int) _main;          \
  441.     (_thread)->md.context[3] = (int) _main + 4; \
  442.     _thread->no_sched = 0; \
  443.     PR_END_MACRO
  444.  
  445. #define _MD_SWITCH_CONTEXT(_thread)    \
  446.     if (!setjmp(CONTEXT(_thread))) { \
  447.     _MD_SAVE_ERRNO(_thread)    \
  448.     _MD_SET_LAST_THREAD(_thread);     \
  449.     _MD_SET_CURRENT_THREAD(_thread);     \
  450.     _PR_Schedule();             \
  451.     }
  452.  
  453. #define _MD_RESTORE_CONTEXT(_newThread)        \
  454. {                     \
  455.     _MD_RESTORE_ERRNO(_newThread)        \
  456.     _MD_SET_CURRENT_THREAD(_newThread); \
  457.     longjmp(CONTEXT(_newThread), 1);    \
  458. }
  459.  
  460. #else
  461. /*
  462. ** Initialize the thread context preparing it to execute _main.
  463. */
  464. #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)                    \
  465.     PR_BEGIN_MACRO                                                          \
  466.     ucontext_t *uc = CONTEXT(_thread);                                    \
  467.     *status = PR_TRUE;                                                    \
  468.     getcontext(uc);                                                        \
  469.     uc->uc_stack.ss_sp = (char *) ((unsigned long)(_sp - WINDOWSIZE - SA(MINFRAME)) & 0xfffffff8);    \
  470.     uc->uc_stack.ss_size = _thread->stack->stackSize;                     \
  471.     uc->uc_stack.ss_flags = 0;                 /* ? */                        \
  472.     uc->uc_mcontext.gregs[REG_SP] = (unsigned int) uc->uc_stack.ss_sp;    \
  473.     uc->uc_mcontext.gregs[REG_PC] = (unsigned int) _main;                \
  474.     uc->uc_mcontext.gregs[REG_nPC] = (unsigned int) ((char*)_main)+4;    \
  475.     uc->uc_flags = UC_ALL;                                                \
  476.     _thread->no_sched = 0;                                                \
  477.     PR_END_MACRO
  478.  
  479. /*
  480. ** Switch away from the current thread context by saving its state and
  481. ** calling the thread scheduler. Reload cpu when we come back from the
  482. ** context switch because it might have changed.
  483. */
  484. #define _MD_SWITCH_CONTEXT(_thread)                    \
  485.     PR_BEGIN_MACRO                                     \
  486.         if (!getcontext(CONTEXT(_thread))) {         \
  487.             _MD_SAVE_ERRNO(_thread);                \
  488.             _MD_SET_LAST_THREAD(_thread);             \
  489.             _PR_Schedule();                             \
  490.         }                                             \
  491.     PR_END_MACRO
  492.  
  493. /*
  494. ** Restore a thread context that was saved by _MD_SWITCH_CONTEXT or
  495. ** initialized by _MD_INIT_CONTEXT.
  496. */
  497. #define _MD_RESTORE_CONTEXT(_newThread)                        \
  498.     PR_BEGIN_MACRO                                            \
  499.         ucontext_t *uc = CONTEXT(_newThread);                 \
  500.         uc->uc_mcontext.gregs[11] = 1;                         \
  501.         _MD_RESTORE_ERRNO(_newThread);                        \
  502.         _MD_SET_CURRENT_THREAD(_newThread);                 \
  503.         setcontext(uc);                                           \
  504.     PR_END_MACRO
  505. #endif
  506.  
  507. #else  /* x86 solaris */
  508.  
  509. #ifdef USE_SETJMP
  510.  
  511. #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
  512.     PR_BEGIN_MACRO \
  513.     *status = PR_TRUE; \
  514.     if (setjmp(CONTEXT(_thread))) _main(); \
  515.     _MD_GET_SP(_thread) = (int) ((_sp) - 64); \
  516.     PR_END_MACRO
  517.  
  518. #define _MD_SWITCH_CONTEXT(_thread) \
  519.     if (!setjmp(CONTEXT(_thread))) { \
  520.         _MD_SAVE_ERRNO(_thread) \
  521.         _PR_Schedule();    \
  522.     }
  523.  
  524. #define _MD_RESTORE_CONTEXT(_newThread) \
  525. { \
  526.     _MD_RESTORE_ERRNO(_newThread) \
  527.     _MD_SET_CURRENT_THREAD(_newThread); \
  528.     longjmp(CONTEXT(_newThread), 1); \
  529. }
  530.  
  531. #else /* USE_SETJMP */
  532.  
  533. #define WINDOWSIZE        0
  534.  
  535. int getedi(void);
  536. void setedi(int);
  537.  
  538. #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)          \
  539.     PR_BEGIN_MACRO                    \
  540.     ucontext_t *uc = CONTEXT(_thread);        \
  541.         *status = PR_TRUE;              \
  542.     getcontext(uc);                    \
  543.     /* Force sp to be double aligned! */        \
  544.         uc->uc_mcontext.gregs[USP] = (int) ((unsigned long)(_sp - WINDOWSIZE - SA(MINFRAME)) & 0xfffffff8);    \
  545.     uc->uc_mcontext.gregs[PC] = (int) _main;    \
  546.     (_thread)->no_sched = 0; \
  547.     PR_END_MACRO
  548.  
  549. /* getcontext() may return 1, contrary to what the man page says */
  550. #define _MD_SWITCH_CONTEXT(_thread)            \
  551.     PR_BEGIN_MACRO                    \
  552.     ucontext_t *uc = CONTEXT(_thread);        \
  553.     PR_ASSERT(_thread->no_sched);            \
  554.     sigfillset(&((_thread)->md.blockMask));        \
  555.     sigprocmask(SIG_BLOCK, &((_thread)->md.blockMask),    \
  556.         &((_thread)->md.oldMask));        \
  557.     (_thread)->md.edi = getedi();            \
  558.     if (! getcontext(uc)) {                \
  559.         sigprocmask(SIG_SETMASK, &((_thread)->md.oldMask), NULL); \
  560.         uc->uc_mcontext.gregs[EDI] = (_thread)->md.edi;    \
  561.         _MD_SAVE_ERRNO(_thread)            \
  562.             _MD_SET_LAST_THREAD(_thread);            \
  563.         _PR_Schedule();                \
  564.     } else {                    \
  565.         sigprocmask(SIG_SETMASK, &((_thread)->md.oldMask), NULL); \
  566.         setedi((_thread)->md.edi);        \
  567.         PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \
  568.         _MD_LAST_THREAD()->no_sched = 0;    \
  569.     }                        \
  570.     PR_END_MACRO
  571.  
  572. /*
  573. ** Restore a thread context, saved by _PR_SWITCH_CONTEXT
  574. */
  575. #define _MD_RESTORE_CONTEXT(_newthread)            \
  576.     PR_BEGIN_MACRO                    \
  577.     ucontext_t *uc = CONTEXT(_newthread);        \
  578.     uc->uc_mcontext.gregs[EAX] = 1;            \
  579.     _MD_RESTORE_ERRNO(_newthread)              \
  580.     _MD_SET_CURRENT_THREAD(_newthread);        \
  581.     (_newthread)->no_sched = 1;            \
  582.     setcontext(uc);                    \
  583.     PR_END_MACRO
  584. #endif /* USE_SETJMP */
  585.  
  586. #endif /* sparc */
  587.  
  588. struct _MDLock {
  589.     PRInt8 notused;
  590. };
  591.  
  592. struct _MDCVar {
  593.     PRInt8 notused;
  594. };
  595.  
  596. struct _MDSemaphore {
  597.     PRInt8 notused;
  598. };
  599.  
  600. struct _MDThread {
  601.     _PR_CONTEXT_TYPE context;
  602.     int errcode;
  603.     int id;
  604. };
  605.  
  606. struct _MDThreadStack {
  607.     PRInt8 notused;
  608. };
  609.  
  610. struct _MDSegment {
  611.     PRInt8 notused;
  612. };
  613.  
  614. /*
  615.  * md-specific cpu structure field
  616.  */
  617. #define _PR_MD_MAX_OSFD FD_SETSIZE
  618.  
  619. struct _MDCPU_Unix {
  620.     PRCList ioQ;
  621.     PRUint32 ioq_timeout;
  622.     PRInt32 ioq_max_osfd;
  623.     PRInt32 ioq_osfd_cnt;
  624. #ifndef _PR_USE_POLL
  625.     fd_set fd_read_set, fd_write_set, fd_exception_set;
  626.     PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
  627.                 fd_exception_cnt[_PR_MD_MAX_OSFD];
  628. #else
  629.     struct pollfd *ioq_pollfds;
  630.     int ioq_pollfds_size;
  631. #endif    /* _PR_USE_POLL */
  632. };
  633.  
  634. #define _PR_IOQ(_cpu)            ((_cpu)->md.md_unix.ioQ)
  635. #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
  636. #define _PR_FD_READ_SET(_cpu)        ((_cpu)->md.md_unix.fd_read_set)
  637. #define _PR_FD_READ_CNT(_cpu)        ((_cpu)->md.md_unix.fd_read_cnt)
  638. #define _PR_FD_WRITE_SET(_cpu)        ((_cpu)->md.md_unix.fd_write_set)
  639. #define _PR_FD_WRITE_CNT(_cpu)        ((_cpu)->md.md_unix.fd_write_cnt)
  640. #define _PR_FD_EXCEPTION_SET(_cpu)    ((_cpu)->md.md_unix.fd_exception_set)
  641. #define _PR_FD_EXCEPTION_CNT(_cpu)    ((_cpu)->md.md_unix.fd_exception_cnt)
  642. #define _PR_IOQ_TIMEOUT(_cpu)        ((_cpu)->md.md_unix.ioq_timeout)
  643. #define _PR_IOQ_MAX_OSFD(_cpu)        ((_cpu)->md.md_unix.ioq_max_osfd)
  644. #define _PR_IOQ_OSFD_CNT(_cpu)        ((_cpu)->md.md_unix.ioq_osfd_cnt)
  645. #define _PR_IOQ_POLLFDS(_cpu)        ((_cpu)->md.md_unix.ioq_pollfds)
  646. #define _PR_IOQ_POLLFDS_SIZE(_cpu)    ((_cpu)->md.md_unix.ioq_pollfds_size)
  647.  
  648. #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu)    32
  649.  
  650. struct _MDCPU {
  651.     struct _MDCPU_Unix md_unix;
  652. };
  653.  
  654. #ifndef _PR_PTHREADS
  655. #define _MD_INIT_LOCKS()
  656. #endif
  657. #define _MD_NEW_LOCK(lock)                PR_SUCCESS
  658. #define _MD_FREE_LOCK(lock)
  659. #define _MD_LOCK(lock)
  660. #define _MD_UNLOCK(lock)
  661. #define _MD_INIT_IO()
  662. #define _MD_IOQ_LOCK()
  663. #define _MD_IOQ_UNLOCK()
  664.  
  665. #define _MD_INIT_RUNNING_CPU(cpu)        _MD_unix_init_running_cpu(cpu)
  666. #define _MD_INIT_THREAD                    _MD_InitializeThread
  667. #define _MD_EXIT_THREAD(thread)
  668. #define _MD_SUSPEND_THREAD(thread)
  669. #define _MD_RESUME_THREAD(thread)
  670. #define _MD_CLEAN_THREAD(_thread)
  671.  
  672. extern PRStatus _MD_WAIT(struct PRThread *, PRIntervalTime timeout);
  673. extern PRStatus _MD_WAKEUP_WAITER(struct PRThread *);
  674. extern void     _MD_YIELD(void);
  675. extern PRStatus _MD_InitializeThread(PRThread *thread);
  676. extern void     _MD_SET_PRIORITY(struct _MDThread *thread,
  677.     PRThreadPriority newPri);
  678. extern PRStatus _MD_CREATE_THREAD(PRThread *thread, void (*start) (void *),
  679.     PRThreadPriority priority, PRThreadScope scope, PRThreadState state,
  680.         PRUint32 stackSize);
  681.  
  682. PR_EXTERN(PRIntervalTime)                _MD_Solaris_GetInterval(void);
  683. #define _MD_GET_INTERVAL                _MD_Solaris_GetInterval
  684. PR_EXTERN(PRIntervalTime)                _MD_Solaris_TicksPerSecond(void);
  685. #define _MD_INTERVAL_PER_SEC            _MD_Solaris_TicksPerSecond
  686.  
  687. /* The following defines the unwrapped versions of select() and poll(). */
  688. extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
  689.     fd_set *exceptfds, struct timeval *timeout);
  690. #define _MD_SELECT    _select
  691.  
  692. #include <stropts.h>
  693. #include <poll.h>
  694. #define _MD_POLL _poll
  695. extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
  696.  
  697. PR_BEGIN_EXTERN_C
  698.  
  699. /*
  700. ** Missing function prototypes
  701. */
  702. extern int gethostname (char *name, int namelen);
  703.  
  704. PR_END_EXTERN_C
  705.  
  706. #endif /* _PR_GLOBAL_THREADS_ONLY */
  707.  
  708. #endif /* nspr_solaris_defs_h___ */
  709.  
  710.