Remove building with NOCRYPTO option
[minix3.git] / minix / lib / libmthread / condition.c
blob3488a5f7c5530879f754bc0c8d3bd4790aa354b0
1 #include <minix/mthread.h>
2 #include "global.h"
3 #include "proto.h"
5 #ifdef MTHREAD_STRICT
6 static struct __mthread_cond *vc_front, *vc_rear;
7 static void mthread_cond_add(mthread_cond_t *c);
8 static void mthread_cond_remove(mthread_cond_t *c);
9 static int mthread_cond_valid(mthread_cond_t *c);
10 #else
11 # define mthread_cond_add(c) ((*c)->mc_magic = MTHREAD_INIT_MAGIC)
12 # define mthread_cond_remove(c) ((*c)->mc_magic = MTHREAD_NOT_INUSE)
13 # define mthread_cond_valid(c) ((*c)->mc_magic == MTHREAD_INIT_MAGIC)
14 #endif
15 #define MAIN_COND mainthread.m_cond
17 /*===========================================================================*
18 * mthread_init_valid_conditions *
19 *===========================================================================*/
20 void mthread_init_valid_conditions(void)
22 #ifdef MTHREAD_STRICT
23 /* Initialize condition variable list */
24 vc_front = vc_rear = NULL;
25 #endif
29 /*===========================================================================*
30 * mthread_cond_add *
31 *===========================================================================*/
32 #ifdef MTHREAD_STRICT
33 static void mthread_cond_add(c)
34 mthread_cond_t *c;
36 /* Add condition to list of valid, initialized conditions */
38 if (vc_front == NULL) { /* Empty list */
39 vc_front = *c;
40 (*c)->mc_prev = NULL;
41 } else {
42 vc_rear->mc_next = *c;
43 (*c)->mc_prev = vc_rear;
46 (*c)->mc_next = NULL;
47 vc_rear = *c;
49 #endif
51 /*===========================================================================*
52 * mthread_cond_broadcast *
53 *===========================================================================*/
54 int mthread_cond_broadcast(cond)
55 mthread_cond_t *cond;
57 /* Signal all threads waiting for condition 'cond'. */
58 mthread_thread_t t;
59 mthread_tcb_t *tcb;
61 if (cond == NULL)
62 return(EINVAL);
63 else if (!mthread_cond_valid(cond))
64 return(EINVAL);
66 tcb = mthread_find_tcb(MAIN_THREAD);
67 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond)
68 mthread_unsuspend(MAIN_THREAD);
70 for (t = (mthread_thread_t) 0; t < no_threads; t++) {
71 tcb = mthread_find_tcb(t);
72 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond)
73 mthread_unsuspend(t);
76 return(0);
80 /*===========================================================================*
81 * mthread_cond_destroy *
82 *===========================================================================*/
83 int mthread_cond_destroy(cond)
84 mthread_cond_t *cond;
86 /* Destroy a condition variable. Make sure it's not in use */
87 mthread_thread_t t;
88 mthread_tcb_t *tcb;
90 if (cond == NULL)
91 return(EINVAL);
92 else if (!mthread_cond_valid(cond))
93 return(EINVAL);
95 /* Is another thread currently using this condition variable? */
96 tcb = mthread_find_tcb(MAIN_THREAD);
97 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond)
98 return(EBUSY);
100 for (t = (mthread_thread_t) 0; t < no_threads; t++) {
101 tcb = mthread_find_tcb(t);
102 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond)
103 return(EBUSY);
106 /* Not in use; invalidate it. */
107 mthread_cond_remove(cond);
108 free(*cond);
109 *cond = NULL;
111 return(0);
115 /*===========================================================================*
116 * mthread_cond_init *
117 *===========================================================================*/
118 int mthread_cond_init(cond, cattr)
119 mthread_cond_t *cond;
120 mthread_condattr_t *cattr;
122 /* Initialize condition variable to a known state. cattr is ignored */
123 struct __mthread_cond *c;
125 if (cond == NULL)
126 return(EINVAL);
127 else if (cattr != NULL)
128 return(ENOSYS);
130 #ifdef MTHREAD_STRICT
131 else if (mthread_cond_valid(cond))
132 /* Already initialized */
133 return(EBUSY);
134 #endif
135 else if ((c = malloc(sizeof(struct __mthread_cond))) == NULL)
136 return(ENOMEM);
138 c->mc_mutex = NULL;
139 *cond = (mthread_cond_t) c;
140 mthread_cond_add(cond);
142 return(0);
146 /*===========================================================================*
147 * mthread_cond_remove *
148 *===========================================================================*/
149 #ifdef MTHREAD_STRICT
150 static void mthread_cond_remove(c)
151 mthread_cond_t *c;
153 /* Remove condition from list of valid, initialized conditions */
155 if ((*c)->mc_prev == NULL)
156 vc_front = (*c)->mc_next;
157 else
158 (*c)->mc_prev->mc_next = (*c)->mc_next;
160 if ((*c)->mc_next == NULL)
161 vc_rear = (*c)->mc_prev;
162 else
163 (*c)->mc_next->mc_prev = (*c)->mc_prev;
166 #endif
168 /*===========================================================================*
169 * mthread_cond_signal *
170 *===========================================================================*/
171 int mthread_cond_signal(cond)
172 mthread_cond_t *cond;
174 /* Signal a thread that condition 'cond' was met. Just a single thread. */
175 mthread_thread_t t;
176 mthread_tcb_t *tcb;
178 if (cond == NULL)
179 return(EINVAL);
180 else if (!mthread_cond_valid(cond))
181 return(EINVAL);
183 tcb = mthread_find_tcb(MAIN_THREAD);
184 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond)
185 mthread_unsuspend(MAIN_THREAD);
187 for (t = (mthread_thread_t) 0; t < no_threads; t++) {
188 tcb = mthread_find_tcb(t);
189 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond){
190 mthread_unsuspend(t);
191 break;
195 return(0);
199 /*===========================================================================*
200 * mthread_cond_valid *
201 *===========================================================================*/
202 #ifdef MTHREAD_STRICT
203 static int mthread_cond_valid(c)
204 mthread_cond_t *c;
206 /* Check to see if cond is on the list of valid conditions */
207 struct __mthread_cond *loopitem;
209 loopitem = vc_front;
211 while (loopitem != NULL) {
212 if (loopitem == *c)
213 return(1);
215 loopitem = loopitem->mc_next;
218 return(0);
220 #endif
222 /*===========================================================================*
223 * mthread_cond_verify *
224 *===========================================================================*/
225 #ifdef MDEBUG
226 int mthread_cond_verify(void)
228 /* Return true in case no condition variables are in use. */
230 return(vc_front == NULL);
232 #endif
235 /*===========================================================================*
236 * mthread_cond_wait *
237 *===========================================================================*/
238 int mthread_cond_wait(cond, mutex)
239 mthread_cond_t *cond;
240 mthread_mutex_t *mutex;
242 /* Wait for a condition to be signaled */
243 mthread_tcb_t *tcb;
244 struct __mthread_cond *c;
245 struct __mthread_mutex *m;
247 if (cond == NULL || mutex == NULL)
248 return(EINVAL);
250 c = (struct __mthread_cond *) *cond;
251 m = (struct __mthread_mutex *) *mutex;
253 if (!mthread_cond_valid(cond) || !mthread_mutex_valid(mutex))
254 return(EINVAL);
256 c->mc_mutex = m; /* Remember we're using this mutex in a cond_wait */
257 if (mthread_mutex_unlock(mutex) != 0) /* Fails when we're not the owner */
258 return(-1);
260 tcb = mthread_find_tcb(current_thread);
261 tcb->m_cond = c; /* Register condition variable. */
262 mthread_suspend(MS_CONDITION);
264 /* When execution returns here, the condition was met. Lock mutex again. */
265 c->mc_mutex = NULL; /* Forget about this mutex */
266 tcb->m_cond = NULL; /* ... and condition var */
267 if (mthread_mutex_lock(mutex) != 0)
268 return(-1);
270 return(0);
273 /* pthread compatibility layer. */
274 __weak_alias(pthread_cond_init, mthread_cond_init)