1 #include <minix/mthread.h>
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
);
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)
15 #define MAIN_COND mainthread.m_cond
17 /*===========================================================================*
18 * mthread_init_valid_conditions *
19 *===========================================================================*/
20 void mthread_init_valid_conditions(void)
23 /* Initialize condition variable list */
24 vc_front
= vc_rear
= NULL
;
29 /*===========================================================================*
31 *===========================================================================*/
33 static void mthread_cond_add(c
)
36 /* Add condition to list of valid, initialized conditions */
38 if (vc_front
== NULL
) { /* Empty list */
42 vc_rear
->mc_next
= *c
;
43 (*c
)->mc_prev
= vc_rear
;
51 /*===========================================================================*
52 * mthread_cond_broadcast *
53 *===========================================================================*/
54 int mthread_cond_broadcast(cond
)
57 /* Signal all threads waiting for condition 'cond'. */
61 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
65 else if (!mthread_cond_valid(cond
))
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
)
82 /*===========================================================================*
83 * mthread_cond_destroy *
84 *===========================================================================*/
85 int mthread_cond_destroy(cond
)
88 /* Destroy a condition variable. Make sure it's not in use */
92 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
96 else if (!mthread_cond_valid(cond
))
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
)
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
)
110 /* Not in use; invalidate it. */
111 mthread_cond_remove(cond
);
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 */
133 else if (cattr
!= NULL
)
136 #ifdef MTHREAD_STRICT
137 else if (mthread_cond_valid(cond
))
138 /* Already initialized */
141 else if ((c
= malloc(sizeof(struct __mthread_cond
))) == NULL
)
145 *cond
= (mthread_cond_t
) c
;
146 mthread_cond_add(cond
);
152 /*===========================================================================*
153 * mthread_cond_remove *
154 *===========================================================================*/
155 #ifdef MTHREAD_STRICT
156 static void mthread_cond_remove(c
)
159 /* Remove condition from list of valid, initialized conditions */
161 if ((*c
)->mc_prev
== NULL
)
162 vc_front
= (*c
)->mc_next
;
164 (*c
)->mc_prev
->mc_next
= (*c
)->mc_next
;
166 if ((*c
)->mc_next
== NULL
)
167 vc_rear
= (*c
)->mc_prev
;
169 (*c
)->mc_next
->mc_prev
= (*c
)->mc_prev
;
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. */
184 MTHREAD_CHECK_INIT(); /* Make sure libmthread is initialized */
188 else if (!mthread_cond_valid(cond
))
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
);
207 /*===========================================================================*
208 * mthread_cond_valid *
209 *===========================================================================*/
210 #ifdef MTHREAD_STRICT
211 static int mthread_cond_valid(c
)
214 /* Check to see if cond is on the list of valid conditions */
215 struct __mthread_cond
*loopitem
;
217 MTHREAD_CHECK_INIT();
221 while (loopitem
!= NULL
) {
225 loopitem
= loopitem
->mc_next
;
232 /*===========================================================================*
233 * mthread_cond_verify *
234 *===========================================================================*/
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
);
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 */
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
)
264 c
= (struct __mthread_cond
*) *cond
;
265 m
= (struct __mthread_mutex
*) *mutex
;
267 if (!mthread_cond_valid(cond
) || !mthread_mutex_valid(mutex
))
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 */
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)