Home | History | Annotate | Line # | Download | only in libpthread
pthread_cond.c revision 1.1.2.2
      1 /*	$NetBSD: pthread_cond.c,v 1.1.2.2 2001/07/25 23:53:01 nathanw Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Nathan J. Williams.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include <assert.h>
     40 #include <errno.h>
     41 
     42 #include "pthread.h"
     43 #include "pthread_int.h"
     44 
     45 
     46 int
     47 pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
     48 {
     49 
     50 #ifdef ERRORCHECK
     51 	if ((cond == NULL) ||
     52 	    (attr && (attr->ptca_magic != _PT_CONDATTR_MAGIC)))
     53 		return EINVAL;
     54 #endif
     55 
     56 	cond->ptc_magic = _PT_COND_MAGIC;
     57 	pthread_lockinit(&cond->ptc_lock);
     58 	PTQ_INIT(&cond->ptc_waiters);
     59 
     60 	return 0;
     61 }
     62 
     63 
     64 int
     65 pthread_cond_destroy(pthread_cond_t *cond)
     66 {
     67 
     68 #ifdef ERRORCHECK
     69 	if ((cond == NULL) || (cond->ptc_magic != _PT_COND_MAGIC) ||
     70 	    (cond->ptc_mutex != NULL) ||
     71 	    (cond->ptc_lock != __SIMPLELOCK_UNLOCKED))
     72 		return EINVAL;
     73 #endif
     74 
     75 	cond->ptc_magic = _PT_COND_DEAD;
     76 
     77 	return 0;
     78 }
     79 
     80 
     81 int
     82 pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
     83 {
     84 	pthread_t self;
     85 #ifdef ERRORCHECK
     86 	if ((cond == NULL) || (cond->ptc_magic != _PT_COND_MAGIC) ||
     87 	    (mutex == NULL) || (mutex->ptm_magic != _PT_MUTEX_MAGIC))
     88 		return EINVAL;
     89 #endif
     90 
     91 	self = pthread__self();
     92 	pthread_spinlock(self, &cond->ptc_lock);
     93 	if (cond->ptc_mutex == NULL)
     94 		cond->ptc_mutex = mutex;
     95 	else
     96 		if (cond->ptc_mutex != mutex) {
     97 			pthread_spinunlock(self, &cond->ptc_lock);
     98 			return EINVAL;
     99 		}
    100 
    101 	PTQ_INSERT_TAIL(&cond->ptc_waiters, self, pt_sleep);
    102 	pthread_mutex_unlock(mutex);
    103 	pthread__block(self, &cond->ptc_lock);
    104 	/* Spinlock is unlocked on return */
    105 	pthread_mutex_lock(mutex);
    106 
    107 	return 0;
    108 }
    109 
    110 
    111 int
    112 pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
    113     const struct timespec *abstime)
    114 {
    115 
    116 	return EINVAL;
    117 }
    118 
    119 
    120 int
    121 pthread_cond_signal(pthread_cond_t *cond)
    122 {
    123 	pthread_t self, signaled;
    124 #ifdef ERRORCHECK
    125 	if ((cond == NULL) || (cond->ptc_magic != _PT_COND_MAGIC))
    126 		return EINVAL;
    127 #endif
    128 
    129 	self = pthread__self();
    130 
    131 	pthread_spinlock(self, &cond->ptc_lock);
    132 	signaled = PTQ_FIRST(&cond->ptc_waiters);
    133 	if (signaled != NULL)
    134 		PTQ_REMOVE(&cond->ptc_waiters, signaled, pt_sleep);
    135 	if (PTQ_EMPTY(&cond->ptc_waiters))
    136 		cond->ptc_mutex = NULL;
    137 	pthread_spinunlock(self, &cond->ptc_lock);
    138 
    139 	if (signaled != NULL)
    140 		pthread__sched(self, signaled);
    141 
    142 	return 0;
    143 }
    144 
    145 
    146 int
    147 pthread_cond_broadacst(pthread_cond_t *cond)
    148 {
    149 	pthread_t self, signaled;
    150 	struct pt_queue_t blockedq, nullq = PTQ_HEAD_INITIALIZER;
    151 #ifdef ERRORCHECK
    152 	if ((cond == NULL) || (cond->ptc_magic != _PT_COND_MAGIC))
    153 		return EINVAL;
    154 #endif
    155 
    156 	self = pthread__self();
    157 
    158 	pthread_spinlock(self, &cond->ptc_lock);
    159 	blockedq = cond->ptc_waiters;
    160 	cond->ptc_waiters = nullq;
    161 	cond->ptc_mutex = NULL;
    162 	pthread_spinunlock(self, &cond->ptc_lock);
    163 
    164 	PTQ_FOREACH(signaled, &blockedq, pt_sleep)
    165 	    pthread__sched(self, signaled);
    166 
    167 	return 0;
    168 
    169 }
    170 
    171 
    172 int
    173 pthread_condattr_init(pthread_condattr_t *attr)
    174 {
    175 
    176 #ifdef ERRORCHECK
    177 	if (attr == NULL)
    178 		return EINVAL;
    179 #endif
    180 
    181 	attr->ptca_magic = _PT_CONDATTR_MAGIC;
    182 
    183 	return 0;
    184 }
    185 
    186 
    187 int
    188 pthread_condattr_destroy(pthread_condattr_t *attr)
    189 {
    190 
    191 #ifdef ERRORCHECK
    192 	if ((attr == NULL) ||
    193 	    (attr->ptca_magic != _PT_CONDATTR_MAGIC))
    194 		return EINVAL;
    195 #endif
    196 
    197 	attr->ptca_magic = _PT_CONDATTR_DEAD;
    198 
    199 	return 0;
    200 }
    201