~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to pypy/translator/c/src/thread_pthread.h

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* Posix threads interface (from CPython) */
 
3
 
 
4
#include <pthread.h>
 
5
#include <errno.h>
 
6
 
 
7
/* The POSIX spec says that implementations supporting the sem_*
 
8
   family of functions must indicate this by defining
 
9
   _POSIX_SEMAPHORES. */   
 
10
#ifdef _POSIX_SEMAPHORES
 
11
/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so 
 
12
   we need to add 0 to make it work there as well. */
 
13
#if (_POSIX_SEMAPHORES+0) == -1
 
14
#define HAVE_BROKEN_POSIX_SEMAPHORES
 
15
#else
 
16
#include <semaphore.h>
 
17
#endif
 
18
#endif
 
19
 
 
20
#if !defined(pthread_attr_default)
 
21
#  define pthread_attr_default ((pthread_attr_t *)NULL)
 
22
#endif
 
23
#if !defined(pthread_mutexattr_default)
 
24
#  define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
 
25
#endif
 
26
#if !defined(pthread_condattr_default)
 
27
#  define pthread_condattr_default ((pthread_condattr_t *)NULL)
 
28
#endif
 
29
 
 
30
/* Whether or not to use semaphores directly rather than emulating them with
 
31
 * mutexes and condition variables:
 
32
 */
 
33
#if defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES)
 
34
#  define USE_SEMAPHORES
 
35
#else
 
36
#  undef USE_SEMAPHORES
 
37
#endif
 
38
 
 
39
 
 
40
#define CHECK_STATUS(name)  if (status != 0) { perror(name); error = 1; }
 
41
 
 
42
/********************* structs ***********/
 
43
 
 
44
#ifdef USE_SEMAPHORES
 
45
 
 
46
#include <semaphore.h>
 
47
 
 
48
struct RPyOpaque_ThreadLock {
 
49
        sem_t sem;
 
50
        int initialized;
 
51
};
 
52
 
 
53
#define RPyOpaque_INITEXPR_ThreadLock  { { /* sem */ }, 0 }
 
54
 
 
55
#else                                      /* no semaphores */
 
56
 
 
57
/* A pthread mutex isn't sufficient to model the Python lock type
 
58
   (see explanations in CPython's Python/thread_pthread.h */
 
59
struct RPyOpaque_ThreadLock {
 
60
        char             locked; /* 0=unlocked, 1=locked */
 
61
        char             initialized;
 
62
        /* a <cond, mutex> pair to handle an acquire of a locked lock */
 
63
        pthread_cond_t   lock_released;
 
64
        pthread_mutex_t  mut;
 
65
};
 
66
 
 
67
#define RPyOpaque_INITEXPR_ThreadLock  {        \
 
68
                0, 0,                           \
 
69
                PTHREAD_COND_INITIALIZER,       \
 
70
                PTHREAD_MUTEX_INITIALIZER       \
 
71
        }
 
72
#endif                                     /* no semaphores */
 
73
 
 
74
/* prototypes */
 
75
 
 
76
long RPyThreadGetIdent(void);
 
77
long RPyThreadStart(void (*func)(void *), void *arg);
 
78
int RPyThreadLockInit(struct RPyOpaque_ThreadLock *lock);
 
79
void RPyOpaqueDealloc_ThreadLock(struct RPyOpaque_ThreadLock *lock);
 
80
int RPyThreadAcquireLock(struct RPyOpaque_ThreadLock *lock, int waitflag);
 
81
void RPyThreadReleaseLock(struct RPyOpaque_ThreadLock *lock);
 
82
int RPyThreadLockInit(struct RPyOpaque_ThreadLock *lock);
 
83
void RPyOpaqueDealloc_ThreadLock(struct RPyOpaque_ThreadLock *lock);
 
84
int RPyThreadAcquireLock(struct RPyOpaque_ThreadLock *lock, int waitflag);
 
85
void RPyThreadReleaseLock(struct RPyOpaque_ThreadLock *lock);
 
86
 
 
87
 
 
88
/* implementations */
 
89
 
 
90
#ifndef PYPY_NOT_MAIN_FILE
 
91
 
 
92
/* XXX This implementation is considered (to quote Tim Peters) "inherently
 
93
   hosed" because:
 
94
     - It does not guarantee the promise that a non-zero integer is returned.
 
95
     - The cast to long is inherently unsafe.
 
96
     - It is not clear that the 'volatile' (for AIX?) and ugly casting in the
 
97
       latter return statement (for Alpha OSF/1) are any longer necessary.
 
98
*/
 
99
long RPyThreadGetIdent(void)
 
100
{
 
101
        volatile pthread_t threadid;
 
102
        /* Jump through some hoops for Alpha OSF/1 */
 
103
        threadid = pthread_self();
 
104
#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
 
105
        return (long) threadid;
 
106
#else
 
107
        return (long) *(long *) &threadid;
 
108
#endif
 
109
}
 
110
 
 
111
long RPyThreadStart(void (*func)(void *), void *arg)
 
112
{
 
113
        pthread_t th;
 
114
        int status;
 
115
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
 
116
        pthread_attr_t attrs;
 
117
#endif
 
118
 
 
119
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
 
120
        pthread_attr_init(&attrs);
 
121
#endif
 
122
#ifdef THREAD_STACK_SIZE
 
123
        pthread_attr_setstacksize(&attrs, THREAD_STACK_SIZE);
 
124
#endif
 
125
#if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) && !defined(__FreeBSD__)
 
126
        pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
 
127
#endif
 
128
 
 
129
        status = pthread_create(&th, 
 
130
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
 
131
                                 &attrs,
 
132
#else
 
133
                                 (pthread_attr_t*)NULL,
 
134
#endif
 
135
                                 (void* (*)(void *))func,
 
136
                                 (void *)arg
 
137
                                 );
 
138
 
 
139
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
 
140
        pthread_attr_destroy(&attrs);
 
141
#endif
 
142
        if (status != 0)
 
143
            return -1;
 
144
 
 
145
        pthread_detach(th);
 
146
 
 
147
#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
 
148
        return (long) th;
 
149
#else
 
150
        return (long) *(long *) &th;
 
151
#endif
 
152
}
 
153
 
 
154
 
 
155
/************************************************************/
 
156
#ifdef USE_SEMAPHORES
 
157
/************************************************************/
 
158
 
 
159
#include <semaphore.h>
 
160
 
 
161
int RPyThreadLockInit(struct RPyOpaque_ThreadLock *lock)
 
162
{
 
163
        int status, error = 0;
 
164
        lock->initialized = 0;
 
165
        status = sem_init(&lock->sem, 0, 1);
 
166
        CHECK_STATUS("sem_init");
 
167
        if (error)
 
168
                return 0;
 
169
        lock->initialized = 1;
 
170
        return 1;
 
171
}
 
172
 
 
173
void RPyOpaqueDealloc_ThreadLock(struct RPyOpaque_ThreadLock *lock)
 
174
{
 
175
        int status, error = 0;
 
176
        if (lock->initialized) {
 
177
                status = sem_destroy(&lock->sem);
 
178
                CHECK_STATUS("sem_destroy");
 
179
                /* 'error' is ignored;
 
180
                   CHECK_STATUS already printed an error message */
 
181
        }
 
182
}
 
183
 
 
184
/*
 
185
 * As of February 2002, Cygwin thread implementations mistakenly report error
 
186
 * codes in the return value of the sem_ calls (like the pthread_ functions).
 
187
 * Correct implementations return -1 and put the code in errno. This supports
 
188
 * either.
 
189
 */
 
190
static int
 
191
rpythread_fix_status(int status)
 
192
{
 
193
        return (status == -1) ? errno : status;
 
194
}
 
195
 
 
196
int RPyThreadAcquireLock(struct RPyOpaque_ThreadLock *lock, int waitflag)
 
197
{
 
198
        int success;
 
199
        sem_t *thelock = &lock->sem;
 
200
        int status, error = 0;
 
201
 
 
202
        do {
 
203
                if (waitflag)
 
204
                        status = rpythread_fix_status(sem_wait(thelock));
 
205
                else
 
206
                        status = rpythread_fix_status(sem_trywait(thelock));
 
207
        } while (status == EINTR); /* Retry if interrupted by a signal */
 
208
 
 
209
        if (waitflag) {
 
210
                CHECK_STATUS("sem_wait");
 
211
        } else if (status != EAGAIN) {
 
212
                CHECK_STATUS("sem_trywait");
 
213
        }
 
214
        
 
215
        success = (status == 0) ? 1 : 0;
 
216
        return success;
 
217
}
 
218
 
 
219
void RPyThreadReleaseLock(struct RPyOpaque_ThreadLock *lock)
 
220
{
 
221
        sem_t *thelock = &lock->sem;
 
222
        int status, error = 0;
 
223
 
 
224
        status = sem_post(thelock);
 
225
        CHECK_STATUS("sem_post");
 
226
}
 
227
 
 
228
/************************************************************/
 
229
#else                                      /* no semaphores */
 
230
/************************************************************/
 
231
 
 
232
int RPyThreadLockInit(struct RPyOpaque_ThreadLock *lock)
 
233
{
 
234
        int status, error = 0;
 
235
 
 
236
        lock->initialized = 0;
 
237
        lock->locked = 0;
 
238
 
 
239
        status = pthread_mutex_init(&lock->mut,
 
240
                                    pthread_mutexattr_default);
 
241
        CHECK_STATUS("pthread_mutex_init");
 
242
 
 
243
        status = pthread_cond_init(&lock->lock_released,
 
244
                                   pthread_condattr_default);
 
245
        CHECK_STATUS("pthread_cond_init");
 
246
 
 
247
        if (error)
 
248
                return 0;
 
249
        lock->initialized = 1;
 
250
        return 1;
 
251
}
 
252
 
 
253
void RPyOpaqueDealloc_ThreadLock(struct RPyOpaque_ThreadLock *lock)
 
254
{
 
255
        int status, error = 0;
 
256
        if (lock->initialized) {
 
257
                status = pthread_mutex_destroy(&lock->mut);
 
258
                CHECK_STATUS("pthread_mutex_destroy");
 
259
 
 
260
                status = pthread_cond_destroy(&lock->lock_released);
 
261
                CHECK_STATUS("pthread_cond_destroy");
 
262
 
 
263
                /* 'error' is ignored;
 
264
                   CHECK_STATUS already printed an error message */
 
265
        }
 
266
}
 
267
 
 
268
int RPyThreadAcquireLock(struct RPyOpaque_ThreadLock *lock, int waitflag)
 
269
{
 
270
        int success;
 
271
        int status, error = 0;
 
272
 
 
273
        status = pthread_mutex_lock( &lock->mut );
 
274
        CHECK_STATUS("pthread_mutex_lock[1]");
 
275
        success = lock->locked == 0;
 
276
 
 
277
        if ( !success && waitflag ) {
 
278
                /* continue trying until we get the lock */
 
279
 
 
280
                /* mut must be locked by me -- part of the condition
 
281
                 * protocol */
 
282
                while ( lock->locked ) {
 
283
                        status = pthread_cond_wait(&lock->lock_released,
 
284
                                                   &lock->mut);
 
285
                        CHECK_STATUS("pthread_cond_wait");
 
286
                }
 
287
                success = 1;
 
288
        }
 
289
        if (success) lock->locked = 1;
 
290
        status = pthread_mutex_unlock( &lock->mut );
 
291
        CHECK_STATUS("pthread_mutex_unlock[1]");
 
292
 
 
293
        if (error) success = 0;
 
294
        return success;
 
295
}
 
296
 
 
297
void RPyThreadReleaseLock(struct RPyOpaque_ThreadLock *lock)
 
298
{
 
299
        int status, error = 0;
 
300
 
 
301
        status = pthread_mutex_lock( &lock->mut );
 
302
        CHECK_STATUS("pthread_mutex_lock[3]");
 
303
 
 
304
        lock->locked = 0;
 
305
 
 
306
        status = pthread_mutex_unlock( &lock->mut );
 
307
        CHECK_STATUS("pthread_mutex_unlock[3]");
 
308
 
 
309
        /* wake up someone (anyone, if any) waiting on the lock */
 
310
        status = pthread_cond_signal( &lock->lock_released );
 
311
        CHECK_STATUS("pthread_cond_signal");
 
312
}
 
313
 
 
314
/************************************************************/
 
315
#endif                                     /* no semaphores */
 
316
/************************************************************/
 
317
 
 
318
 
 
319
/* Thread-local storage */
 
320
#define RPyThreadTLS    pthread_key_t
 
321
 
 
322
char *RPyThreadTLS_Create(RPyThreadTLS *result)
 
323
{
 
324
        if (pthread_key_create(result, NULL) != 0)
 
325
                return "out of thread-local storage keys";
 
326
        else
 
327
                return NULL;
 
328
}
 
329
 
 
330
#define RPyThreadTLS_Get(key)           pthread_getspecific(key)
 
331
#define RPyThreadTLS_Set(key, value)    pthread_setspecific(key, value)
 
332
 
 
333
 
 
334
#endif /* PYPY_NOT_MAIN_FILE */