1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
#ifndef XTHREAD_H_
#define XTHREAD_H_
/* whether word reads are potentially non-atomic.
* this is conservative, likely most arches this runs
* on have atomic word read/writes.
*/
#ifndef WORDACCESS_UNSAFE
# if __i386 || __x86_64
# define WORDACCESS_UNSAFE 0
# else
# define WORDACCESS_UNSAFE 1
# endif
#endif
/////////////////////////////////////////////////////////////////////////////
#ifdef _WIN32
//#define NTDDI_VERSION NTDDI_WIN2K // needed to get win2000 api calls, fails with mingw
#define _WIN32_WINNT 0x400 // maybe working alternative for mingw
#include <stdio.h>//D
#include <fcntl.h>
#include <io.h>
#include <time.h>
#include <winsock2.h>
#include <process.h>
#include <windows.h>
/* work around some bugs in ptw32 */
#if defined(__MINGW32__) && defined(_TIMESPEC_DEFINED)
#define HAVE_STRUCT_TIMESPEC 1
#endif
#include <pthread.h>
#define sigset_t int
#define sigfillset(a)
#define pthread_sigmask(a,b,c)
#define sigaddset(a,b)
#define sigemptyset(s)
typedef pthread_mutex_t xmutex_t;
#define X_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
#define X_MUTEX_CREATE(mutex) pthread_mutex_init (&(mutex), 0)
#define X_LOCK(mutex) pthread_mutex_lock (&(mutex))
#define X_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
typedef pthread_cond_t xcond_t;
#define X_COND_INIT PTHREAD_COND_INITIALIZER
#define X_COND_CREATE(cond) pthread_cond_init (&(cond), 0)
#define X_COND_SIGNAL(cond) pthread_cond_signal (&(cond))
#define X_COND_BROADCAST(cond) pthread_cond_broadcast (&(cond))
#define X_COND_WAIT(cond,mutex) pthread_cond_wait (&(cond), &(mutex))
#define X_COND_TIMEDWAIT(cond,mutex,to) pthread_cond_timedwait (&(cond), &(mutex), &(to))
typedef pthread_t xthread_t;
#define X_THREAD_PROC(name) static void *name (void *thr_arg)
#define X_THREAD_ATFORK(a,b,c)
static int
xthread_create (xthread_t *tid, void *(*proc)(void *), void *arg)
{
int retval;
pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
retval = pthread_create (tid, &attr, proc, arg) == 0;
pthread_attr_destroy (&attr);
return retval;
}
#define respipe_read(a,b,c) PerlSock_recv ((a), (b), (c), 0)
#define respipe_write(a,b,c) send ((a), (b), (c), 0)
#define respipe_close(a) PerlSock_closesocket ((a))
#else
/////////////////////////////////////////////////////////////////////////////
#if __linux && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
#endif
/* just in case */
#define _REENTRANT 1
#if __solaris
# define _POSIX_PTHREAD_SEMANTICS 1
/* try to bribe solaris headers into providing a current pthread API
* despite environment being configured for an older version.
*/
# define __EXTENSIONS__ 1
#endif
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <limits.h>
#include <pthread.h>
typedef pthread_mutex_t xmutex_t;
#if __linux && defined (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)
# define X_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
# define X_MUTEX_CREATE(mutex) \
do { \
pthread_mutexattr_t attr; \
pthread_mutexattr_init (&attr); \
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ADAPTIVE_NP); \
pthread_mutex_init (&(mutex), &attr); \
} while (0)
#else
# define X_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
# define X_MUTEX_CREATE(mutex) pthread_mutex_init (&(mutex), 0)
#endif
#define X_LOCK(mutex) pthread_mutex_lock (&(mutex))
#define X_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
typedef pthread_cond_t xcond_t;
#define X_COND_INIT PTHREAD_COND_INITIALIZER
#define X_COND_CREATE(cond) pthread_cond_init (&(cond), 0)
#define X_COND_SIGNAL(cond) pthread_cond_signal (&(cond))
#define X_COND_BROADCAST(cond) pthread_cond_broadcast (&(cond))
#define X_COND_WAIT(cond,mutex) pthread_cond_wait (&(cond), &(mutex))
#define X_COND_TIMEDWAIT(cond,mutex,to) pthread_cond_timedwait (&(cond), &(mutex), &(to))
typedef pthread_t xthread_t;
#define X_THREAD_PROC(name) static void *name (void *thr_arg)
#define X_THREAD_ATFORK(prepare,parent,child) pthread_atfork (prepare, parent, child)
// the broken bsd's once more
#ifndef PTHREAD_STACK_MIN
# define PTHREAD_STACK_MIN 0
#endif
#ifndef X_STACKSIZE
# define X_STACKSIZE sizeof (void *) * 4096
#endif
static int
xthread_create (xthread_t *tid, void *(*proc)(void *), void *arg)
{
int retval;
sigset_t fullsigset, oldsigset;
pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
if (X_STACKSIZE != 0)
pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < X_STACKSIZE ? X_STACKSIZE : PTHREAD_STACK_MIN);
#ifdef PTHREAD_SCOPE_PROCESS
pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
#endif
sigfillset (&fullsigset);
pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
retval = pthread_create (tid, &attr, proc, arg) == 0;
pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
pthread_attr_destroy (&attr);
return retval;
}
#define respipe_read(a,b,c) read ((a), (b), (c))
#define respipe_write(a,b,c) write ((a), (b), (c))
#define respipe_close(a) close ((a))
#endif
#if __linux && __GNUC__ >= 4 && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 3 && 0 /* also check arch */
/* __thread has little to no advantage over pthread_* in most configurations, so this is not used */
# define X_TLS_DECLARE(varname) __thread void *varname
# define X_TLS_INIT(varname)
# define X_TLS_SET(varname,value) varname = (value)
# define X_TLS_GET(varname) varname
#else
# define X_TLS_DECLARE(varname) pthread_key_t varname
# define X_TLS_INIT(varname) do { if (pthread_key_create (&(varname), 0)) abort (); } while (0)
# define X_TLS_SET(varname,value) pthread_setspecific (varname, (value))
# define X_TLS_GET(varname) pthread_getspecific (varname)
#endif
#endif
|