25
25
#include "ei_locking.h"
28
#ifdef USE_DECLSPEC_THREAD
27
29
/* Define (and initialize) the variable __erl_errno */
28
30
volatile __declspec(thread) int __erl_errno = 0;
32
static volatile DWORD errno_tls_index = TLS_OUT_OF_INDEXES;
33
static LONG volatile tls_init_mutex = 0;
30
37
#if defined(VXWORKS)
33
40
Moved to each of the erl_*threads.c files, as they seem to know how
34
41
to get thread-safety.
43
static volatile int __erl_errno;
37
44
volatile int *__erl_errno_place(void)
39
46
/* This check is somewhat insufficient, double task var entries will occur
49
56
#if defined(__WIN32__)
58
#ifdef USE_DECLSPEC_THREAD
51
60
volatile int *__erl_errno_place(void)
53
62
return &__erl_errno;
66
static void tls_init_once(void)
69
if (errno_tls_index != TLS_OUT_OF_INDEXES) {
72
if (InterlockedExchange((LPLONG) &tls_init_mutex,1L) == 0) {
74
errno_tls_index = TlsAlloc();
75
if (errno_tls_index == TLS_OUT_OF_INDEXES) {
77
"FATAL ERROR: can not allocate TLS index for "
78
"erl_errno (error code = %d)!\n",GetLastError());
82
while (errno_tls_index == TLS_OUT_OF_INDEXES) {
88
volatile int *__erl_errno_place(void)
92
ptr = TlsGetValue(errno_tls_index);
94
ptr = malloc(sizeof(int));
96
TlsSetValue(errno_tls_index, (PVOID) ptr);
101
#endif /* USE_DECLSPEC_THREAD */
56
103
#endif /* __WIN32__ */
58
105
#if defined(_REENTRANT) && !defined(VXWORKS) && !defined(__WIN32__)
125
172
* Return a pointer to the erl_errno locus.
126
* If pthread functions fail we fall back to using __erl_errno
173
* If pthread functions fail we fall back to using fallback_errno
127
174
* so that the main thread (actually not a thread in all ascpects)
128
175
* still will set and get an erl_errno value.
129
* FIXME is this a bit too nice???
130
* If -lpthread is not given on Solaris __erl_errno will be used
131
* but it costs some....,
176
* Actually this is a bit to nice, it would be preferrable to exit fatal
177
* as we do on windows, but we might break some code with one thread
178
* but still compiled with -D_REENTRANT, so we'll leave it here.
133
180
volatile int *__erl_errno_place(void)
135
182
int *erl_errno_p;
183
static volatile int use_fallback = 0;
184
static volatile int fallback_errno = 0;
187
return &fallback_errno;
137
190
/* This will create the key once for all threads */
138
if (pthread_once(&erl_errno_key_once, erl_errno_key_alloc) != 0)
191
if (pthread_once(&erl_errno_key_once, erl_errno_key_alloc) != 0) {
193
return &fallback_errno;
141
196
/* This is the normal case, return the pointer to the data */
142
if ((erl_errno_p = pthread_getspecific(erl_errno_key)) != NULL)
197
if ((erl_errno_p = pthread_getspecific(erl_errno_key)) != NULL) {
143
198
return erl_errno_p;
145
/* Case where it is the first time we access this data in this thread. */
146
/* FIXME check malloc but what to do????? */
147
erl_errno_p = malloc(sizeof(int));
201
if ((erl_errno_p = malloc(sizeof(int))) == NULL) {
203
return &fallback_errno;
149
206
if (pthread_setspecific(erl_errno_key, erl_errno_p) != 0 ||
150
207
(erl_errno_p = pthread_getspecific(erl_errno_key)) == NULL) {
151
208
free(erl_errno_p);
209
return &fallback_errno;
155
212
return erl_errno_p;