]>
git.saurik.com Git - apple/libc.git/blob - pthreads.subproj/pthread_cond.c
2 * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
5 * Permission to use, copy, modify, and distribute this software and
6 * its documentation for any purpose and without fee is hereby granted,
7 * provided that the above copyright notice appears in all copies and
8 * that both the copyright notice and this permission notice appear in
9 * supporting documentation.
11 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
12 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE.
15 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
16 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
18 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
19 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 * POSIX Pthread Library
29 #include "pthread_internals.h"
30 #include <sys/time.h> /* For struct timespec and getclock(). */
34 * Destroy a condition variable.
37 pthread_cond_destroy(pthread_cond_t
*cond
)
39 if (cond
->sig
== _PTHREAD_COND_SIG
)
42 if (cond
->busy
!= (pthread_mutex_t
*)NULL
)
48 cond
->sig
= _PTHREAD_NO_SIG
;
53 return (EINVAL
); /* Not an initialized condition variable structure */
57 * Initialize a condition variable. Note: 'attr' is ignored.
60 pthread_cond_init(pthread_cond_t
*cond
,
61 const pthread_condattr_t
*attr
)
63 LOCK_INIT(cond
->lock
);
64 cond
->sig
= _PTHREAD_COND_SIG
;
65 cond
->next
= (pthread_cond_t
*)NULL
;
66 cond
->prev
= (pthread_cond_t
*)NULL
;
67 cond
->busy
= (pthread_mutex_t
*)NULL
;
69 cond
->sigspending
= 0;
70 cond
->sem
= MACH_PORT_NULL
;
75 * Signal a condition variable, waking up all threads waiting for it.
78 pthread_cond_broadcast(pthread_cond_t
*cond
)
80 kern_return_t kern_res
;
82 if (cond
->sig
== _PTHREAD_COND_SIG_init
) {
83 if ((res
= pthread_cond_init(cond
, NULL
)) != 0) {
87 if (cond
->sig
!= _PTHREAD_COND_SIG
) {
88 /* Not a condition variable */
92 if (cond
->sem
== MACH_PORT_NULL
) {
93 /* Avoid kernel call since there are no waiters... */
99 PTHREAD_MACH_CALL(semaphore_signal_all(cond
->sem
), kern_res
);
102 if (cond
->waiters
== 0 && cond
->sigspending
== 0) {
103 restore_sem_to_pool(cond
->sem
);
104 cond
->sem
= MACH_PORT_NULL
;
107 if (kern_res
!= KERN_SUCCESS
) {
114 * Signal a condition variable, waking a specified thread.
117 pthread_cond_signal_thread_np(pthread_cond_t
*cond
, pthread_t thread
)
119 kern_return_t kern_res
;
120 if (cond
->sig
== _PTHREAD_COND_SIG_init
) {
122 if ((res
= pthread_cond_init(cond
, NULL
)) != 0) {
126 if (cond
->sig
!= _PTHREAD_COND_SIG
) {
127 return (EINVAL
); /* Not a condition variable */
130 if (cond
->sem
== MACH_PORT_NULL
) {
131 /* Avoid kernel call since there are not enough waiters... */
137 if (thread
== (pthread_t
)NULL
) {
138 kern_res
= semaphore_signal_thread(cond
->sem
, MACH_PORT_NULL
);
139 if (kern_res
== KERN_INVALID_ARGUMENT
) {
140 PTHREAD_MACH_CALL(semaphore_signal(cond
->sem
), kern_res
);
141 } else if (kern_res
== KERN_NOT_WAITING
) {
142 kern_res
= KERN_SUCCESS
;
144 } else if (thread
->sig
== _PTHREAD_SIG
) {
145 PTHREAD_MACH_CALL(semaphore_signal_thread(cond
->sem
, thread
->kernel_thread
), kern_res
);
147 kern_res
= KERN_FAILURE
;
151 if (cond
->waiters
== 0 && cond
->sigspending
== 0) {
152 restore_sem_to_pool(cond
->sem
);
153 cond
->sem
= MACH_PORT_NULL
;
156 if (kern_res
!= KERN_SUCCESS
) {
163 * Signal a condition variable, waking only one thread.
166 pthread_cond_signal(pthread_cond_t
*cond
)
168 return pthread_cond_signal_thread_np(cond
, NULL
);
172 * Manage a list of condition variables associated with a mutex
176 _pthread_cond_add(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
180 if ((c
= mutex
->busy
) != (pthread_cond_t
*)NULL
)
185 cond
->prev
= (pthread_cond_t
*)NULL
;
188 if (cond
->sem
== MACH_PORT_NULL
) {
189 cond
->sem
= new_sem_from_pool();
194 _pthread_cond_remove(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
196 pthread_cond_t
*n
, *p
;
198 if ((n
= cond
->next
) != (pthread_cond_t
*)NULL
)
200 n
->prev
= cond
->prev
;
202 if ((p
= cond
->prev
) != (pthread_cond_t
*)NULL
)
204 p
->next
= cond
->next
;
206 { /* This is the first in the list */
210 if (cond
->sigspending
== 0) {
211 restore_sem_to_pool(cond
->sem
);
212 cond
->sem
= MACH_PORT_NULL
;
217 * Suspend waiting for a condition variable.
218 * Note: we have to keep a list of condition variables which are using
219 * this same mutex variable so we can detect invalid 'destroy' sequences.
222 _pthread_cond_wait(pthread_cond_t
*cond
,
223 pthread_mutex_t
*mutex
,
224 const struct timespec
*abstime
,
228 kern_return_t kern_res
;
229 pthread_mutex_t
*busy
;
230 mach_timespec_t then
;
231 if (cond
->sig
== _PTHREAD_COND_SIG_init
) {
232 if ((res
= pthread_cond_init(cond
, NULL
)) != 0) {
236 if (cond
->sig
!= _PTHREAD_COND_SIG
) {
237 /* Not a condition variable */
242 if (isRelative
== 0) {
245 gettimeofday(&tv
, NULL
);
246 TIMEVAL_TO_TIMESPEC(&tv
, &now
);
248 /* Compute relative time to sleep */
249 then
.tv_nsec
= abstime
->tv_nsec
- now
.tv_nsec
;
250 then
.tv_sec
= abstime
->tv_sec
- now
.tv_sec
;
251 if (then
.tv_nsec
< 0) {
252 then
.tv_nsec
+= 1000000000; /* nsec/sec */
255 if (((int)then
.tv_sec
< 0) ||
256 ((then
.tv_sec
== 0) && (then
.tv_nsec
== 0))) {
260 then
.tv_sec
= abstime
->tv_sec
;
261 then
.tv_nsec
= abstime
->tv_nsec
;
266 if ((busy
!= (pthread_mutex_t
*)NULL
) && (busy
!= mutex
)) {
267 /* Must always specify the same mutex! */
272 if (cond
->waiters
== 1) {
273 _pthread_cond_add(cond
, mutex
);
278 if (mutex
->sem
== MACH_PORT_NULL
) {
279 mutex
->sem
= new_sem_from_pool();
281 mutex
->cond_lock
= 1;
284 kern_res
= semaphore_timedwait_signal(cond
->sem
, mutex
->sem
, then
);
286 PTHREAD_MACH_CALL(semaphore_wait_signal(cond
->sem
, mutex
->sem
), kern_res
);
290 if (cond
->waiters
== 0) {
291 _pthread_cond_remove(cond
, mutex
);
292 cond
->busy
= (pthread_mutex_t
*)NULL
;
295 if ((res
= pthread_mutex_lock(mutex
)) != ESUCCESS
) {
298 if (kern_res
== KERN_SUCCESS
) {
300 } else if (kern_res
== KERN_OPERATION_TIMED_OUT
) {
308 pthread_cond_wait(pthread_cond_t
*cond
,
309 pthread_mutex_t
*mutex
)
311 return (_pthread_cond_wait(cond
, mutex
, (struct timespec
*)NULL
, 0));
315 pthread_cond_timedwait(pthread_cond_t
*cond
,
316 pthread_mutex_t
*mutex
,
317 const struct timespec
*abstime
)
319 return (_pthread_cond_wait(cond
, mutex
, abstime
, 0));
323 pthread_cond_timedwait_relative_np(pthread_cond_t
*cond
,
324 pthread_mutex_t
*mutex
,
325 const struct timespec
*abstime
)
327 return (_pthread_cond_wait(cond
, mutex
, abstime
, 1));