]> git.saurik.com Git - apple/libc.git/blame - pthreads/pthread_cond.c
Libc-498.1.5.tar.gz
[apple/libc.git] / pthreads / pthread_cond.c
CommitLineData
9385eb3d 1/*
b5d655f7 2 * Copyright (c) 2000-2003, 2007, 2008 Apple Inc. All rights reserved.
9385eb3d
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
9385eb3d
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
e9ce8d39
A
23/*
24 * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
25 * All Rights Reserved
26 *
27 * Permission to use, copy, modify, and distribute this software and
28 * its documentation for any purpose and without fee is hereby granted,
29 * provided that the above copyright notice appears in all copies and
30 * that both the copyright notice and this permission notice appear in
31 * supporting documentation.
32 *
33 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
34 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35 * FOR A PARTICULAR PURPOSE.
36 *
37 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
39 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
40 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
41 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
42 */
43/*
44 * MkLinux
45 */
46
47/*
48 * POSIX Pthread Library
49 */
50
51#include "pthread_internals.h"
52#include <sys/time.h> /* For struct timespec and getclock(). */
53#include <stdio.h>
224c7076 54
b5d655f7 55#ifdef PLOCKSTAT
224c7076 56#include "plockstat.h"
b5d655f7
A
57#else /* !PLOCKSTAT */
58#define PLOCKSTAT_MUTEX_RELEASE(x, y)
59#endif /* PLOCKSTAT */
60
9385eb3d 61extern void _pthread_mutex_remove(pthread_mutex_t *, pthread_t);
3d9156a7
A
62extern int __unix_conforming;
63
64#ifndef BUILDING_VARIANT /* [ */
9385eb3d
A
65
66/*
e9ce8d39
A
67 * Destroy a condition variable.
68 */
69int
70pthread_cond_destroy(pthread_cond_t *cond)
71{
9385eb3d
A
72 int ret;
73 int sig = cond->sig;
74
75 /* to provide backwards compat for apps using united condtn vars */
224c7076 76 if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init) && (sig != _PTHREAD_KERN_COND_SIG))
9385eb3d
A
77 return(EINVAL);
78
79 LOCK(cond->lock);
e9ce8d39
A
80 if (cond->sig == _PTHREAD_COND_SIG)
81 {
9385eb3d 82 if (cond->busy == (pthread_mutex_t *)NULL)
e9ce8d39
A
83 {
84 cond->sig = _PTHREAD_NO_SIG;
224c7076 85 ret = 0;
9385eb3d
A
86 } else
87 ret = EBUSY;
224c7076
A
88 } else if (cond->sig == _PTHREAD_KERN_COND_SIG) {
89 int condid = cond->_pthread_cond_kernid;
90 UNLOCK(cond->lock);
91 if (__pthread_cond_destroy(condid) == -1)
92 return(errno);
93 cond->sig = _PTHREAD_NO_SIG;
94 return(0);
e9ce8d39 95 } else
9385eb3d
A
96 ret = EINVAL; /* Not an initialized condition variable structure */
97 UNLOCK(cond->lock);
98 return (ret);
e9ce8d39
A
99}
100
e9ce8d39
A
101
102/*
103 * Signal a condition variable, waking up all threads waiting for it.
104 */
105int
106pthread_cond_broadcast(pthread_cond_t *cond)
107{
9385eb3d
A
108 kern_return_t kern_res;
109 semaphore_t sem;
110 int sig = cond->sig;
111
112 /* to provide backwards compat for apps using united condtn vars */
224c7076 113 if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init) && (sig != _PTHREAD_KERN_COND_SIG))
9385eb3d
A
114 return(EINVAL);
115
116 LOCK(cond->lock);
117 if (cond->sig != _PTHREAD_COND_SIG)
118 {
119 int res;
120
121 if (cond->sig == _PTHREAD_COND_SIG_init)
122 {
224c7076
A
123 _pthread_cond_init(cond, NULL, 0);
124 res = 0;
125 } else if (cond->sig == _PTHREAD_KERN_COND_SIG) {
126 int condid = cond->_pthread_cond_kernid;
127 UNLOCK(cond->lock);
128 if (__pthread_cond_broadcast(condid) == -1)
129 return(errno);
130 return(0);
9385eb3d
A
131 } else
132 res = EINVAL; /* Not a condition variable */
133 UNLOCK(cond->lock);
134 return (res);
135 }
136 else if ((sem = cond->sem) == SEMAPHORE_NULL)
137 {
138 /* Avoid kernel call since there are no waiters... */
139 UNLOCK(cond->lock);
224c7076 140 return (0);
9385eb3d
A
141 }
142 cond->sigspending++;
143 UNLOCK(cond->lock);
144
145 PTHREAD_MACH_CALL(semaphore_signal_all(sem), kern_res);
146
147 LOCK(cond->lock);
148 cond->sigspending--;
149 if (cond->waiters == 0 && cond->sigspending == 0)
150 {
151 cond->sem = SEMAPHORE_NULL;
152 restore_sem_to_pool(sem);
153 }
154 UNLOCK(cond->lock);
155 if (kern_res != KERN_SUCCESS)
156 return (EINVAL);
224c7076 157 return (0);
e9ce8d39
A
158}
159
160/*
161 * Signal a condition variable, waking a specified thread.
162 */
163int
164pthread_cond_signal_thread_np(pthread_cond_t *cond, pthread_t thread)
165{
9385eb3d
A
166 kern_return_t kern_res;
167 semaphore_t sem;
168 int sig = cond->sig;
169
170 /* to provide backwards compat for apps using united condtn vars */
9385eb3d 171
224c7076
A
172 if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init) && (sig != _PTHREAD_KERN_COND_SIG))
173 return(EINVAL);
9385eb3d
A
174 LOCK(cond->lock);
175 if (cond->sig != _PTHREAD_COND_SIG)
176 {
177 int ret;
178
179 if (cond->sig == _PTHREAD_COND_SIG_init)
180 {
224c7076
A
181 _pthread_cond_init(cond, NULL, 0);
182 ret = 0;
183 } else if (cond->sig == _PTHREAD_KERN_COND_SIG) {
184 int condid = cond->_pthread_cond_kernid;
185 UNLOCK(cond->lock);
186 if (__pthread_cond_signal(condid) == -1)
187 return(errno);
188 return(0);
189 } else
9385eb3d
A
190 ret = EINVAL; /* Not a condition variable */
191 UNLOCK(cond->lock);
192 return (ret);
193 }
194 else if ((sem = cond->sem) == SEMAPHORE_NULL)
195 {
196 /* Avoid kernel call since there are not enough waiters... */
197 UNLOCK(cond->lock);
224c7076 198 return (0);
e9ce8d39 199 }
9385eb3d
A
200 cond->sigspending++;
201 UNLOCK(cond->lock);
202
203 if (thread == (pthread_t)NULL)
204 {
205 kern_res = semaphore_signal_thread(sem, THREAD_NULL);
206 if (kern_res == KERN_NOT_WAITING)
207 kern_res = KERN_SUCCESS;
208 }
209 else if (thread->sig == _PTHREAD_SIG)
210 {
211 PTHREAD_MACH_CALL(semaphore_signal_thread(
212 sem, pthread_mach_thread_np(thread)), kern_res);
213 }
214 else
215 kern_res = KERN_FAILURE;
216
217 LOCK(cond->lock);
218 cond->sigspending--;
219 if (cond->waiters == 0 && cond->sigspending == 0)
220 {
221 cond->sem = SEMAPHORE_NULL;
222 restore_sem_to_pool(sem);
223 }
224 UNLOCK(cond->lock);
225 if (kern_res != KERN_SUCCESS)
226 return (EINVAL);
224c7076 227 return (0);
e9ce8d39
A
228}
229
230/*
231 * Signal a condition variable, waking only one thread.
232 */
233int
234pthread_cond_signal(pthread_cond_t *cond)
235{
9385eb3d 236 return pthread_cond_signal_thread_np(cond, NULL);
e9ce8d39
A
237}
238
239/*
240 * Manage a list of condition variables associated with a mutex
241 */
242
243static void
244_pthread_cond_add(pthread_cond_t *cond, pthread_mutex_t *mutex)
245{
246 pthread_cond_t *c;
247 LOCK(mutex->lock);
248 if ((c = mutex->busy) != (pthread_cond_t *)NULL)
249 {
250 c->prev = cond;
251 }
252 cond->next = c;
253 cond->prev = (pthread_cond_t *)NULL;
254 mutex->busy = cond;
255 UNLOCK(mutex->lock);
9385eb3d 256 if (cond->sem == SEMAPHORE_NULL)
e9ce8d39 257 cond->sem = new_sem_from_pool();
e9ce8d39
A
258}
259
260static void
261_pthread_cond_remove(pthread_cond_t *cond, pthread_mutex_t *mutex)
262{
263 pthread_cond_t *n, *p;
9385eb3d 264
e9ce8d39
A
265 LOCK(mutex->lock);
266 if ((n = cond->next) != (pthread_cond_t *)NULL)
267 {
268 n->prev = cond->prev;
269 }
270 if ((p = cond->prev) != (pthread_cond_t *)NULL)
271 {
272 p->next = cond->next;
9385eb3d
A
273 }
274 else
e9ce8d39
A
275 { /* This is the first in the list */
276 mutex->busy = n;
277 }
278 UNLOCK(mutex->lock);
9385eb3d
A
279 if (cond->sigspending == 0)
280 {
281 restore_sem_to_pool(cond->sem);
282 cond->sem = SEMAPHORE_NULL;
e9ce8d39
A
283 }
284}
285
3d9156a7
A
286static void cond_cleanup(void *arg)
287{
288 pthread_cond_t *cond = (pthread_cond_t *)arg;
289 pthread_mutex_t *mutex;
224c7076
A
290// 4597450: begin
291 pthread_t thread = pthread_self();
292 int thcanceled = 0;
293
294 LOCK(thread->lock);
295 thcanceled = (thread->detached & _PTHREAD_WASCANCEL);
296 UNLOCK(thread->lock);
297
298 if (thcanceled == 0)
299 return;
300
301// 4597450: end
3d9156a7
A
302 LOCK(cond->lock);
303 mutex = cond->busy;
304 cond->waiters--;
305 if (cond->waiters == 0) {
306 _pthread_cond_remove(cond, mutex);
307 cond->busy = (pthread_mutex_t *)NULL;
308 }
309 UNLOCK(cond->lock);
224c7076 310
3d9156a7
A
311 /*
312 ** Can't do anything if this fails -- we're on the way out
313 */
314 (void)pthread_mutex_lock(mutex);
315}
316
e9ce8d39
A
317/*
318 * Suspend waiting for a condition variable.
319 * Note: we have to keep a list of condition variables which are using
320 * this same mutex variable so we can detect invalid 'destroy' sequences.
224c7076
A
321 * If isconforming < 0, we skip the _pthread_testcancel(), but keep the
322 * remaining conforming behavior..
e9ce8d39 323 */
3d9156a7 324__private_extern__ int
e9ce8d39
A
325_pthread_cond_wait(pthread_cond_t *cond,
326 pthread_mutex_t *mutex,
327 const struct timespec *abstime,
3d9156a7
A
328 int isRelative,
329 int isconforming)
e9ce8d39 330{
224c7076 331 int res, saved_error;
9385eb3d 332 kern_return_t kern_res;
3d9156a7 333 int wait_res;
9385eb3d
A
334 pthread_mutex_t *busy;
335 mach_timespec_t then;
3d9156a7 336 struct timespec cthen = {0,0};
9385eb3d 337 int sig = cond->sig;
224c7076
A
338 int msig = mutex->sig;
339extern void _pthread_testcancel(pthread_t thread, int isconforming);
9385eb3d
A
340
341 /* to provide backwards compat for apps using united condtn vars */
224c7076 342 if((sig != _PTHREAD_COND_SIG) && (sig != _PTHREAD_COND_SIG_init) && (sig != _PTHREAD_KERN_COND_SIG))
9385eb3d 343 return(EINVAL);
224c7076
A
344
345 if (isconforming) {
346 if((msig != _PTHREAD_MUTEX_SIG) && (msig != _PTHREAD_MUTEX_SIG_init) && (msig != _PTHREAD_KERN_MUTEX_SIG))
347 return(EINVAL);
348 if (isconforming > 0)
349 _pthread_testcancel(pthread_self(), 1);
350 }
9385eb3d
A
351 LOCK(cond->lock);
352 if (cond->sig != _PTHREAD_COND_SIG)
353 {
354 if (cond->sig != _PTHREAD_COND_SIG_init)
355 {
224c7076
A
356 if ((cond->sig == _PTHREAD_KERN_COND_SIG) && (mutex->sig == _PTHREAD_KERN_MUTEX_SIG)) {
357 int condid = cond->_pthread_cond_kernid;
358 int mutexid = mutex->_pthread_mutex_kernid;
359 UNLOCK(cond->lock);
360
361 if (abstime) {
362 struct timespec now;
363 struct timeval tv;
364 gettimeofday(&tv, NULL);
365 TIMEVAL_TO_TIMESPEC(&tv, &now);
366
367 /* Compute relative time to sleep */
368 then.tv_nsec = abstime->tv_nsec - now.tv_nsec;
369 then.tv_sec = abstime->tv_sec - now.tv_sec;
370 if (then.tv_nsec < 0)
371 {
372 then.tv_nsec += NSEC_PER_SEC;
373 then.tv_sec--;
374 }
375 if (((int)then.tv_sec < 0) ||
376 ((then.tv_sec == 0) && (then.tv_nsec == 0)))
377 {
378 UNLOCK(cond->lock);
379 return ETIMEDOUT;
380 }
381 if ((res = pthread_mutex_unlock(mutex)) != 0)
382 return (res);
383
384 if ((__pthread_cond_timedwait(condid, mutexid, &then)) == -1)
385 saved_error = errno;
386 else
387 saved_error = 0;
388 } else {
389 if ((res = pthread_mutex_unlock(mutex)) != 0)
390 return (res);
391 if(( __pthread_cond_wait(condid, mutexid)) == -1)
392 saved_error = errno;
393 else
394 saved_error = 0;
395 }
396 if ((res = pthread_mutex_lock(mutex)) != 0)
397 return (res);
398 return(saved_error);
399 } else {
400 UNLOCK(cond->lock);
401 return (EINVAL); /* Not a condition variable */
402 }
9385eb3d 403 }
224c7076 404 _pthread_cond_init(cond, NULL, 0);
9385eb3d
A
405 }
406
3d9156a7
A
407 if (abstime) {
408 if (!isconforming)
9385eb3d 409 {
3d9156a7
A
410 if (isRelative == 0) {
411 struct timespec now;
412 struct timeval tv;
413 gettimeofday(&tv, NULL);
414 TIMEVAL_TO_TIMESPEC(&tv, &now);
415
416 /* Compute relative time to sleep */
417 then.tv_nsec = abstime->tv_nsec - now.tv_nsec;
418 then.tv_sec = abstime->tv_sec - now.tv_sec;
419 if (then.tv_nsec < 0)
420 {
421 then.tv_nsec += NSEC_PER_SEC;
422 then.tv_sec--;
423 }
424 if (((int)then.tv_sec < 0) ||
425 ((then.tv_sec == 0) && (then.tv_nsec == 0)))
426 {
427 UNLOCK(cond->lock);
428 return ETIMEDOUT;
429 }
430 } else {
431 then.tv_sec = abstime->tv_sec;
432 then.tv_nsec = abstime->tv_nsec;
9385eb3d 433 }
3d9156a7 434 if (then.tv_nsec >= NSEC_PER_SEC) {
9385eb3d 435 UNLOCK(cond->lock);
3d9156a7 436 return EINVAL;
9385eb3d 437 }
3d9156a7 438 } else {
224c7076
A
439 if (isRelative == 0) {
440 /* preflight the checks for failures */
441 struct timespec now;
442 struct timeval tv;
443 gettimeofday(&tv, NULL);
444 TIMEVAL_TO_TIMESPEC(&tv, &now);
445
446 /* Compute relative time to sleep */
447 then.tv_nsec = abstime->tv_nsec - now.tv_nsec;
448 then.tv_sec = abstime->tv_sec - now.tv_sec;
449 if (then.tv_nsec < 0)
450 {
451 then.tv_nsec += NSEC_PER_SEC;
452 then.tv_sec--;
453 }
454 if (((int)then.tv_sec < 0) ||
455 ((then.tv_sec == 0) && (then.tv_nsec == 0)))
456 {
457 UNLOCK(cond->lock);
458 return ETIMEDOUT;
459 }
460 if (then.tv_nsec >= NSEC_PER_SEC) {
461 UNLOCK(cond->lock);
462 return EINVAL;
463 }
464 }
465 /* we can cleanup this code and pass the calculated time
466 * to the kernel. But kernel is going to do the same. TILL
467 * we change the kernel do this anyway
468 */
3d9156a7
A
469 cthen.tv_sec = abstime->tv_sec;
470 cthen.tv_nsec = abstime->tv_nsec;
471 if ((cthen.tv_sec < 0) || (cthen.tv_nsec < 0)) {
472 UNLOCK(cond->lock);
473 return EINVAL;
474 }
475 if (cthen.tv_nsec >= NSEC_PER_SEC) {
476 UNLOCK(cond->lock);
477 return EINVAL;
478 }
479 }
9385eb3d
A
480 }
481
482 if (++cond->waiters == 1)
483 {
484 _pthread_cond_add(cond, mutex);
485 cond->busy = mutex;
486 }
487 else if ((busy = cond->busy) != mutex)
488 {
489 /* Must always specify the same mutex! */
490 cond->waiters--;
491 UNLOCK(cond->lock);
492 return (EINVAL);
493 }
494 UNLOCK(cond->lock);
495
496#if defined(DEBUG)
497 _pthread_mutex_remove(mutex, pthread_self());
498#endif
499 LOCK(mutex->lock);
500 if (--mutex->lock_count == 0)
501 {
224c7076
A
502 PLOCKSTAT_MUTEX_RELEASE(mutex, (mutex->type == PTHREAD_MUTEX_RECURSIVE)? 1:0);
503
9385eb3d
A
504 if (mutex->sem == SEMAPHORE_NULL)
505 mutex->sem = new_sem_from_pool();
506 mutex->owner = _PTHREAD_MUTEX_OWNER_SWITCHING;
507 UNLOCK(mutex->lock);
508
3d9156a7
A
509 if (!isconforming) {
510 if (abstime) {
511 kern_res = semaphore_timedwait_signal(cond->sem, mutex->sem, then);
512 } else {
513 PTHREAD_MACH_CALL(semaphore_wait_signal(cond->sem, mutex->sem), kern_res);
514 }
9385eb3d 515 } else {
3d9156a7
A
516 pthread_cleanup_push(cond_cleanup, (void *)cond);
517 wait_res = __semwait_signal(cond->sem, mutex->sem, abstime != NULL, isRelative,
518 cthen.tv_sec, cthen.tv_nsec);
519 pthread_cleanup_pop(0);
9385eb3d 520 }
3d9156a7 521 } else {
224c7076 522 PLOCKSTAT_MUTEX_RELEASE(mutex, (mutex->type == PTHREAD_MUTEX_RECURSIVE)? 1:0);
9385eb3d 523 UNLOCK(mutex->lock);
3d9156a7
A
524 if (!isconforming) {
525 if (abstime) {
526 kern_res = semaphore_timedwait(cond->sem, then);
527 } else {
528 PTHREAD_MACH_CALL(semaphore_wait(cond->sem), kern_res);
529 }
530 } else {
531 pthread_cleanup_push(cond_cleanup, (void *)cond);
532 wait_res = __semwait_signal(cond->sem, NULL, abstime != NULL, isRelative,
533 cthen.tv_sec, cthen.tv_nsec);
534 pthread_cleanup_pop(0);
9385eb3d 535 }
3d9156a7 536
9385eb3d
A
537 }
538
539 LOCK(cond->lock);
540 cond->waiters--;
541 if (cond->waiters == 0)
542 {
543 _pthread_cond_remove(cond, mutex);
544 cond->busy = (pthread_mutex_t *)NULL;
545 }
546 UNLOCK(cond->lock);
224c7076 547 if ((res = pthread_mutex_lock(mutex)) != 0)
9385eb3d
A
548 return (res);
549
3d9156a7
A
550 if (!isconforming) {
551 /* KERN_ABORTED can be treated as a spurious wakeup */
552 if ((kern_res == KERN_SUCCESS) || (kern_res == KERN_ABORTED))
224c7076 553 return (0);
3d9156a7
A
554 else if (kern_res == KERN_OPERATION_TIMED_OUT)
555 return (ETIMEDOUT);
556 return (EINVAL);
557 } else {
558 if (wait_res < 0) {
559 if (errno == ETIMEDOUT) {
560 return ETIMEDOUT;
561 } else if (errno == EINTR) {
562 /*
563 ** EINTR can be treated as a spurious wakeup unless we were canceled.
564 */
565 return 0;
566 }
567 return EINVAL;
568 }
569 return 0;
570 }
e9ce8d39
A
571}
572
e9ce8d39
A
573
574int
575pthread_cond_timedwait_relative_np(pthread_cond_t *cond,
576 pthread_mutex_t *mutex,
577 const struct timespec *abstime)
578{
3d9156a7 579 return (_pthread_cond_wait(cond, mutex, abstime, 1, 0));
e9ce8d39
A
580}
581
5b2abdfb
A
582int
583pthread_condattr_init(pthread_condattr_t *attr)
584{
585 attr->sig = _PTHREAD_COND_ATTR_SIG;
224c7076
A
586 attr->pshared = _PTHREAD_DEFAULT_PSHARED;
587 return (0);
5b2abdfb
A
588}
589
590int
591pthread_condattr_destroy(pthread_condattr_t *attr)
592{
593 attr->sig = _PTHREAD_NO_SIG; /* Uninitialized */
224c7076 594 return (0);
5b2abdfb
A
595}
596
597int
598pthread_condattr_getpshared(const pthread_condattr_t *attr,
599 int *pshared)
600{
601 if (attr->sig == _PTHREAD_COND_ATTR_SIG)
602 {
224c7076
A
603 *pshared = (int)attr->pshared;
604 return (0);
5b2abdfb
A
605 } else
606 {
607 return (EINVAL); /* Not an initialized 'attribute' structure */
608 }
609}
610
224c7076
A
611#ifdef PR_5243343
612/* 5243343 - temporary hack to detect if we are running the conformance test */
613extern int PR_5243343_flag;
614#endif /* PR_5243343 */
5b2abdfb 615
224c7076
A
616__private_extern__ int
617_pthread_cond_init(pthread_cond_t *cond,
618 const pthread_condattr_t *attr,
619 int conforming)
620{
621 cond->next = (pthread_cond_t *)NULL;
622 cond->prev = (pthread_cond_t *)NULL;
623 cond->busy = (pthread_mutex_t *)NULL;
624 cond->waiters = 0;
625 cond->sigspending = 0;
626 if (conforming) {
627 if (attr) {
628 cond->pshared = attr->pshared;
629 if (cond->pshared == PTHREAD_PROCESS_SHARED) {
630 cond->sem = SEMAPHORE_NULL;
631 cond->sig = 0;
632 if( __pthread_cond_init(cond, attr) == -1)
633 return(errno);
634 cond->sig = _PTHREAD_KERN_COND_SIG;
635 return(0);
636 }
637 }
638 else
639 cond->pshared = _PTHREAD_DEFAULT_PSHARED;
640 } else
641 cond->pshared = _PTHREAD_DEFAULT_PSHARED;
642 cond->sem = SEMAPHORE_NULL;
643 cond->sig = _PTHREAD_COND_SIG;
644 return (0);
645}
646
647
648/* temp home till pshared is fixed correctly */
5b2abdfb
A
649int
650pthread_condattr_setpshared(pthread_condattr_t * attr, int pshared)
651{
224c7076 652
5b2abdfb
A
653 if (attr->sig == _PTHREAD_COND_ATTR_SIG)
654 {
224c7076
A
655#if __DARWIN_UNIX03
656#ifdef PR_5243343
657 if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED && PR_5243343_flag))
658#else /* !PR_5243343 */
659 if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED))
660#endif /* PR_5243343 */
661#else /* __DARWIN_UNIX03 */
5b2abdfb 662 if ( pshared == PTHREAD_PROCESS_PRIVATE)
224c7076 663#endif /* __DARWIN_UNIX03 */
5b2abdfb 664 {
224c7076
A
665 attr->pshared = pshared;
666 return (0);
5b2abdfb
A
667 } else
668 {
669 return (EINVAL); /* Invalid parameter */
670 }
671 } else
672 {
673 return (EINVAL); /* Not an initialized 'attribute' structure */
674 }
675
676}
677
224c7076 678
3d9156a7
A
679#else /* !BUILDING_VARIANT */
680extern int _pthread_cond_wait(pthread_cond_t *cond,
681 pthread_mutex_t *mutex,
682 const struct timespec *abstime,
683 int isRelative,
684 int isconforming);
685
224c7076
A
686extern int
687_pthread_cond_init(pthread_cond_t *cond,
688 const pthread_condattr_t *attr,
689 int conforming);
690
3d9156a7 691#endif /* !BUILDING_VARIANT ] */
224c7076
A
692/*
693 * Initialize a condition variable. Note: 'attr' is ignored.
694 */
3d9156a7 695
224c7076
A
696/*
697 * Initialize a condition variable. This is the public interface.
698 * We can't trust the lock, so initialize it first before taking
699 * it.
700 */
3d9156a7 701int
224c7076
A
702pthread_cond_init(pthread_cond_t *cond,
703 const pthread_condattr_t *attr)
3d9156a7
A
704{
705 int conforming;
3d9156a7 706
224c7076
A
707#if __DARWIN_UNIX03
708 conforming = 1;
3d9156a7 709#else /* __DARWIN_UNIX03 */
224c7076 710 conforming = 0;
3d9156a7 711#endif /* __DARWIN_UNIX03 */
224c7076
A
712
713
714 LOCK_INIT(cond->lock);
715 return (_pthread_cond_init(cond, attr, conforming));
3d9156a7
A
716}
717
224c7076
A
718/*
719int
720pthread_cond_wait(pthread_cond_t *cond,
721 pthread_mutex_t *mutex)
722
3d9156a7
A
723int
724pthread_cond_timedwait(pthread_cond_t *cond,
725 pthread_mutex_t *mutex,
726 const struct timespec *abstime)
3d9156a7 727
224c7076 728moved to pthread_cancelable.c */