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'. */
63 else if (!mthread_cond_valid(cond
))
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
)
80 /*===========================================================================*
81 * mthread_cond_destroy *
82 *===========================================================================*/
83 int mthread_cond_destroy(cond
)
86 /* Destroy a condition variable. Make sure it's not in use */
92 else if (!mthread_cond_valid(cond
))
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
)
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
)
106 /* Not in use; invalidate it. */
107 mthread_cond_remove(cond
);
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
;
127 else if (cattr
!= NULL
)
130 #ifdef MTHREAD_STRICT
131 else if (mthread_cond_valid(cond
))
132 /* Already initialized */
135 else if ((c
= malloc(sizeof(struct __mthread_cond
))) == NULL
)
139 *cond
= (mthread_cond_t
) c
;
140 mthread_cond_add(cond
);
146 /*===========================================================================*
147 * mthread_cond_remove *
148 *===========================================================================*/
149 #ifdef MTHREAD_STRICT
150 static void mthread_cond_remove(c
)
153 /* Remove condition from list of valid, initialized conditions */
155 if ((*c
)->mc_prev
== NULL
)
156 vc_front
= (*c
)->mc_next
;
158 (*c
)->mc_prev
->mc_next
= (*c
)->mc_next
;
160 if ((*c
)->mc_next
== NULL
)
161 vc_rear
= (*c
)->mc_prev
;
163 (*c
)->mc_next
->mc_prev
= (*c
)->mc_prev
;
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. */
180 else if (!mthread_cond_valid(cond
))
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
);
199 /*===========================================================================*
200 * mthread_cond_valid *
201 *===========================================================================*/
202 #ifdef MTHREAD_STRICT
203 static int mthread_cond_valid(c
)
206 /* Check to see if cond is on the list of valid conditions */
207 struct __mthread_cond
*loopitem
;
211 while (loopitem
!= NULL
) {
215 loopitem
= loopitem
->mc_next
;
222 /*===========================================================================*
223 * mthread_cond_verify *
224 *===========================================================================*/
226 int mthread_cond_verify(void)
228 /* Return true in case no condition variables are in use. */
230 return(vc_front
== NULL
);
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 */
244 struct __mthread_cond
*c
;
245 struct __mthread_mutex
*m
;
247 if (cond
== NULL
|| mutex
== NULL
)
250 c
= (struct __mthread_cond
*) *cond
;
251 m
= (struct __mthread_mutex
*) *mutex
;
253 if (!mthread_cond_valid(cond
) || !mthread_mutex_valid(mutex
))
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 */
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)
273 /* pthread compatibility layer. */
274 __weak_alias(pthread_cond_init
, mthread_cond_init
)