mkfs: drop support for zone != block
[minix.git] / lib / libmthread / condition.c
blobec3bcc43dc350314a4a9fbfb8aaf313dc5345b45
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 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
63 if (cond == NULL)
64 return(EINVAL);
65 else if (!mthread_cond_valid(cond))
66 return(EINVAL);
68 tcb = mthread_find_tcb(MAIN_THREAD);
69 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond)
70 mthread_unsuspend(MAIN_THREAD);
72 for (t = (mthread_thread_t) 0; t < no_threads; t++) {
73 tcb = mthread_find_tcb(t);
74 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond)
75 mthread_unsuspend(t);
78 return(0);
82 /*===========================================================================*
83 * mthread_cond_destroy *
84 *===========================================================================*/
85 int mthread_cond_destroy(cond)
86 mthread_cond_t *cond;
88 /* Destroy a condition variable. Make sure it's not in use */
89 mthread_thread_t t;
90 mthread_tcb_t *tcb;
92 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
94 if (cond == NULL)
95 return(EINVAL);
96 else if (!mthread_cond_valid(cond))
97 return(EINVAL);
99 /* Is another thread currently using this condition variable? */
100 tcb = mthread_find_tcb(MAIN_THREAD);
101 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond)
102 return(EBUSY);
104 for (t = (mthread_thread_t) 0; t < no_threads; t++) {
105 tcb = mthread_find_tcb(t);
106 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond)
107 return(EBUSY);
110 /* Not in use; invalidate it. */
111 mthread_cond_remove(cond);
112 free(*cond);
113 *cond = NULL;
115 return(0);
119 /*===========================================================================*
120 * mthread_cond_init *
121 *===========================================================================*/
122 int mthread_cond_init(cond, cattr)
123 mthread_cond_t *cond;
124 mthread_condattr_t *cattr;
126 /* Initialize condition variable to a known state. cattr is ignored */
127 struct __mthread_cond *c;
129 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
131 if (cond == NULL)
132 return(EINVAL);
133 else if (cattr != NULL)
134 return(ENOSYS);
136 #ifdef MTHREAD_STRICT
137 else if (mthread_cond_valid(cond))
138 /* Already initialized */
139 return(EBUSY);
140 #endif
141 else if ((c = malloc(sizeof(struct __mthread_cond))) == NULL)
142 return(ENOMEM);
144 c->mc_mutex = NULL;
145 *cond = (mthread_cond_t) c;
146 mthread_cond_add(cond);
148 return(0);
152 /*===========================================================================*
153 * mthread_cond_remove *
154 *===========================================================================*/
155 #ifdef MTHREAD_STRICT
156 static void mthread_cond_remove(c)
157 mthread_cond_t *c;
159 /* Remove condition from list of valid, initialized conditions */
161 if ((*c)->mc_prev == NULL)
162 vc_front = (*c)->mc_next;
163 else
164 (*c)->mc_prev->mc_next = (*c)->mc_next;
166 if ((*c)->mc_next == NULL)
167 vc_rear = (*c)->mc_prev;
168 else
169 (*c)->mc_next->mc_prev = (*c)->mc_prev;
172 #endif
174 /*===========================================================================*
175 * mthread_cond_signal *
176 *===========================================================================*/
177 int mthread_cond_signal(cond)
178 mthread_cond_t *cond;
180 /* Signal a thread that condition 'cond' was met. Just a single thread. */
181 mthread_thread_t t;
182 mthread_tcb_t *tcb;
184 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
186 if (cond == NULL)
187 return(EINVAL);
188 else if (!mthread_cond_valid(cond))
189 return(EINVAL);
191 tcb = mthread_find_tcb(MAIN_THREAD);
192 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond)
193 mthread_unsuspend(MAIN_THREAD);
195 for (t = (mthread_thread_t) 0; t < no_threads; t++) {
196 tcb = mthread_find_tcb(t);
197 if (tcb->m_state == MS_CONDITION && tcb->m_cond == *cond){
198 mthread_unsuspend(t);
199 break;
203 return(0);
207 /*===========================================================================*
208 * mthread_cond_valid *
209 *===========================================================================*/
210 #ifdef MTHREAD_STRICT
211 static int mthread_cond_valid(c)
212 mthread_cond_t *c;
214 /* Check to see if cond is on the list of valid conditions */
215 struct __mthread_cond *loopitem;
217 MTHREAD_CHECK_INIT();
219 loopitem = vc_front;
221 while (loopitem != NULL) {
222 if (loopitem == *c)
223 return(1);
225 loopitem = loopitem->mc_next;
228 return(0);
230 #endif
232 /*===========================================================================*
233 * mthread_cond_verify *
234 *===========================================================================*/
235 #ifdef MDEBUG
236 int mthread_cond_verify(void)
238 /* Return true in case no condition variables are in use. */
240 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
242 return(vc_front == NULL);
244 #endif
247 /*===========================================================================*
248 * mthread_cond_wait *
249 *===========================================================================*/
250 int mthread_cond_wait(cond, mutex)
251 mthread_cond_t *cond;
252 mthread_mutex_t *mutex;
254 /* Wait for a condition to be signaled */
255 mthread_tcb_t *tcb;
256 struct __mthread_cond *c;
257 struct __mthread_mutex *m;
259 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
261 if (cond == NULL || mutex == NULL)
262 return(EINVAL);
264 c = (struct __mthread_cond *) *cond;
265 m = (struct __mthread_mutex *) *mutex;
267 if (!mthread_cond_valid(cond) || !mthread_mutex_valid(mutex))
268 return(EINVAL);
270 c->mc_mutex = m; /* Remember we're using this mutex in a cond_wait */
271 if (mthread_mutex_unlock(mutex) != 0) /* Fails when we're not the owner */
272 return(-1);
274 tcb = mthread_find_tcb(current_thread);
275 tcb->m_cond = c; /* Register condition variable. */
276 mthread_suspend(MS_CONDITION);
278 /* When execution returns here, the condition was met. Lock mutex again. */
279 c->mc_mutex = NULL; /* Forget about this mutex */
280 tcb->m_cond = NULL; /* ... and condition var */
281 if (mthread_mutex_lock(mutex) != 0)
282 return(-1);
284 return(0);