3 #include <barrelfish/barrelfish.h>
7 typedef void (*destructor_fn_t)(void *);
8 typedef void *(*start_fn_t)(void *);
10 struct pthread_mutex_attr
18 struct pthread_mutex {
19 struct thread_mutex mutex;
21 struct pthread_mutex_attr attrs;
28 struct thread_cond cond;
31 #define PTHREADS_RWLOCK_MAGIC 0xdeadbeef
35 pthread_mutex_t mtxExclusiveAccess;
36 pthread_mutex_t mtxSharedAccessCompleted;
37 pthread_cond_t cndSharedAccessCompleted;
38 int nSharedAccessCount;
39 int nExclusiveAccessCount;
40 int nCompletedSharedAccessCount;
46 struct thread *thread;
47 const void *keys[PTHREAD_KEYS_MAX];
53 static pthread_key_t key_index = 0;
54 static struct thread_mutex key_mutex = THREAD_MUTEX_INITIALIZER;
55 static destructor_fn_t destructors[PTHREAD_KEYS_MAX];
57 static int start_pthread(void *arg)
59 struct pthread *myself = arg;
62 thread_set_tls_key(0, myself);
65 myself->retval = myself->start_fn(myself->arg);
67 // Call all key destructors
68 for(pthread_key_t i = 0; i < key_index; i++) {
69 if ((destructors[i] != NULL) && (myself->keys[i] != NULL)) {
70 void *value = (void *) myself->keys[i];
71 myself->keys[i] = NULL;
72 destructors[i](value);
76 // 'myself' data structure is freed when joined with this thread
80 int pthread_create(pthread_t *pthread, const pthread_attr_t *attr,
81 void *(*start_routine) (void *), void *arg)
83 *pthread = malloc(sizeof(struct pthread));
84 assert(*pthread != NULL);
85 memset(*pthread, 0, sizeof(struct pthread));
87 // XXX: attributes are ignored.
88 (*pthread)->start_fn = start_routine;
89 (*pthread)->arg = arg;
92 (*pthread)->thread = thread_create(start_pthread, *pthread);
96 pthread_t pthread_self(void)
98 pthread_t self = thread_get_tls_key(0);
100 // If NULL, we're the first thread, not created via pthreads.
101 // Create a pthread structure.
103 struct pthread *myself = malloc(sizeof(struct pthread));
104 assert(myself != NULL);
105 memset(myself, 0, sizeof(struct pthread));
106 myself->thread = thread_self();
107 thread_set_tls_key(0, myself);
114 void *pthread_getspecific(pthread_key_t key)
116 if(key >= PTHREAD_KEYS_MAX) {
120 return (void *)pthread_self()->keys[key];
123 int pthread_setspecific(pthread_key_t key, const void *val)
125 if(key >= PTHREAD_KEYS_MAX) {
129 pthread_self()->keys[key] = val;
133 int pthread_attr_init(pthread_attr_t *attr)
139 static struct thread_mutex mutex_mutex = THREAD_MUTEX_INITIALIZER;
141 int pthread_mutex_init(pthread_mutex_t *mutex,
142 const pthread_mutexattr_t *attr)
144 // XXX: Attributes ignored.
145 *mutex = malloc(sizeof(struct pthread_mutex));
150 thread_mutex_init(&(*mutex)->mutex);
151 (*mutex)->locked = 0;
153 debug_printf("kind = %u\n", (*attr)->kind);
154 memcpy(&(*mutex)->attrs, *attr, sizeof(struct pthread_mutex_attr));
156 (*mutex)->attrs.kind = PTHREAD_MUTEX_NORMAL;
157 (*mutex)->attrs.robustness = 0;
158 (*mutex)->attrs.pshared = PTHREAD_PROCESS_PRIVATE;
163 int pthread_mutex_destroy(pthread_mutex_t *mutex)
165 if(*mutex != PTHREAD_MUTEX_INITIALIZER) {
172 int pthread_mutex_lock(pthread_mutex_t *mutex)
174 thread_mutex_lock(&mutex_mutex);
176 if(*mutex == PTHREAD_MUTEX_INITIALIZER) {
177 pthread_mutex_init(mutex, NULL);
181 thread_mutex_unlock(&mutex_mutex);
182 if ((*mutex)->attrs.kind == PTHREAD_MUTEX_RECURSIVE) {
183 thread_mutex_lock_nested(&(*mutex)->mutex);
185 thread_mutex_lock(&(*mutex)->mutex);
190 int pthread_mutex_unlock(pthread_mutex_t *mutex)
192 thread_mutex_lock(&mutex_mutex);
194 if(*mutex == PTHREAD_MUTEX_INITIALIZER) {
195 pthread_mutex_init(mutex, NULL);
198 if((*mutex)->locked == 0) {
199 thread_mutex_unlock(&mutex_mutex);
204 thread_mutex_unlock(&mutex_mutex);
205 thread_mutex_unlock(&(*mutex)->mutex);
209 int pthread_mutex_trylock(pthread_mutex_t *mutex)
211 thread_mutex_lock(&mutex_mutex);
213 if(*mutex == PTHREAD_MUTEX_INITIALIZER) {
214 pthread_mutex_init(mutex, NULL);
217 thread_mutex_unlock(&mutex_mutex);
219 int retval = (thread_mutex_trylock(&(*mutex)->mutex) ? 0 : EBUSY);
221 if(retval != EBUSY) {
222 thread_mutex_lock(&mutex_mutex);
224 thread_mutex_unlock(&mutex_mutex);
230 int pthread_cond_init(pthread_cond_t *cond,
231 const pthread_condattr_t *attr)
233 *cond = malloc(sizeof(struct pthread_cond));
238 thread_cond_init(&(*cond)->cond);
242 int pthread_cond_signal(pthread_cond_t *cond)
244 thread_mutex_lock(&mutex_mutex);
245 if(*cond == PTHREAD_COND_INITIALIZER) {
246 pthread_cond_init(cond, NULL);
248 thread_mutex_unlock(&mutex_mutex);
250 thread_cond_signal(&(*cond)->cond);
254 int pthread_cond_timedwait(pthread_cond_t *cond,
255 pthread_mutex_t *mutex,
256 const struct timespec *timeout)
258 thread_mutex_lock(&mutex_mutex);
259 if(*cond == PTHREAD_COND_INITIALIZER) {
260 pthread_cond_init(cond, NULL);
262 if(*mutex == PTHREAD_MUTEX_INITIALIZER) {
263 pthread_mutex_init(mutex, NULL);
265 thread_mutex_unlock(&mutex_mutex);
271 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
273 thread_mutex_lock(&mutex_mutex);
274 if(*cond == PTHREAD_COND_INITIALIZER) {
275 pthread_cond_init(cond, NULL);
277 if(*mutex == PTHREAD_MUTEX_INITIALIZER) {
278 pthread_mutex_init(mutex, NULL);
280 thread_mutex_unlock(&mutex_mutex);
282 thread_cond_wait(&(*cond)->cond, &(*mutex)->mutex);
286 int pthread_cond_broadcast(pthread_cond_t *cond)
288 thread_mutex_lock(&mutex_mutex);
290 if(*cond == PTHREAD_COND_INITIALIZER) {
291 pthread_cond_init(cond, NULL);
293 thread_mutex_unlock(&mutex_mutex);
295 thread_cond_broadcast(&(*cond)->cond);
300 int pthread_cond_destroy(pthread_cond_t *cond)
306 int pthread_join(pthread_t thread, void **retval)
308 errval_t err = thread_join(thread->thread, NULL);
309 assert(err_is_ok(err));
311 if (retval != NULL) {
312 *retval = thread->retval;
318 int pthread_key_create(pthread_key_t *key,
319 void (*callback) (void *))
323 thread_mutex_lock(&key_mutex);
325 if(key_index == PTHREAD_KEYS_MAX) {
331 destructors[key_index] = callback;
335 thread_mutex_unlock(&key_mutex);
339 int pthread_key_delete(pthread_key_t key)
341 thread_mutex_lock(&key_mutex);
344 if ((key < PTHREAD_KEYS_MAX) && (destructors[key] != NULL)) {
345 destructors[key] = NULL;
349 thread_mutex_unlock(&key_mutex);
353 int pthread_mutexattr_init(pthread_mutexattr_t *attr)
356 pthread_mutexattr_t ma;
358 ma = (pthread_mutexattr_t) calloc (1, sizeof (*ma));
364 ma->pshared = PTHREAD_PROCESS_PRIVATE;
365 ma->kind = PTHREAD_MUTEX_DEFAULT;
373 int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
377 if (attr == NULL || *attr == NULL) {
380 pthread_mutexattr_t ma = *attr;
389 int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr,
394 if ((attr != NULL && *attr != NULL) && (pshared != NULL)) {
395 *pshared = (*attr)->pshared;
404 int pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *type)
408 if (attr != NULL && *attr != NULL && type != NULL) {
409 *type = (*attr)->kind;
417 int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
421 if ((attr != NULL && *attr != NULL)) {
423 case PTHREAD_MUTEX_NORMAL:
424 case PTHREAD_MUTEX_RECURSIVE:
425 case PTHREAD_MUTEX_ERRORCHECK:
426 (*attr)->kind = type;
439 int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
443 if ((attr != NULL && *attr != NULL)
444 && ((pshared == PTHREAD_PROCESS_SHARED)
445 || (pshared == PTHREAD_PROCESS_PRIVATE))) {
447 if (pshared == PTHREAD_PROCESS_SHARED) {
448 #if !defined( _POSIX_THREAD_PROCESS_SHARED )
450 pshared = PTHREAD_PROCESS_PRIVATE;
453 #endif /* _POSIX_THREAD_PROCESS_SHARED */
458 (*attr)->pshared = pshared;
468 int pthread_equal(pthread_t pt1, pthread_t pt2)
470 if (pt1 == NULL && pt2 == NULL) {
473 return pt1->thread == pt2->thread;
476 int pthread_rwlock_init(pthread_rwlock_t *rwlock,
477 const pthread_rwlockattr_t *attr)
479 pthread_rwlock_t rwl;
481 rwl = calloc(1, sizeof(struct pthread_rwlock));
486 rwl->nMagic = PTHREADS_RWLOCK_MAGIC;
487 rwl->mtxExclusiveAccess = PTHREAD_MUTEX_INITIALIZER;
488 rwl->mtxSharedAccessCompleted = PTHREAD_MUTEX_INITIALIZER;
490 pthread_cond_init (&rwl->cndSharedAccessCompleted, NULL);
496 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
499 pthread_rwlock_t rwl;
501 if (rwlock == NULL || *rwlock == NULL) {
505 if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) {
506 result = pthread_rwlock_init(rwlock, NULL);
514 if (rwl->nMagic != PTHREADS_RWLOCK_MAGIC) {
518 if (rwl->nExclusiveAccessCount == 0) {
519 if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) {
523 if (++rwl->nCompletedSharedAccessCount == 0) {
524 result = pthread_cond_signal (&(rwl->cndSharedAccessCompleted));
527 result1 = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
529 rwl->nExclusiveAccessCount--;
530 result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted));
531 result1 = pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
534 return ((result != 0) ? result : result1);
537 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
540 pthread_rwlock_t rwl;
542 if (rwlock == NULL || *rwlock == NULL) {
546 if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) {
547 result = pthread_rwlock_init(rwlock, NULL);
555 if (rwl->nMagic != PTHREADS_RWLOCK_MAGIC) {
559 if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0) {
563 if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) {
564 (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
568 if (rwl->nExclusiveAccessCount == 0) {
569 if (rwl->nCompletedSharedAccessCount > 0) {
570 rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
571 rwl->nCompletedSharedAccessCount = 0;
574 if (rwl->nSharedAccessCount > 0) {
575 rwl->nCompletedSharedAccessCount = -rwl->nSharedAccessCount;
578 * This routine may be a cancelation point
579 * according to POSIX 1003.1j section 18.1.2.
581 // pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl);
584 result = pthread_cond_wait (&(rwl->cndSharedAccessCompleted),
585 &(rwl->mtxSharedAccessCompleted));
586 } while (result == 0 && rwl->nCompletedSharedAccessCount < 0);
588 //pthread_cleanup_pop ((result != 0) ? 1 : 0);
591 rwl->nSharedAccessCount = 0;
597 rwl->nExclusiveAccessCount++;
603 int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
606 pthread_rwlock_t rwl;
608 if (rwlock == NULL || *rwlock == NULL) {
613 * We do a quick check to see if we need to do more work
614 * to initialise a static rwlock. We check
615 * again inside the guarded section of ptw32_rwlock_check_need_init()
616 * to avoid race conditions.
618 if (*rwlock == PTHREAD_RWLOCK_INITIALIZER) {
619 result = pthread_rwlock_init(rwlock, NULL);
627 if (rwl->nMagic != PTHREADS_RWLOCK_MAGIC) {
631 if ((result = pthread_mutex_lock (&(rwl->mtxExclusiveAccess))) != 0) {
635 if (++rwl->nSharedAccessCount == 0xFFFFFFFF) {
636 if ((result = pthread_mutex_lock (&(rwl->mtxSharedAccessCompleted))) != 0) {
637 (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
641 rwl->nSharedAccessCount -= rwl->nCompletedSharedAccessCount;
642 rwl->nCompletedSharedAccessCount = 0;
644 if ((result = pthread_mutex_unlock (&(rwl->mtxSharedAccessCompleted))) != 0) {
645 (void) pthread_mutex_unlock (&(rwl->mtxExclusiveAccess));
650 return (pthread_mutex_unlock (&(rwl->mtxExclusiveAccess)));
654 int _pthread_once(pthread_once_t *ctrl, void (*init) (void))
656 if (ctrl == NULL || init == NULL) {
661 pthread_mutex_lock(&ctrl->mutex);
666 //pthread_cleanup_push(ptw32_mcs_lock_release, &node);
668 //pthread_cleanup_pop(0);
672 pthread_mutex_unlock(&ctrl->mutex);