VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/include/md/_solaris.h@ 101798

Last change on this file since 101798 was 101796, checked in by vboxsync, 16 months ago

libs/xpcom: Switch to using our own atomics on Solaris like we do on darwin and linux, bugref:10545

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.0 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Netscape Portable Runtime (NSPR).
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38#ifndef nspr_solaris_defs_h___
39#define nspr_solaris_defs_h___
40
41/*
42 * Internal configuration macros
43 */
44
45#define PR_LINKER_ARCH "solaris"
46#define _PR_SI_SYSNAME "SOLARIS"
47#ifdef sparc
48#define _PR_SI_ARCHITECTURE "sparc"
49#elif defined(i386)
50#define _PR_SI_ARCHITECTURE "x86"
51#elif defined(__x86_64)
52#define _PR_SI_ARCHITECTURE "x86-64"
53#else
54#error unknown processor
55#endif
56#define PR_DLL_SUFFIX ".so"
57
58#define _PR_VMBASE 0x30000000
59#define _PR_STACK_VMBASE 0x50000000
60#define _MD_DEFAULT_STACK_SIZE (2*65536L)
61#define _MD_MMAP_FLAGS MAP_SHARED
62
63#undef HAVE_STACK_GROWING_UP
64
65#ifndef HAVE_WEAK_IO_SYMBOLS
66#define HAVE_WEAK_IO_SYMBOLS
67#endif
68
69#undef HAVE_WEAK_MALLOC_SYMBOLS
70#define HAVE_DLL
71#define USE_DLFCN
72#define NEED_STRFTIME_LOCK
73
74#if defined(_LARGEFILE64_SOURCE) /* vbox */
75#define _PR_HAVE_OFF64_T /* vbox */
76#elif defined(_LP64) || _FILE_OFFSET_BITS == 32 /* vbox */
77#define _PR_HAVE_LARGE_OFF_T /* vbox */
78#else /* vbox */
79#define _PR_NO_LARGE_FILES /* vbox */
80#endif /* vbox */
81
82
83/*
84 * Intel x86 has atomic instructions.
85 *
86 * Sparc v8 does not have instructions to efficiently implement
87 * atomic increment/decrement operations. In the local threads
88 * only and pthreads versions, we use the default atomic routine
89 * implementation in pratom.c. The obsolete global threads only
90 * version uses a global mutex_t to implement the atomic routines
91 * in solaris.c, which is actually equivalent to the default
92 * implementation.
93 *
94 * 64-bit Solaris requires sparc v9, which has atomic instructions.
95 */
96#if defined(i386) || defined(_PR_GLOBAL_THREADS_ONLY) || defined(IS_64)
97#define _PR_HAVE_ATOMIC_OPS
98#endif
99
100#if defined(_PR_GLOBAL_THREADS_ONLY) || defined(_PR_PTHREADS)
101/*
102 * We have assembly language implementation of atomic
103 * stacks for the 32-bit sparc and x86 architectures only.
104 *
105 * Note: We ran into thread starvation problem with the
106 * 32-bit sparc assembly language implementation of atomic
107 * stacks, so we do not use it now. (Bugzilla bug 113740)
108 */
109#if !defined(sparc) && !defined(__x86_64)
110#define _PR_HAVE_ATOMIC_CAS
111#endif
112#endif
113
114#define _PR_POLL_AVAILABLE
115#define _PR_USE_POLL
116#define _PR_STAT_HAS_ST_ATIM
117#ifdef SOLARIS2_5
118#define _PR_HAVE_SYSV_SEMAPHORES
119#define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
120#else
121#define _PR_HAVE_POSIX_SEMAPHORES
122#define PR_HAVE_POSIX_NAMED_SHARED_MEMORY
123#endif
124#define _PR_HAVE_GETIPNODEBYNAME
125#define _PR_HAVE_GETIPNODEBYADDR
126#define _PR_HAVE_GETADDRINFO
127#define _PR_INET6_PROBE
128#define _PR_ACCEPT_INHERIT_NONBLOCK
129#if !defined(_XPG4_2) || defined(_XPG6) || defined(__EXTENSIONS__) /* vbox */
130#define _PR_INET6 /* vbox */
131#endif /* vbox */
132#ifdef _PR_INET6
133#define _PR_HAVE_INET_NTOP
134#else
135#define AF_INET6 26
136struct addrinfo {
137 int ai_flags;
138 int ai_family;
139 int ai_socktype;
140 int ai_protocol;
141 size_t ai_addrlen;
142 char *ai_canonname;
143 struct sockaddr *ai_addr;
144 struct addrinfo *ai_next;
145};
146#define AI_CANONNAME 0x0010
147#define AI_V4MAPPED 0x0001
148#define AI_ALL 0x0002
149#define AI_ADDRCONFIG 0x0004
150#define _PR_HAVE_MD_SOCKADDR_IN6
151/* isomorphic to struct in6_addr on Solaris 8 */
152struct _md_in6_addr {
153 union {
154 PRUint8 _S6_u8[16];
155 PRUint32 _S6_u32[4];
156 PRUint32 __S6_align;
157 } _S6_un;
158};
159/* isomorphic to struct sockaddr_in6 on Solaris 8 */
160struct _md_sockaddr_in6 {
161 PRUint16 sin6_family;
162 PRUint16 sin6_port;
163 PRUint32 sin6_flowinfo;
164 struct _md_in6_addr sin6_addr;
165 PRUint32 sin6_scope_id;
166 PRUint32 __sin6_src_id;
167};
168#endif
169#if defined(_PR_GLOBAL_THREADS_ONLY) || defined(_PR_PTHREADS)
170#define _PR_HAVE_GETHOST_R
171#define _PR_HAVE_GETHOST_R_POINTER
172#endif
173
174#include "prinrval.h"
175NSPR_API(PRIntervalTime) _MD_Solaris_GetInterval(void);
176#define _MD_GET_INTERVAL _MD_Solaris_GetInterval
177NSPR_API(PRIntervalTime) _MD_Solaris_TicksPerSecond(void);
178#define _MD_INTERVAL_PER_SEC _MD_Solaris_TicksPerSecond
179
180#include "_iprt_atomic.h"
181
182#if defined(_PR_PTHREADS)
183
184NSPR_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
199NSPR_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
212NSPR_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
228extern struct PRLock *_pr_schedLock;
229
230/*
231** Thread Local Storage
232*/
233
234#define THREAD_KEY_T thread_key_t
235
236extern struct PRThread *_pr_attached_thread_tls();
237extern struct PRThread *_pr_current_thread_tls();
238extern struct _PRCPU *_pr_current_cpu_tls();
239extern struct PRThread *_pr_last_thread_tls();
240
241extern THREAD_KEY_T threadid_key;
242extern THREAD_KEY_T cpuid_key;
243extern 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)
266extern 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
276extern void _MD_Begin_SuspendAll(void);
277extern void _MD_End_SuspendAll(void);
278extern 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))
289struct _MDLock;
290NSPR_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)
330extern 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
348extern 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
352extern PRStatus _MD_wait(struct PRThread *, PRIntervalTime timeout);
353#define _MD_WAIT _MD_wait
354
355extern PRStatus _MD_WakeupWaiter(struct PRThread *);
356#define _MD_WAKEUP_WAITER _MD_WakeupWaiter
357
358NSPR_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
368struct _MDLock {
369 MUTEX_T lock;
370#ifdef PROFILE_LOCKS
371 PRInt32 hitcount;
372 PRInt32 misscount;
373#endif
374};
375
376struct _MDCVar {
377 COND_T cv;
378};
379
380struct _MDSemaphore {
381 sema_t sem;
382};
383
384struct _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
393struct _MDThreadStack {
394 PRInt8 notused;
395};
396
397struct _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
406struct _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
438struct _MDCPU {
439 struct _MDCPU_Unix md_unix;
440};
441
442/* The following defines the unwrapped versions of select() and poll(). */
443extern 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
449extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
450
451PR_BEGIN_EXTERN_C
452
453/*
454** Missing function prototypes
455*/
456extern int gethostname (char *name, int namelen);
457
458PR_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
477NSPR_API(void) _MD_EarlyInit(void);
478NSPR_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
639int getedi(void);
640void 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
692struct _MDLock {
693 PRInt8 notused;
694};
695
696struct _MDCVar {
697 PRInt8 notused;
698};
699
700struct _MDSemaphore {
701 PRInt8 notused;
702};
703
704struct _MDThread {
705 _PR_CONTEXT_TYPE context;
706 int errcode;
707 int id;
708};
709
710struct _MDThreadStack {
711 PRInt8 notused;
712};
713
714struct _MDSegment {
715 PRInt8 notused;
716};
717
718/*
719 * md-specific cpu structure field
720 */
721#define _PR_MD_MAX_OSFD FD_SETSIZE
722
723struct _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
754struct _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
776extern PRStatus _MD_WAIT(struct PRThread *, PRIntervalTime timeout);
777extern PRStatus _MD_WAKEUP_WAITER(struct PRThread *);
778extern void _MD_YIELD(void);
779extern PRStatus _MD_InitializeThread(PRThread *thread);
780extern void _MD_SET_PRIORITY(struct _MDThread *thread,
781 PRThreadPriority newPri);
782extern PRStatus _MD_CREATE_THREAD(PRThread *thread, void (*start) (void *),
783 PRThreadPriority priority, PRThreadScope scope, PRThreadState state,
784 PRUint32 stackSize);
785
786NSPR_API(PRIntervalTime) _MD_Solaris_GetInterval(void);
787#define _MD_GET_INTERVAL _MD_Solaris_GetInterval
788NSPR_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(). */
792extern 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
799extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
800
801PR_BEGIN_EXTERN_C
802
803/*
804** Missing function prototypes
805*/
806extern int gethostname (char *name, int namelen);
807
808PR_END_EXTERN_C
809
810#endif /* _PR_GLOBAL_THREADS_ONLY */
811
812extern void _MD_solaris_map_sendfile_error(int err);
813
814#endif /* nspr_solaris_defs_h___ */
815
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette