summaryrefslogtreecommitdiff
path: root/xthread.h
blob: d9a404e5e7e0ca60e73ae6ffa117c3ca023ab86b (plain)
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
#ifndef XTHREAD_H_
#define XTHREAD_H_

/* whether word reads are potentially non-atomic.
 * this is conservatice, 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
typedef int ssize_t;

#define NTDDI_VERSION NTDDI_WIN2K // needed to get win2000 api calls
#define _WIN32_WINNT 0x400
#include <stdio.h>//D
#include <fcntl.h>
#include <io.h>
#include <time.h>
#include <winsock2.h>
#include <process.h>
#include <windows.h>
#include <pthread.h>
#define sigset_t int
#define sigfillset(a)
#define pthread_sigmask(a,b,c)
#define sigaddset(a,b)
#define sigemptyset(s)
#define sigfillset(s)

typedef pthread_mutex_t mutex_t;
#define X_MUTEX_INIT           PTHREAD_MUTEX_INITIALIZER
#define X_LOCK(mutex)          pthread_mutex_lock (&(mutex))
#define X_UNLOCK(mutex)        pthread_mutex_unlock (&(mutex))

typedef pthread_cond_t cond_t;
#define X_COND_INIT                     PTHREAD_COND_INITIALIZER
#define X_COND_SIGNAL(cond)             pthread_cond_signal (&(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 thread_t;
#define X_THREAD_PROC(name) void *name (void *thr_arg)
#define X_THREAD_ATFORK(a,b,c)

static int
thread_create (thread_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 mutex_t;
#if __linux && defined (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)
# define X_MUTEX_INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
#else
# define X_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
#endif
#define X_LOCK(mutex)   pthread_mutex_lock   (&(mutex))
#define X_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))

typedef pthread_cond_t cond_t;
#define X_COND_INIT PTHREAD_COND_INITIALIZER
#define X_COND_SIGNAL(cond) pthread_cond_signal (&(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 thread_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 (long) * 4096
#endif

static int
thread_create (thread_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);
  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

#endif