nsprpub/pr/include/md/_solaris.h

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef nspr_solaris_defs_h___
     7 #define nspr_solaris_defs_h___
     9 /*
    10  * Internal configuration macros
    11  */
    13 #define PR_LINKER_ARCH	"solaris"
    14 #define _PR_SI_SYSNAME	"SOLARIS"
    15 #ifdef sparc
    16 #define _PR_SI_ARCHITECTURE	"sparc"
    17 #elif defined(__x86_64)
    18 #define _PR_SI_ARCHITECTURE	"x86-64"
    19 #elif defined(i386)
    20 #define _PR_SI_ARCHITECTURE	"x86"
    21 #else
    22 #error unknown processor
    23 #endif
    24 #define PR_DLL_SUFFIX		".so"
    26 #define _PR_VMBASE		0x30000000
    27 #define _PR_STACK_VMBASE	0x50000000
    28 #define _MD_DEFAULT_STACK_SIZE	(2*65536L)
    29 #define _MD_MMAP_FLAGS          MAP_SHARED
    31 #undef  HAVE_STACK_GROWING_UP
    33 #ifndef HAVE_WEAK_IO_SYMBOLS
    34 #define	HAVE_WEAK_IO_SYMBOLS
    35 #endif
    37 #undef	HAVE_WEAK_MALLOC_SYMBOLS
    38 #define	HAVE_DLL
    39 #define	USE_DLFCN
    40 #define NEED_STRFTIME_LOCK
    42 /*
    43  * Intel x86 has atomic instructions.
    44  *
    45  * Sparc v8 does not have instructions to efficiently implement
    46  * atomic increment/decrement operations.  We use the default
    47  * atomic routine implementation in pratom.c.
    48  *
    49  * 64-bit Solaris requires sparc v9, which has atomic instructions.
    50  */
    51 #if defined(i386) || defined(IS_64)
    52 #define _PR_HAVE_ATOMIC_OPS
    53 #endif
    55 #define _PR_POLL_AVAILABLE
    56 #define _PR_USE_POLL
    57 #define _PR_STAT_HAS_ST_ATIM
    58 #ifdef SOLARIS2_5
    59 #define _PR_HAVE_SYSV_SEMAPHORES
    60 #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
    61 #else
    62 #define _PR_HAVE_POSIX_SEMAPHORES
    63 #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY
    64 #endif
    65 #define _PR_HAVE_GETIPNODEBYNAME
    66 #define _PR_HAVE_GETIPNODEBYADDR
    67 #define _PR_HAVE_GETADDRINFO
    68 #define _PR_INET6_PROBE
    69 #define _PR_ACCEPT_INHERIT_NONBLOCK
    70 #ifdef _PR_INET6
    71 #define _PR_HAVE_INET_NTOP
    72 #else
    73 #define AF_INET6 26
    74 struct addrinfo {
    75     int ai_flags;
    76     int ai_family;
    77     int ai_socktype;
    78     int ai_protocol;
    79     size_t ai_addrlen;
    80     char *ai_canonname;
    81     struct sockaddr *ai_addr;
    82     struct addrinfo *ai_next;
    83 };
    84 #define AI_CANONNAME 0x0010
    85 #define AI_V4MAPPED 0x0001 
    86 #define AI_ALL      0x0002
    87 #define AI_ADDRCONFIG   0x0004
    88 #define _PR_HAVE_MD_SOCKADDR_IN6
    89 /* isomorphic to struct in6_addr on Solaris 8 */
    90 struct _md_in6_addr {
    91     union {
    92         PRUint8  _S6_u8[16];
    93         PRUint32 _S6_u32[4];
    94         PRUint32 __S6_align;
    95     } _S6_un;
    96 };
    97 /* isomorphic to struct sockaddr_in6 on Solaris 8 */
    98 struct _md_sockaddr_in6 {
    99     PRUint16 sin6_family;
   100     PRUint16 sin6_port;
   101     PRUint32 sin6_flowinfo;
   102     struct _md_in6_addr sin6_addr;
   103     PRUint32 sin6_scope_id;
   104     PRUint32 __sin6_src_id;
   105 };
   106 #endif
   107 #if defined(_PR_PTHREADS)
   108 #define _PR_HAVE_GETHOST_R
   109 #define _PR_HAVE_GETHOST_R_POINTER
   110 #endif
   112 #include "prinrval.h"
   113 #define _MD_INTERVAL_INIT()
   114 NSPR_API(PRIntervalTime) _MD_Solaris_GetInterval(void);
   115 #define _MD_GET_INTERVAL                  _MD_Solaris_GetInterval
   116 NSPR_API(PRIntervalTime) _MD_Solaris_TicksPerSecond(void);
   117 #define _MD_INTERVAL_PER_SEC              _MD_Solaris_TicksPerSecond
   119 #if defined(_PR_HAVE_ATOMIC_OPS)
   120 /*
   121 ** Atomic Operations
   122 */
   123 #define _MD_INIT_ATOMIC()
   125 NSPR_API(PRInt32) _MD_AtomicIncrement(PRInt32 *val);
   126 #define _MD_ATOMIC_INCREMENT _MD_AtomicIncrement
   128 NSPR_API(PRInt32) _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val);
   129 #define _MD_ATOMIC_ADD _MD_AtomicAdd
   131 NSPR_API(PRInt32) _MD_AtomicDecrement(PRInt32 *val);
   132 #define _MD_ATOMIC_DECREMENT _MD_AtomicDecrement
   134 NSPR_API(PRInt32) _MD_AtomicSet(PRInt32 *val, PRInt32 newval);
   135 #define _MD_ATOMIC_SET _MD_AtomicSet
   136 #endif /* _PR_HAVE_ATOMIC_OPS */
   138 #if defined(_PR_PTHREADS)
   140 NSPR_API(void)		_MD_EarlyInit(void);
   142 #define _MD_EARLY_INIT		_MD_EarlyInit
   143 #define _MD_FINAL_INIT		_PR_UnixInit
   145 #else /* _PR_PTHREADS */
   147 /*
   148  * _PR_LOCAL_THREADS_ONLY implementation on Solaris
   149  */
   151 #include "prthread.h"
   153 #include <errno.h>
   154 #include <ucontext.h>
   155 #include <sys/stack.h>
   156 #include <synch.h>
   158 /*
   159 ** Initialization Related definitions
   160 */
   162 NSPR_API(void)				_MD_EarlyInit(void);
   163 NSPR_API(void)				_MD_SolarisInit();
   164 #define _MD_EARLY_INIT		_MD_EarlyInit
   165 #define _MD_FINAL_INIT		_MD_SolarisInit
   166 #define	_MD_INIT_THREAD		_MD_InitializeThread
   168 #ifdef USE_SETJMP
   170 #include <setjmp.h>
   172 #define _PR_CONTEXT_TYPE	jmp_buf
   174 #ifdef sparc
   175 #define _MD_GET_SP(_t)		(_t)->md.context[2]
   176 #else
   177 #define _MD_GET_SP(_t)		(_t)->md.context[4]
   178 #endif
   180 #define PR_NUM_GCREGS		_JBLEN
   181 #define CONTEXT(_thread)	(_thread)->md.context
   183 #else  /* ! USE_SETJMP */
   185 #ifdef sparc
   186 #define	_PR_CONTEXT_TYPE	ucontext_t
   187 #define _MD_GET_SP(_t)		(_t)->md.context.uc_mcontext.gregs[REG_SP]
   188 /*
   189 ** Sparc's use register windows. the _MD_GetRegisters for the sparc's
   190 ** doesn't actually store anything into the argument buffer; instead the
   191 ** register windows are homed to the stack. I assume that the stack
   192 ** always has room for the registers to spill to...
   193 */
   194 #define PR_NUM_GCREGS		0
   195 #else
   196 #define _PR_CONTEXT_TYPE	unsigned int edi; sigset_t oldMask, blockMask; ucontext_t
   197 #define _MD_GET_SP(_t)		(_t)->md.context.uc_mcontext.gregs[USP]
   198 #define PR_NUM_GCREGS		_JBLEN
   199 #endif
   201 #define CONTEXT(_thread)	(&(_thread)->md.context)
   203 #endif /* ! USE_SETJMP */
   205 #include <time.h>
   206 /* 
   207  * Because clock_gettime() on Solaris/x86 always generates a
   208  * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(),
   209  * which is implemented using gettimeofday().
   210  */
   211 #ifdef i386
   212 #define GETTIME(tt) _pr_solx86_clock_gettime(CLOCK_REALTIME, (tt))
   213 #else
   214 #define GETTIME(tt) clock_gettime(CLOCK_REALTIME, (tt))
   215 #endif  /* i386 */
   217 #define _MD_SAVE_ERRNO(_thread)			(_thread)->md.errcode = errno;
   218 #define _MD_RESTORE_ERRNO(_thread)		errno = (_thread)->md.errcode;
   220 #ifdef sparc
   222 #ifdef USE_SETJMP
   223 #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)	      \
   224     PR_BEGIN_MACRO				      \
   225 	int *context = (_thread)->md.context;	      \
   226     *status = PR_TRUE;              \
   227 	(void) setjmp(context);			      \
   228 	(_thread)->md.context[1] = (int) ((_sp) - 64); \
   229 	(_thread)->md.context[2] = (int) _main;	      \
   230 	(_thread)->md.context[3] = (int) _main + 4; \
   231     _thread->no_sched = 0; \
   232     PR_END_MACRO
   234 #define _MD_SWITCH_CONTEXT(_thread)    \
   235     if (!setjmp(CONTEXT(_thread))) { \
   236 	_MD_SAVE_ERRNO(_thread)    \
   237 	_MD_SET_LAST_THREAD(_thread);	 \
   238     _MD_SET_CURRENT_THREAD(_thread);	 \
   239 	_PR_Schedule();		     \
   240     }
   242 #define _MD_RESTORE_CONTEXT(_newThread)	    \
   243 {				     \
   244 	_MD_RESTORE_ERRNO(_newThread)	    \
   245 	_MD_SET_CURRENT_THREAD(_newThread); \
   246     longjmp(CONTEXT(_newThread), 1);    \
   247 }
   249 #else
   250 /*
   251 ** Initialize the thread context preparing it to execute _main.
   252 */
   253 #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)					\
   254     PR_BEGIN_MACRO				      									\
   255     ucontext_t *uc = CONTEXT(_thread);									\
   256     *status = PR_TRUE;													\
   257     getcontext(uc);														\
   258     uc->uc_stack.ss_sp = (char *) ((unsigned long)(_sp - WINDOWSIZE - SA(MINFRAME)) & 0xfffffff8);	\
   259     uc->uc_stack.ss_size = _thread->stack->stackSize; 					\
   260     uc->uc_stack.ss_flags = 0; 				/* ? */		        		\
   261     uc->uc_mcontext.gregs[REG_SP] = (unsigned int) uc->uc_stack.ss_sp;	\
   262     uc->uc_mcontext.gregs[REG_PC] = (unsigned int) _main;				\
   263     uc->uc_mcontext.gregs[REG_nPC] = (unsigned int) ((char*)_main)+4;	\
   264     uc->uc_flags = UC_ALL;												\
   265     _thread->no_sched = 0;												\
   266     PR_END_MACRO
   268 /*
   269 ** Switch away from the current thread context by saving its state and
   270 ** calling the thread scheduler. Reload cpu when we come back from the
   271 ** context switch because it might have changed.
   272 */
   273 #define _MD_SWITCH_CONTEXT(_thread)    				\
   274     PR_BEGIN_MACRO                     				\
   275 		if (!getcontext(CONTEXT(_thread))) { 		\
   276 			_MD_SAVE_ERRNO(_thread);    			\
   277 			_MD_SET_LAST_THREAD(_thread);	 		\
   278 			_PR_Schedule();			 				\
   279 		}					 						\
   280     PR_END_MACRO
   282 /*
   283 ** Restore a thread context that was saved by _MD_SWITCH_CONTEXT or
   284 ** initialized by _MD_INIT_CONTEXT.
   285 */
   286 #define _MD_RESTORE_CONTEXT(_newThread)	    				\
   287     PR_BEGIN_MACRO			    							\
   288     	ucontext_t *uc = CONTEXT(_newThread); 				\
   289     	uc->uc_mcontext.gregs[11] = 1;     					\
   290 		_MD_RESTORE_ERRNO(_newThread);	    				\
   291 		_MD_SET_CURRENT_THREAD(_newThread); 				\
   292     	setcontext(uc);		       							\
   293     PR_END_MACRO
   294 #endif
   296 #else  /* x86 solaris */
   298 #ifdef USE_SETJMP
   300 #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \
   301     PR_BEGIN_MACRO \
   302     *status = PR_TRUE; \
   303     if (setjmp(CONTEXT(_thread))) _main(); \
   304     _MD_GET_SP(_thread) = (int) ((_sp) - 64); \
   305     PR_END_MACRO
   307 #define _MD_SWITCH_CONTEXT(_thread) \
   308     if (!setjmp(CONTEXT(_thread))) { \
   309         _MD_SAVE_ERRNO(_thread) \
   310         _PR_Schedule();	\
   311     }
   313 #define _MD_RESTORE_CONTEXT(_newThread) \
   314 { \
   315     _MD_RESTORE_ERRNO(_newThread) \
   316     _MD_SET_CURRENT_THREAD(_newThread); \
   317     longjmp(CONTEXT(_newThread), 1); \
   318 }
   320 #else /* USE_SETJMP */
   322 #define WINDOWSIZE		0
   324 int getedi(void);
   325 void setedi(int);
   327 #define _MD_INIT_CONTEXT(_thread, _sp, _main, status)	      \
   328 	PR_BEGIN_MACRO					\
   329 	ucontext_t *uc = CONTEXT(_thread);		\
   330         *status = PR_TRUE;              \
   331 	getcontext(uc);					\
   332 	/* Force sp to be double aligned! */		\
   333     	uc->uc_mcontext.gregs[USP] = (int) ((unsigned long)(_sp - WINDOWSIZE - SA(MINFRAME)) & 0xfffffff8);	\
   334 	uc->uc_mcontext.gregs[PC] = (int) _main;	\
   335 	(_thread)->no_sched = 0; \
   336 	PR_END_MACRO
   338 /* getcontext() may return 1, contrary to what the man page says */
   339 #define _MD_SWITCH_CONTEXT(_thread)			\
   340 	PR_BEGIN_MACRO					\
   341 	ucontext_t *uc = CONTEXT(_thread);		\
   342 	PR_ASSERT(_thread->no_sched);			\
   343 	sigfillset(&((_thread)->md.blockMask));		\
   344 	sigprocmask(SIG_BLOCK, &((_thread)->md.blockMask),	\
   345 		&((_thread)->md.oldMask));		\
   346 	(_thread)->md.edi = getedi();			\
   347 	if (! getcontext(uc)) {				\
   348 		sigprocmask(SIG_SETMASK, &((_thread)->md.oldMask), NULL); \
   349 		uc->uc_mcontext.gregs[EDI] = (_thread)->md.edi;	\
   350 		_MD_SAVE_ERRNO(_thread)    		\
   351 	        _MD_SET_LAST_THREAD(_thread);	        \
   352 		_PR_Schedule();				\
   353 	} else {					\
   354 		sigprocmask(SIG_SETMASK, &((_thread)->md.oldMask), NULL); \
   355 		setedi((_thread)->md.edi);		\
   356 		PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \
   357 		_MD_LAST_THREAD()->no_sched = 0;	\
   358 	}						\
   359 	PR_END_MACRO
   361 /*
   362 ** Restore a thread context, saved by _PR_SWITCH_CONTEXT
   363 */
   364 #define _MD_RESTORE_CONTEXT(_newthread)			\
   365 	PR_BEGIN_MACRO					\
   366 	ucontext_t *uc = CONTEXT(_newthread);		\
   367 	uc->uc_mcontext.gregs[EAX] = 1;			\
   368 	_MD_RESTORE_ERRNO(_newthread)  			\
   369 	_MD_SET_CURRENT_THREAD(_newthread);		\
   370 	(_newthread)->no_sched = 1;			\
   371 	setcontext(uc);					\
   372 	PR_END_MACRO
   373 #endif /* USE_SETJMP */
   375 #endif /* sparc */
   377 struct _MDLock {
   378 	PRInt8 notused;
   379 };
   381 struct _MDCVar {
   382 	PRInt8 notused;
   383 };
   385 struct _MDSemaphore {
   386 	PRInt8 notused;
   387 };
   389 struct _MDThread {
   390     _PR_CONTEXT_TYPE context;
   391     int errcode;
   392     int id;
   393 };
   395 struct _MDThreadStack {
   396     PRInt8 notused;
   397 };
   399 struct _MDSegment {
   400     PRInt8 notused;
   401 };
   403 /*
   404  * md-specific cpu structure field
   405  */
   406 #define _PR_MD_MAX_OSFD FD_SETSIZE
   408 struct _MDCPU_Unix {
   409     PRCList ioQ;
   410     PRUint32 ioq_timeout;
   411     PRInt32 ioq_max_osfd;
   412     PRInt32 ioq_osfd_cnt;
   413 #ifndef _PR_USE_POLL
   414     fd_set fd_read_set, fd_write_set, fd_exception_set;
   415     PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD],
   416 				fd_exception_cnt[_PR_MD_MAX_OSFD];
   417 #else
   418 	struct pollfd *ioq_pollfds;
   419 	int ioq_pollfds_size;
   420 #endif	/* _PR_USE_POLL */
   421 };
   423 #define _PR_IOQ(_cpu)			((_cpu)->md.md_unix.ioQ)
   424 #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu))
   425 #define _PR_FD_READ_SET(_cpu)		((_cpu)->md.md_unix.fd_read_set)
   426 #define _PR_FD_READ_CNT(_cpu)		((_cpu)->md.md_unix.fd_read_cnt)
   427 #define _PR_FD_WRITE_SET(_cpu)		((_cpu)->md.md_unix.fd_write_set)
   428 #define _PR_FD_WRITE_CNT(_cpu)		((_cpu)->md.md_unix.fd_write_cnt)
   429 #define _PR_FD_EXCEPTION_SET(_cpu)	((_cpu)->md.md_unix.fd_exception_set)
   430 #define _PR_FD_EXCEPTION_CNT(_cpu)	((_cpu)->md.md_unix.fd_exception_cnt)
   431 #define _PR_IOQ_TIMEOUT(_cpu)		((_cpu)->md.md_unix.ioq_timeout)
   432 #define _PR_IOQ_MAX_OSFD(_cpu)		((_cpu)->md.md_unix.ioq_max_osfd)
   433 #define _PR_IOQ_OSFD_CNT(_cpu)		((_cpu)->md.md_unix.ioq_osfd_cnt)
   434 #define _PR_IOQ_POLLFDS(_cpu)		((_cpu)->md.md_unix.ioq_pollfds)
   435 #define _PR_IOQ_POLLFDS_SIZE(_cpu)	((_cpu)->md.md_unix.ioq_pollfds_size)
   437 #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu)	32
   439 struct _MDCPU {
   440 	struct _MDCPU_Unix md_unix;
   441 };
   443 #define _MD_INIT_LOCKS()
   444 #define _MD_NEW_LOCK(lock)				PR_SUCCESS
   445 #define _MD_FREE_LOCK(lock)
   446 #define _MD_LOCK(lock)
   447 #define _MD_UNLOCK(lock)
   448 #define _MD_INIT_IO()
   449 #define _MD_IOQ_LOCK()
   450 #define _MD_IOQ_UNLOCK()
   452 #define _MD_INIT_RUNNING_CPU(cpu)		_MD_unix_init_running_cpu(cpu)
   453 #define _MD_INIT_THREAD					_MD_InitializeThread
   454 #define _MD_EXIT_THREAD(thread)
   455 #define _MD_SUSPEND_THREAD(thread)
   456 #define _MD_RESUME_THREAD(thread)
   457 #define _MD_CLEAN_THREAD(_thread)
   459 extern PRStatus _MD_WAIT(struct PRThread *, PRIntervalTime timeout);
   460 extern PRStatus _MD_WAKEUP_WAITER(struct PRThread *);
   461 extern void     _MD_YIELD(void);
   462 extern PRStatus _MD_InitializeThread(PRThread *thread);
   463 extern void     _MD_SET_PRIORITY(struct _MDThread *thread,
   464 	PRThreadPriority newPri);
   465 extern PRStatus _MD_CREATE_THREAD(PRThread *thread, void (*start) (void *),
   466 	PRThreadPriority priority, PRThreadScope scope, PRThreadState state,
   467         PRUint32 stackSize);
   469 /* The following defines the unwrapped versions of select() and poll(). */
   470 extern int _select(int nfds, fd_set *readfds, fd_set *writefds,
   471 	fd_set *exceptfds, struct timeval *timeout);
   472 #define _MD_SELECT	_select
   474 #include <stropts.h>
   475 #include <poll.h>
   476 #define _MD_POLL _poll
   477 extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout);
   479 PR_BEGIN_EXTERN_C
   481 /*
   482 ** Missing function prototypes
   483 */
   484 extern int gethostname (char *name, int namelen);
   486 PR_END_EXTERN_C
   488 #endif /* _PR_PTHREADS */
   490 extern void _MD_solaris_map_sendfile_error(int err);
   492 #endif /* nspr_solaris_defs_h___ */

mercurial