Use run_once() macro for initialization
[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         mcs_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         sem_t *__sem = (sem_t*)arg;
43         pthread_t pthread = (pthread_t)uthread;
44         pthread->state = PTH_BLK_MUTEX;
45         TAILQ_INSERT_TAIL(&__sem->queue, pthread, next);
46         mcs_pdr_unlock(&__sem->lock);
47 }
48
49 int sem_wait (sem_t *__sem)
50 {
51         mcs_pdr_lock(&__sem->lock);
52         if(__sem->count > 0) {
53                 __sem->count--;
54                 mcs_pdr_unlock(&__sem->lock);
55         }
56         else {
57                 // We unlock in the body of __sem_block
58                 uthread_yield(TRUE, __sem_block, __sem);
59         }
60         return 0;
61 }
62
63 int sem_trywait (sem_t *__sem)
64 {
65         int ret = -1;
66         mcs_pdr_lock(&__sem->lock);
67         if(__sem->count > 0) {
68                 __sem->count--;
69                 ret = 0;
70         }
71         mcs_pdr_unlock(&__sem->lock);
72         return ret;
73 }
74
75 int sem_post (sem_t *__sem)
76 {
77         mcs_pdr_lock(&__sem->lock);
78         pthread_t pthread = TAILQ_FIRST(&__sem->queue);
79         if(pthread)
80                 TAILQ_REMOVE(&__sem->queue, pthread, next);
81         else
82                 __sem->count++; 
83         mcs_pdr_unlock(&__sem->lock);
84
85         if(pthread) {
86                 uthread_runnable((struct uthread*)pthread);
87         }
88         return 0;
89 }
90
91 int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval)
92 {
93         mcs_pdr_lock(&__sem->lock);
94         *__sval = __sem->count;
95         mcs_pdr_unlock(&__sem->lock);
96         return 0;
97 }
98