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