Back to index

lightning-sunbird  0.9+nobinonly
_solaris.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef nspr_solaris_defs_h___
00039 #define nspr_solaris_defs_h___
00040 
00041 /*
00042  * Internal configuration macros
00043  */
00044 
00045 #define PR_LINKER_ARCH      "solaris"
00046 #define _PR_SI_SYSNAME      "SOLARIS"
00047 #ifdef sparc
00048 #define _PR_SI_ARCHITECTURE "sparc"
00049 #elif defined(__x86_64)
00050 #define _PR_SI_ARCHITECTURE "x86-64"
00051 #elif defined(i386)
00052 #define _PR_SI_ARCHITECTURE "x86"
00053 #else
00054 #error unknown processor
00055 #endif
00056 #define PR_DLL_SUFFIX              ".so"
00057 
00058 #define _PR_VMBASE          0x30000000
00059 #define _PR_STACK_VMBASE    0x50000000
00060 #define _MD_DEFAULT_STACK_SIZE     (2*65536L)
00061 #define _MD_MMAP_FLAGS          MAP_SHARED
00062 
00063 #undef  HAVE_STACK_GROWING_UP
00064 
00065 #ifndef HAVE_WEAK_IO_SYMBOLS
00066 #define       HAVE_WEAK_IO_SYMBOLS
00067 #endif
00068 
00069 #undef HAVE_WEAK_MALLOC_SYMBOLS
00070 #define       HAVE_DLL
00071 #define       USE_DLFCN
00072 #define NEED_STRFTIME_LOCK
00073 
00074 /*
00075  * Intel x86 has atomic instructions.
00076  *
00077  * Sparc v8 does not have instructions to efficiently implement
00078  * atomic increment/decrement operations.  In the local threads
00079  * only and pthreads versions, we use the default atomic routine
00080  * implementation in pratom.c.  The obsolete global threads only
00081  * version uses a global mutex_t to implement the atomic routines
00082  * in solaris.c, which is actually equivalent to the default
00083  * implementation.
00084  *
00085  * 64-bit Solaris requires sparc v9, which has atomic instructions.
00086  */
00087 #if defined(i386) || defined(_PR_GLOBAL_THREADS_ONLY) || defined(IS_64)
00088 #define _PR_HAVE_ATOMIC_OPS
00089 #endif
00090 
00091 #define _PR_POLL_AVAILABLE
00092 #define _PR_USE_POLL
00093 #define _PR_STAT_HAS_ST_ATIM
00094 #ifdef SOLARIS2_5
00095 #define _PR_HAVE_SYSV_SEMAPHORES
00096 #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
00097 #else
00098 #define _PR_HAVE_POSIX_SEMAPHORES
00099 #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY
00100 #endif
00101 #define _PR_HAVE_GETIPNODEBYNAME
00102 #define _PR_HAVE_GETIPNODEBYADDR
00103 #define _PR_HAVE_GETADDRINFO
00104 #define _PR_INET6_PROBE
00105 #define _PR_ACCEPT_INHERIT_NONBLOCK
00106 #ifdef _PR_INET6
00107 #define _PR_HAVE_INET_NTOP
00108 #else
00109 #define AF_INET6 26
00110 struct addrinfo {
00111     int ai_flags;
00112     int ai_family;
00113     int ai_socktype;
00114     int ai_protocol;
00115     size_t ai_addrlen;
00116     char *ai_canonname;
00117     struct sockaddr *ai_addr;
00118     struct addrinfo *ai_next;
00119 };
00120 #define AI_CANONNAME 0x0010
00121 #define AI_V4MAPPED 0x0001 
00122 #define AI_ALL      0x0002
00123 #define AI_ADDRCONFIG   0x0004
00124 #define _PR_HAVE_MD_SOCKADDR_IN6
00125 /* isomorphic to struct in6_addr on Solaris 8 */
00126 struct _md_in6_addr {
00127     union {
00128         PRUint8  _S6_u8[16];
00129         PRUint32 _S6_u32[4];
00130         PRUint32 __S6_align;
00131     } _S6_un;
00132 };
00133 /* isomorphic to struct sockaddr_in6 on Solaris 8 */
00134 struct _md_sockaddr_in6 {
00135     PRUint16 sin6_family;
00136     PRUint16 sin6_port;
00137     PRUint32 sin6_flowinfo;
00138     struct _md_in6_addr sin6_addr;
00139     PRUint32 sin6_scope_id;
00140     PRUint32 __sin6_src_id;
00141 };
00142 #endif
00143 #if defined(_PR_GLOBAL_THREADS_ONLY) || defined(_PR_PTHREADS)
00144 #define _PR_HAVE_GETHOST_R
00145 #define _PR_HAVE_GETHOST_R_POINTER
00146 #endif
00147 
00148 #include "prinrval.h"
00149 NSPR_API(PRIntervalTime) _MD_Solaris_GetInterval(void);
00150 #define _MD_GET_INTERVAL                  _MD_Solaris_GetInterval
00151 NSPR_API(PRIntervalTime) _MD_Solaris_TicksPerSecond(void);
00152 #define _MD_INTERVAL_PER_SEC              _MD_Solaris_TicksPerSecond
00153 
00154 #if defined(_PR_HAVE_ATOMIC_OPS)
00155 /*
00156 ** Atomic Operations
00157 */
00158 #define _MD_INIT_ATOMIC()
00159 
00160 NSPR_API(PRInt32) _MD_AtomicIncrement(PRInt32 *val);
00161 #define _MD_ATOMIC_INCREMENT _MD_AtomicIncrement
00162 
00163 NSPR_API(PRInt32) _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val);
00164 #define _MD_ATOMIC_ADD _MD_AtomicAdd
00165 
00166 NSPR_API(PRInt32) _MD_AtomicDecrement(PRInt32 *val);
00167 #define _MD_ATOMIC_DECREMENT _MD_AtomicDecrement
00168 
00169 NSPR_API(PRInt32) _MD_AtomicSet(PRInt32 *val, PRInt32 newval);
00170 #define _MD_ATOMIC_SET _MD_AtomicSet
00171 #endif /* _PR_HAVE_ATOMIC_OPS */
00172 
00173 #if defined(_PR_PTHREADS)
00174 
00175 NSPR_API(void)              _MD_EarlyInit(void);
00176 
00177 #define _MD_EARLY_INIT             _MD_EarlyInit
00178 #define _MD_FINAL_INIT             _PR_UnixInit
00179 
00180 #elif defined(_PR_GLOBAL_THREADS_ONLY)
00181 
00182 #include "prthread.h"
00183 
00184 #include <ucontext.h>
00185 
00186 /*
00187 ** Iinitialization Related definitions
00188 */
00189 
00190 NSPR_API(void)              _MD_EarlyInit(void);
00191 
00192 #define _MD_EARLY_INIT             _MD_EarlyInit
00193 #define _MD_FINAL_INIT             _PR_UnixInit
00194 
00195 #define _MD_GET_SP(threadp) threadp->md.sp
00196 
00197 /*
00198 ** Clean-up the thread machine dependent data structure
00199 */
00200 #define       _MD_INIT_THREAD                           _MD_InitializeThread
00201 #define       _MD_INIT_ATTACHED_THREAD    _MD_InitializeThread
00202 
00203 NSPR_API(PRStatus) _MD_CreateThread(PRThread *thread, 
00204                                    void (*start)(void *), 
00205                                    PRThreadPriority priority,
00206                                    PRThreadScope scope, 
00207                                    PRThreadState state, 
00208                                    PRUint32 stackSize);
00209 #define _MD_CREATE_THREAD _MD_CreateThread
00210 
00211 #define       _PR_CONTEXT_TYPE     ucontext_t
00212 
00213 #define CONTEXT(_thread) (&(_thread)->md.context)
00214 
00215 #include <thread.h>
00216 #include <sys/lwp.h>
00217 #include <synch.h>
00218 
00219 extern struct PRLock *_pr_schedLock;
00220 
00221 /*
00222 ** Thread Local Storage 
00223 */
00224 
00225 #define THREAD_KEY_T thread_key_t
00226 
00227 extern struct PRThread *_pr_attached_thread_tls();
00228 extern struct PRThread *_pr_current_thread_tls();
00229 extern struct _PRCPU *_pr_current_cpu_tls();
00230 extern struct PRThread *_pr_last_thread_tls();
00231 
00232 extern THREAD_KEY_T threadid_key;
00233 extern THREAD_KEY_T cpuid_key;
00234 extern THREAD_KEY_T last_thread_key;
00235 
00236 #define _MD_GET_ATTACHED_THREAD() _pr_attached_thread_tls()
00237 #define _MD_CURRENT_THREAD() _pr_current_thread_tls()
00238 #define _MD_CURRENT_CPU() _pr_current_cpu_tls()
00239 #define _MD_LAST_THREAD() _pr_last_thread_tls()
00240        
00241 #define _MD_SET_CURRENT_THREAD(newval)                  \
00242        PR_BEGIN_MACRO                                   \
00243        thr_setspecific(threadid_key, (void *)newval);   \
00244        PR_END_MACRO
00245 
00246 #define _MD_SET_CURRENT_CPU(newval)                     \
00247        PR_BEGIN_MACRO                                   \
00248        thr_setspecific(cpuid_key, (void *)newval);      \
00249        PR_END_MACRO
00250 
00251 #define _MD_SET_LAST_THREAD(newval)                            \
00252        PR_BEGIN_MACRO                                          \
00253        thr_setspecific(last_thread_key, (void *)newval);       \
00254        PR_END_MACRO
00255        
00256 #define       _MD_CLEAN_THREAD(_thread)   _MD_cleanup_thread(_thread)
00257 extern void _MD_exit_thread(PRThread *thread);
00258 #define _MD_EXIT_THREAD(thread)           _MD_exit_thread(thread)
00259 
00260 #define       _MD_SUSPEND_THREAD(thread)  _MD_Suspend(thread)
00261 #define       _MD_RESUME_THREAD(thread)   thr_continue((thread)->md.handle)
00262 
00263 /* XXXX Needs to be defined - Prashant */
00264 #define _MD_SUSPEND_CPU(cpu)
00265 #define _MD_RESUME_CPU(cpu)
00266 
00267 extern void _MD_Begin_SuspendAll(void);
00268 extern void _MD_End_SuspendAll(void);
00269 extern void _MD_End_ResumeAll(void);
00270 #define _MD_BEGIN_SUSPEND_ALL()           _MD_Begin_SuspendAll()
00271 #define _MD_BEGIN_RESUME_ALL()            
00272 #define       _MD_END_SUSPEND_ALL()              _MD_End_SuspendAll()
00273 #define       _MD_END_RESUME_ALL()        _MD_End_ResumeAll()
00274 
00275 #define _MD_INIT_LOCKS()
00276 #define _MD_NEW_LOCK(md_lockp) (mutex_init(&((md_lockp)->lock),USYNC_THREAD,NULL) ? PR_FAILURE : PR_SUCCESS)
00277 #define _MD_FREE_LOCK(md_lockp) mutex_destroy(&((md_lockp)->lock))
00278 #define _MD_UNLOCK(md_lockp) mutex_unlock(&((md_lockp)->lock))
00279 #define _MD_TEST_AND_LOCK(md_lockp) mutex_trylock(&((md_lockp)->lock))
00280 struct _MDLock;
00281 NSPR_API(void) _MD_lock(struct _MDLock *md_lock);
00282 #undef PROFILE_LOCKS
00283 #ifndef PROFILE_LOCKS
00284 #define _MD_LOCK(md_lockp) _MD_lock(md_lockp)
00285 #else
00286 #define _MD_LOCK(md_lockp)                 \
00287     PR_BEGIN_MACRO \
00288     int rv = _MD_TEST_AND_LOCK(md_lockp); \
00289     if (rv == 0) { \
00290         (md_lockp)->hitcount++; \
00291     } else { \
00292         (md_lockp)->misscount++; \
00293         _MD_lock(md_lockp); \
00294     } \
00295     PR_END_MACRO
00296 #endif
00297 
00298 #define _PR_LOCK_HEAP() if (_pr_heapLock) _MD_LOCK(&_pr_heapLock->md)
00299 #define _PR_UNLOCK_HEAP() if (_pr_heapLock) _MD_UNLOCK(&_pr_heapLock->md)
00300 
00301 #define _MD_ATTACH_THREAD(threadp)
00302 
00303 
00304 #define THR_KEYCREATE thr_keycreate
00305 #define THR_SELF thr_self
00306 #define _MD_NEW_CV(condp) cond_init(&((condp)->cv), USYNC_THREAD, 0)
00307 #define COND_WAIT(condp, mutexp) cond_wait(condp, mutexp)
00308 #define COND_TIMEDWAIT(condp, mutexp, tspec) \
00309                                      cond_timedwait(condp, mutexp, tspec)
00310 #define _MD_NOTIFY_CV(condp, lockp) cond_signal(&((condp)->cv))
00311 #define _MD_NOTIFYALL_CV(condp,unused) cond_broadcast(&((condp)->cv)) 
00312 #define _MD_FREE_CV(condp) cond_destroy(&((condp)->cv))
00313 #define _MD_YIELD() thr_yield()
00314 #include <time.h>
00315 /* 
00316  * Because clock_gettime() on Solaris/x86 2.4 always generates a
00317  * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(),
00318  * which is implemented using gettimeofday().
00319  */
00320 #if defined(i386) && defined(SOLARIS2_4)
00321 extern int _pr_solx86_clock_gettime(clockid_t clock_id, struct timespec *tp);
00322 #define GETTIME(tt) _pr_solx86_clock_gettime(CLOCK_REALTIME, (tt))
00323 #else
00324 #define GETTIME(tt) clock_gettime(CLOCK_REALTIME, (tt))
00325 #endif  /* i386 && SOLARIS2_4 */
00326 
00327 #define MUTEX_T mutex_t
00328 #define COND_T cond_t
00329 
00330 #define _MD_NEW_SEM(md_semp,_val)  sema_init(&((md_semp)->sem),_val,USYNC_THREAD,NULL)
00331 #define _MD_DESTROY_SEM(md_semp) sema_destroy(&((md_semp)->sem))
00332 #define _MD_WAIT_SEM(md_semp) sema_wait(&((md_semp)->sem))
00333 #define _MD_POST_SEM(md_semp) sema_post(&((md_semp)->sem))
00334 
00335 #define _MD_SAVE_ERRNO(_thread)
00336 #define _MD_RESTORE_ERRNO(_thread)
00337 #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
00338 
00339 extern struct _MDLock _pr_ioq_lock;
00340 #define _MD_IOQ_LOCK()             _MD_LOCK(&_pr_ioq_lock)
00341 #define _MD_IOQ_UNLOCK()    _MD_UNLOCK(&_pr_ioq_lock)
00342 
00343 extern PRStatus _MD_wait(struct PRThread *, PRIntervalTime timeout);
00344 #define _MD_WAIT _MD_wait
00345 
00346 extern PRStatus _MD_WakeupWaiter(struct PRThread *);
00347 #define _MD_WAKEUP_WAITER _MD_WakeupWaiter
00348 
00349 NSPR_API(void) _MD_InitIO(void);
00350 #define _MD_INIT_IO _MD_InitIO
00351 
00352 #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
00353     PR_BEGIN_MACRO \
00354     *status = PR_TRUE; \
00355     PR_END_MACRO
00356 #define _MD_SWITCH_CONTEXT(_thread)
00357 #define _MD_RESTORE_CONTEXT(_newThread)
00358 
00359 struct _MDLock {
00360     MUTEX_T lock;
00361 #ifdef PROFILE_LOCKS
00362     PRInt32 hitcount;
00363     PRInt32 misscount;
00364 #endif
00365 };
00366 
00367 struct _MDCVar {
00368     COND_T cv;
00369 };
00370 
00371 struct _MDSemaphore {
00372     sema_t sem;
00373 };
00374 
00375 struct _MDThread {
00376     _PR_CONTEXT_TYPE context;
00377     thread_t handle;
00378     lwpid_t lwpid;
00379     uint_t sp;              /* stack pointer */
00380     uint_t threadID; /* ptr to solaris-internal thread id structures */
00381     struct _MDSemaphore waiter_sem;
00382 };
00383 
00384 struct _MDThreadStack {
00385     PRInt8 notused;
00386 };
00387 
00388 struct _MDSegment {
00389     PRInt8 notused;
00390 };
00391 
00392 /*
00393  * md-specific cpu structure field, common to all Unix platforms
00394  */
00395 #define _PR_MD_MAX_OSFD FD_SETSIZE
00396 
00397 struct _MDCPU_Unix {
00398     PRCList ioQ;
00399     PRUint32 ioq_timeout;
00400     PRInt32 ioq_max_osfd;
00401     PRInt32 ioq_osfd_cnt;
00402 #ifndef _PR_USE_POLL
00403     fd_set fd_read_set, fd_write_set, fd_exception_set;
00404     PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
00405                             fd_exception_cnt[_PR_MD_MAX_OSFD];
00406 #else
00407        struct pollfd *ioq_pollfds;
00408        int ioq_pollfds_size;
00409 #endif /* _PR_USE_POLL */
00410 };
00411 
00412 #define _PR_IOQ(_cpu)                     ((_cpu)->md.md_unix.ioQ)
00413 #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
00414 #define _PR_FD_READ_SET(_cpu)             ((_cpu)->md.md_unix.fd_read_set)
00415 #define _PR_FD_READ_CNT(_cpu)             ((_cpu)->md.md_unix.fd_read_cnt)
00416 #define _PR_FD_WRITE_SET(_cpu)            ((_cpu)->md.md_unix.fd_write_set)
00417 #define _PR_FD_WRITE_CNT(_cpu)            ((_cpu)->md.md_unix.fd_write_cnt)
00418 #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
00419 #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
00420 #define _PR_IOQ_TIMEOUT(_cpu)             ((_cpu)->md.md_unix.ioq_timeout)
00421 #define _PR_IOQ_MAX_OSFD(_cpu)            ((_cpu)->md.md_unix.ioq_max_osfd)
00422 #define _PR_IOQ_OSFD_CNT(_cpu)            ((_cpu)->md.md_unix.ioq_osfd_cnt)
00423 #define _PR_IOQ_POLLFDS(_cpu)             ((_cpu)->md.md_unix.ioq_pollfds)
00424 #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
00425 
00426 #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu)    32
00427 
00428 
00429 struct _MDCPU {
00430        struct _MDCPU_Unix md_unix;
00431 };
00432 
00433 /* The following defines the unwrapped versions of select() and poll(). */
00434 extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
00435        fd_set *exceptfds, struct timeval *timeout);
00436 #define _MD_SELECT   _select
00437 
00438 #include <poll.h>
00439 #define _MD_POLL _poll
00440 extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
00441 
00442 PR_BEGIN_EXTERN_C
00443 
00444 /*
00445 ** Missing function prototypes
00446 */
00447 extern int gethostname (char *name, int namelen);
00448 
00449 PR_END_EXTERN_C
00450 
00451 #else /* _PR_GLOBAL_THREADS_ONLY */
00452 
00453 /*
00454  * LOCAL_THREADS_ONLY implementation on Solaris
00455  */
00456 
00457 #include "prthread.h"
00458 
00459 #include <errno.h>
00460 #include <ucontext.h>
00461 #include <sys/stack.h>
00462 #include <synch.h>
00463 
00464 /*
00465 ** Iinitialization Related definitions
00466 */
00467 
00468 NSPR_API(void)                            _MD_EarlyInit(void);
00469 NSPR_API(void)                            _MD_SolarisInit();
00470 #define _MD_EARLY_INIT             _MD_EarlyInit
00471 #define _MD_FINAL_INIT             _MD_SolarisInit
00472 #define       _MD_INIT_THREAD             _MD_InitializeThread
00473 
00474 #ifdef USE_SETJMP
00475 
00476 #include <setjmp.h>
00477 
00478 #define _PR_CONTEXT_TYPE    jmp_buf
00479 
00480 #ifdef sparc
00481 #define _MD_GET_SP(_t)             (_t)->md.context[2]
00482 #else
00483 #define _MD_GET_SP(_t)             (_t)->md.context[4]
00484 #endif
00485 
00486 #define PR_NUM_GCREGS              _JBLEN
00487 #define CONTEXT(_thread)    (_thread)->md.context
00488 
00489 #else  /* ! USE_SETJMP */
00490 
00491 #ifdef sparc
00492 #define       _PR_CONTEXT_TYPE     ucontext_t
00493 #define _MD_GET_SP(_t)             (_t)->md.context.uc_mcontext.gregs[REG_SP]
00494 /*
00495 ** Sparc's use register windows. the _MD_GetRegisters for the sparc's
00496 ** doesn't actually store anything into the argument buffer; instead the
00497 ** register windows are homed to the stack. I assume that the stack
00498 ** always has room for the registers to spill to...
00499 */
00500 #define PR_NUM_GCREGS              0
00501 #else
00502 #define _PR_CONTEXT_TYPE    unsigned int edi; sigset_t oldMask, blockMask; ucontext_t
00503 #define _MD_GET_SP(_t)             (_t)->md.context.uc_mcontext.gregs[USP]
00504 #define PR_NUM_GCREGS              _JBLEN
00505 #endif
00506 
00507 #define CONTEXT(_thread)    (&(_thread)->md.context)
00508 
00509 #endif /* ! USE_SETJMP */
00510 
00511 #include <time.h>
00512 /* 
00513  * Because clock_gettime() on Solaris/x86 always generates a
00514  * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(),
00515  * which is implemented using gettimeofday().
00516  */
00517 #ifdef i386
00518 #define GETTIME(tt) _pr_solx86_clock_gettime(CLOCK_REALTIME, (tt))
00519 #else
00520 #define GETTIME(tt) clock_gettime(CLOCK_REALTIME, (tt))
00521 #endif  /* i386 */
00522 
00523 #define _MD_SAVE_ERRNO(_thread)                  (_thread)->md.errcode = errno;
00524 #define _MD_RESTORE_ERRNO(_thread)        errno = (_thread)->md.errcode;
00525 
00526 #ifdef sparc
00527 
00528 #ifdef USE_SETJMP
00529 #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)         \
00530     PR_BEGIN_MACRO                              \
00531        int *context = (_thread)->md.context;           \
00532     *status = PR_TRUE;              \
00533        (void) setjmp(context);                         \
00534        (_thread)->md.context[1] = (int) ((_sp) - 64); \
00535        (_thread)->md.context[2] = (int) _main;         \
00536        (_thread)->md.context[3] = (int) _main + 4; \
00537     _thread->no_sched = 0; \
00538     PR_END_MACRO
00539 
00540 #define _MD_SWITCH_CONTEXT(_thread)    \
00541     if (!setjmp(CONTEXT(_thread))) { \
00542        _MD_SAVE_ERRNO(_thread)    \
00543        _MD_SET_LAST_THREAD(_thread);       \
00544     _MD_SET_CURRENT_THREAD(_thread);       \
00545        _PR_Schedule();                  \
00546     }
00547 
00548 #define _MD_RESTORE_CONTEXT(_newThread)       \
00549 {                                \
00550        _MD_RESTORE_ERRNO(_newThread)          \
00551        _MD_SET_CURRENT_THREAD(_newThread); \
00552     longjmp(CONTEXT(_newThread), 1);    \
00553 }
00554 
00555 #else
00556 /*
00557 ** Initialize the thread context preparing it to execute _main.
00558 */
00559 #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)                               \
00560     PR_BEGIN_MACRO                                                                                       \
00561     ucontext_t *uc = CONTEXT(_thread);                                                            \
00562     *status = PR_TRUE;                                                                                          \
00563     getcontext(uc);                                                                                             \
00564     uc->uc_stack.ss_sp = (char *) ((unsigned long)(_sp - WINDOWSIZE - SA(MINFRAME)) & 0xfffffff8);       \
00565     uc->uc_stack.ss_size = _thread->stack->stackSize;                               \
00566     uc->uc_stack.ss_flags = 0;                          /* ? */                                   \
00567     uc->uc_mcontext.gregs[REG_SP] = (unsigned int) uc->uc_stack.ss_sp;       \
00568     uc->uc_mcontext.gregs[REG_PC] = (unsigned int) _main;                           \
00569     uc->uc_mcontext.gregs[REG_nPC] = (unsigned int) ((char*)_main)+4; \
00570     uc->uc_flags = UC_ALL;                                                                               \
00571     _thread->no_sched = 0;                                                                               \
00572     PR_END_MACRO
00573 
00574 /*
00575 ** Switch away from the current thread context by saving its state and
00576 ** calling the thread scheduler. Reload cpu when we come back from the
00577 ** context switch because it might have changed.
00578 */
00579 #define _MD_SWITCH_CONTEXT(_thread)                            \
00580     PR_BEGIN_MACRO                                             \
00581               if (!getcontext(CONTEXT(_thread))) {             \
00582                      _MD_SAVE_ERRNO(_thread);                         \
00583                      _MD_SET_LAST_THREAD(_thread);                    \
00584                      _PR_Schedule();                                                \
00585               }                                                                            \
00586     PR_END_MACRO
00587 
00588 /*
00589 ** Restore a thread context that was saved by _MD_SWITCH_CONTEXT or
00590 ** initialized by _MD_INIT_CONTEXT.
00591 */
00592 #define _MD_RESTORE_CONTEXT(_newThread)                               \
00593     PR_BEGIN_MACRO                                                                  \
00594        ucontext_t *uc = CONTEXT(_newThread);                          \
00595        uc->uc_mcontext.gregs[11] = 1;                                        \
00596               _MD_RESTORE_ERRNO(_newThread);                                 \
00597               _MD_SET_CURRENT_THREAD(_newThread);                            \
00598        setcontext(uc);                                                                     \
00599     PR_END_MACRO
00600 #endif
00601 
00602 #else  /* x86 solaris */
00603 
00604 #ifdef USE_SETJMP
00605 
00606 #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
00607     PR_BEGIN_MACRO \
00608     *status = PR_TRUE; \
00609     if (setjmp(CONTEXT(_thread))) _main(); \
00610     _MD_GET_SP(_thread) = (int) ((_sp) - 64); \
00611     PR_END_MACRO
00612 
00613 #define _MD_SWITCH_CONTEXT(_thread) \
00614     if (!setjmp(CONTEXT(_thread))) { \
00615         _MD_SAVE_ERRNO(_thread) \
00616         _PR_Schedule();     \
00617     }
00618 
00619 #define _MD_RESTORE_CONTEXT(_newThread) \
00620 { \
00621     _MD_RESTORE_ERRNO(_newThread) \
00622     _MD_SET_CURRENT_THREAD(_newThread); \
00623     longjmp(CONTEXT(_newThread), 1); \
00624 }
00625 
00626 #else /* USE_SETJMP */
00627 
00628 #define WINDOWSIZE          0
00629  
00630 int getedi(void);
00631 void setedi(int);
00632  
00633 #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)         \
00634        PR_BEGIN_MACRO                                   \
00635        ucontext_t *uc = CONTEXT(_thread);        \
00636         *status = PR_TRUE;              \
00637        getcontext(uc);                                  \
00638        /* Force sp to be double aligned! */             \
00639        uc->uc_mcontext.gregs[USP] = (int) ((unsigned long)(_sp - WINDOWSIZE - SA(MINFRAME)) & 0xfffffff8);      \
00640        uc->uc_mcontext.gregs[PC] = (int) _main;  \
00641        (_thread)->no_sched = 0; \
00642        PR_END_MACRO
00643 
00644 /* getcontext() may return 1, contrary to what the man page says */
00645 #define _MD_SWITCH_CONTEXT(_thread)                     \
00646        PR_BEGIN_MACRO                                   \
00647        ucontext_t *uc = CONTEXT(_thread);        \
00648        PR_ASSERT(_thread->no_sched);                    \
00649        sigfillset(&((_thread)->md.blockMask));          \
00650        sigprocmask(SIG_BLOCK, &((_thread)->md.blockMask),      \
00651               &((_thread)->md.oldMask));         \
00652        (_thread)->md.edi = getedi();                    \
00653        if (! getcontext(uc)) {                          \
00654               sigprocmask(SIG_SETMASK, &((_thread)->md.oldMask), NULL); \
00655               uc->uc_mcontext.gregs[EDI] = (_thread)->md.edi;  \
00656               _MD_SAVE_ERRNO(_thread)            \
00657                _MD_SET_LAST_THREAD(_thread);             \
00658               _PR_Schedule();                           \
00659        } else {                                  \
00660               sigprocmask(SIG_SETMASK, &((_thread)->md.oldMask), NULL); \
00661               setedi((_thread)->md.edi);         \
00662               PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \
00663               _MD_LAST_THREAD()->no_sched = 0;   \
00664        }                                         \
00665        PR_END_MACRO
00666 
00667 /*
00668 ** Restore a thread context, saved by _PR_SWITCH_CONTEXT
00669 */
00670 #define _MD_RESTORE_CONTEXT(_newthread)                 \
00671        PR_BEGIN_MACRO                                   \
00672        ucontext_t *uc = CONTEXT(_newthread);            \
00673        uc->uc_mcontext.gregs[EAX] = 1;                  \
00674        _MD_RESTORE_ERRNO(_newthread)                    \
00675        _MD_SET_CURRENT_THREAD(_newthread);              \
00676        (_newthread)->no_sched = 1;               \
00677        setcontext(uc);                                  \
00678        PR_END_MACRO
00679 #endif /* USE_SETJMP */
00680 
00681 #endif /* sparc */
00682 
00683 struct _MDLock {
00684        PRInt8 notused;
00685 };
00686 
00687 struct _MDCVar {
00688        PRInt8 notused;
00689 };
00690 
00691 struct _MDSemaphore {
00692        PRInt8 notused;
00693 };
00694 
00695 struct _MDThread {
00696     _PR_CONTEXT_TYPE context;
00697     int errcode;
00698     int id;
00699 };
00700 
00701 struct _MDThreadStack {
00702     PRInt8 notused;
00703 };
00704 
00705 struct _MDSegment {
00706     PRInt8 notused;
00707 };
00708 
00709 /*
00710  * md-specific cpu structure field
00711  */
00712 #define _PR_MD_MAX_OSFD FD_SETSIZE
00713 
00714 struct _MDCPU_Unix {
00715     PRCList ioQ;
00716     PRUint32 ioq_timeout;
00717     PRInt32 ioq_max_osfd;
00718     PRInt32 ioq_osfd_cnt;
00719 #ifndef _PR_USE_POLL
00720     fd_set fd_read_set, fd_write_set, fd_exception_set;
00721     PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
00722                             fd_exception_cnt[_PR_MD_MAX_OSFD];
00723 #else
00724        struct pollfd *ioq_pollfds;
00725        int ioq_pollfds_size;
00726 #endif /* _PR_USE_POLL */
00727 };
00728 
00729 #define _PR_IOQ(_cpu)                     ((_cpu)->md.md_unix.ioQ)
00730 #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
00731 #define _PR_FD_READ_SET(_cpu)             ((_cpu)->md.md_unix.fd_read_set)
00732 #define _PR_FD_READ_CNT(_cpu)             ((_cpu)->md.md_unix.fd_read_cnt)
00733 #define _PR_FD_WRITE_SET(_cpu)            ((_cpu)->md.md_unix.fd_write_set)
00734 #define _PR_FD_WRITE_CNT(_cpu)            ((_cpu)->md.md_unix.fd_write_cnt)
00735 #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set)
00736 #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt)
00737 #define _PR_IOQ_TIMEOUT(_cpu)             ((_cpu)->md.md_unix.ioq_timeout)
00738 #define _PR_IOQ_MAX_OSFD(_cpu)            ((_cpu)->md.md_unix.ioq_max_osfd)
00739 #define _PR_IOQ_OSFD_CNT(_cpu)            ((_cpu)->md.md_unix.ioq_osfd_cnt)
00740 #define _PR_IOQ_POLLFDS(_cpu)             ((_cpu)->md.md_unix.ioq_pollfds)
00741 #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size)
00742 
00743 #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu)    32
00744 
00745 struct _MDCPU {
00746        struct _MDCPU_Unix md_unix;
00747 };
00748 
00749 #ifndef _PR_PTHREADS
00750 #define _MD_INIT_LOCKS()
00751 #endif
00752 #define _MD_NEW_LOCK(lock)                       PR_SUCCESS
00753 #define _MD_FREE_LOCK(lock)
00754 #define _MD_LOCK(lock)
00755 #define _MD_UNLOCK(lock)
00756 #define _MD_INIT_IO()
00757 #define _MD_IOQ_LOCK()
00758 #define _MD_IOQ_UNLOCK()
00759 
00760 #define _MD_INIT_RUNNING_CPU(cpu)         _MD_unix_init_running_cpu(cpu)
00761 #define _MD_INIT_THREAD                                 _MD_InitializeThread
00762 #define _MD_EXIT_THREAD(thread)
00763 #define _MD_SUSPEND_THREAD(thread)
00764 #define _MD_RESUME_THREAD(thread)
00765 #define _MD_CLEAN_THREAD(_thread)
00766 
00767 extern PRStatus _MD_WAIT(struct PRThread *, PRIntervalTime timeout);
00768 extern PRStatus _MD_WAKEUP_WAITER(struct PRThread *);
00769 extern void     _MD_YIELD(void);
00770 extern PRStatus _MD_InitializeThread(PRThread *thread);
00771 extern void     _MD_SET_PRIORITY(struct _MDThread *thread,
00772        PRThreadPriority newPri);
00773 extern PRStatus _MD_CREATE_THREAD(PRThread *thread, void (*start) (void *),
00774        PRThreadPriority priority, PRThreadScope scope, PRThreadState state,
00775         PRUint32 stackSize);
00776 
00777 NSPR_API(PRIntervalTime)                         _MD_Solaris_GetInterval(void);
00778 #define _MD_GET_INTERVAL                         _MD_Solaris_GetInterval
00779 NSPR_API(PRIntervalTime)                         _MD_Solaris_TicksPerSecond(void);
00780 #define _MD_INTERVAL_PER_SEC                     _MD_Solaris_TicksPerSecond
00781 
00782 /* The following defines the unwrapped versions of select() and poll(). */
00783 extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
00784        fd_set *exceptfds, struct timeval *timeout);
00785 #define _MD_SELECT   _select
00786 
00787 #include <stropts.h>
00788 #include <poll.h>
00789 #define _MD_POLL _poll
00790 extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
00791 
00792 PR_BEGIN_EXTERN_C
00793 
00794 /*
00795 ** Missing function prototypes
00796 */
00797 extern int gethostname (char *name, int namelen);
00798 
00799 PR_END_EXTERN_C
00800 
00801 #endif /* _PR_GLOBAL_THREADS_ONLY */
00802 
00803 extern void _MD_solaris_map_sendfile_error(int err);
00804 
00805 #endif /* nspr_solaris_defs_h___ */
00806