pthread_switch: fast user-level context switch
[akaros.git] / user / pthread / semaphore.c
1 #include <uthread.h>
2 #include <semaphore.h>
3 #include <mcs.h>
4 #include <stdio.h>
5
6 int sem_init (sem_t *__sem, int __pshared, unsigned int __value)
7 {
8         if(__pshared == TRUE) {
9                 printf("__pshared functionality of sem_init is not yet implemented!");
10                 return -1;
11         }
12         __sem->count = __value;
13         TAILQ_INIT(&__sem->queue);
14         spin_pdr_init(&__sem->lock);
15         return 0;
16 }
17
18 int sem_destroy (sem_t *__sem)
19 {
20         return 0;
21 }
22
23 sem_t *sem_open (__const char *__name, int __oflag, ...)
24 {
25         printf("sem_open is not yet implemented!");
26         return NULL;
27 }
28
29 int sem_close (sem_t *__sem)
30 {
31         printf("sem_close is not yet implemented!");
32         return -1;
33 }
34
35 int sem_unlink (__const char *__name)
36 {
37         printf("sem_unlink is not yet implemented!");
38         return -1;
39 }
40
41 static void __sem_block(struct uthread *uthread, void *arg)
42 {
43         sem_t *__sem = (sem_t*)arg;
44         pthread_t pthread = (pthread_t)uthread;
45         __pthread_generic_yield(pthread);
46         pthread->state = PTH_BLK_MUTEX;
47         TAILQ_INSERT_TAIL(&__sem->queue, pthread, next);
48         spin_pdr_unlock(&__sem->lock);
49 }
50
51 int sem_wait (sem_t *__sem)
52 {
53         spin_pdr_lock(&__sem->lock);
54         if(__sem->count > 0) {
55                 __sem->count--;
56                 spin_pdr_unlock(&__sem->lock);
57         }
58         else {
59                 // We unlock in the body of __sem_block
60                 uthread_yield(TRUE, __sem_block, __sem);
61         }
62         return 0;
63 }
64
65 int sem_trywait (sem_t *__sem)
66 {
67         int ret = -1;
68         spin_pdr_lock(&__sem->lock);
69         if(__sem->count > 0) {
70                 __sem->count--;
71                 ret = 0;
72         }
73         spin_pdr_unlock(&__sem->lock);
74         return ret;
75 }
76
77 int sem_post (sem_t *__sem)
78 {
79         spin_pdr_lock(&__sem->lock);
80         pthread_t pthread = TAILQ_FIRST(&__sem->queue);
81         if(pthread)
82                 TAILQ_REMOVE(&__sem->queue, pthread, next);
83         else
84                 __sem->count++; 
85         spin_pdr_unlock(&__sem->lock);
86
87         if(pthread) {
88                 uthread_runnable((struct uthread*)pthread);
89         }
90         return 0;
91 }
92
93 int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval)
94 {
95         spin_pdr_lock(&__sem->lock);
96         *__sval = __sem->count;
97         spin_pdr_unlock(&__sem->lock);
98         return 0;
99 }
100