*** empty log message ***
authorSam Lantinga <slouken@libsdl.org>
Mon, 17 Dec 2001 19:56:28 +0000
changeset 256640dcf27d2f7
parent 255 dcb5e869f8b5
child 257 9ac9ab945955
*** empty log message ***
src/thread/Makefile.am
src/thread/bsdi/SDL_syssem.c
     1.1 --- a/src/thread/Makefile.am	Sun Dec 16 20:00:27 2001 +0000
     1.2 +++ b/src/thread/Makefile.am	Mon Dec 17 19:56:28 2001 +0000
     1.3 @@ -6,6 +6,7 @@
     1.4  ARCH_SUBDIRS = $(srcdir)/generic	\
     1.5                 $(srcdir)/amigaos	\
     1.6                 $(srcdir)/beos		\
     1.7 +               $(srcdir)/bsdi		\
     1.8                 $(srcdir)/epoc		\
     1.9                 $(srcdir)/irix		\
    1.10                 $(srcdir)/linux		\
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/thread/bsdi/SDL_syssem.c	Mon Dec 17 19:56:28 2001 +0000
     2.3 @@ -0,0 +1,508 @@
     2.4 +/*
     2.5 +    SDL - Simple DirectMedia Layer
     2.6 +    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
     2.7 +
     2.8 +    This library is free software; you can redistribute it and/or
     2.9 +    modify it under the terms of the GNU Library General Public
    2.10 +    License as published by the Free Software Foundation; either
    2.11 +    version 2 of the License, or (at your option) any later version.
    2.12 +
    2.13 +    This library is distributed in the hope that it will be useful,
    2.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    2.16 +    Library General Public License for more details.
    2.17 +
    2.18 +    You should have received a copy of the GNU Library General Public
    2.19 +    License along with this library; if not, write to the Free
    2.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.21 +
    2.22 +    Sam Lantinga
    2.23 +    slouken@devolution.com
    2.24 +*/
    2.25 +
    2.26 +#ifdef SAVE_RCSID
    2.27 +static char rcsid =
    2.28 + "@(#) $Id$";
    2.29 +#endif
    2.30 +
    2.31 +#include <stdlib.h>
    2.32 +#include "SDL_error.h"
    2.33 +#include "SDL_thread.h"
    2.34 +#include "SDL_timer.h"
    2.35 +
    2.36 +#ifdef SDL_USE_PTHREADS
    2.37 +
    2.38 +#include <stdio.h>
    2.39 +#include <stdlib.h>
    2.40 +#include <unistd.h>			/* For getpid() */
    2.41 +#include <pthread.h>
    2.42 +
    2.43 +
    2.44 +/*
    2.45 + * This is semaphore.h inlined here so that BSD/OS POSIX semaphore are
    2.46 + * completely selfcontained without requiring any additional include files
    2.47 + * or libraries not present in the stock system
    2.48 +*/
    2.49 +
    2.50 +/* semaphore.h: POSIX 1003.1b semaphores */
    2.51 +
    2.52 +/*-
    2.53 + * Copyright (c) 1996, 1997
    2.54 + *	HD Associates, Inc.  All rights reserved.
    2.55 + *
    2.56 + * Redistribution and use in source and binary forms, with or without
    2.57 + * modification, are permitted provided that the following conditions
    2.58 + * are met:
    2.59 + * 1. Redistributions of source code must retain the above copyright
    2.60 + *    notice, this list of conditions and the following disclaimer.
    2.61 + * 2. Redistributions in binary form must reproduce the above copyright
    2.62 + *    notice, this list of conditions and the following disclaimer in the
    2.63 + *    documentation and/or other materials provided with the distribution.
    2.64 + * 3. All advertising materials mentioning features or use of this software
    2.65 + *    must display the following acknowledgement:
    2.66 + *	This product includes software developed by HD Associates, Inc
    2.67 + * 4. Neither the name of the author nor the names of any co-contributors
    2.68 + *    may be used to endorse or promote products derived from this software
    2.69 + *    without specific prior written permission.
    2.70 + *
    2.71 + * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND
    2.72 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    2.73 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    2.74 + * ARE DISCLAIMED.  IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
    2.75 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    2.76 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    2.77 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    2.78 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    2.79 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    2.80 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    2.81 + * SUCH DAMAGE.
    2.82 + *
    2.83 + * $FreeBSD: src/sys/posix4/semaphore.h,v 1.6 2000/01/20 07:55:42 jasone Exp $
    2.84 + */
    2.85 +
    2.86 +#include <machine/limits.h>
    2.87 +
    2.88 +#include <sys/types.h>
    2.89 +#include <fcntl.h>
    2.90 +
    2.91 +/* Opaque type definition. */
    2.92 +struct sem;
    2.93 +typedef struct sem *sem_t;
    2.94 +
    2.95 +#define SEM_FAILED	((sem_t *)0)
    2.96 +#define SEM_VALUE_MAX	UINT_MAX
    2.97 +
    2.98 +#include <sys/cdefs.h>
    2.99 +
   2.100 +__BEGIN_DECLS
   2.101 +int	 sem_init __P((sem_t *, int, unsigned int));
   2.102 +int	 sem_destroy __P((sem_t *));
   2.103 +sem_t	*sem_open __P((const char *, int, ...));
   2.104 +int	 sem_close __P((sem_t *));
   2.105 +int	 sem_unlink __P((const char *));
   2.106 +int	 sem_wait __P((sem_t *));
   2.107 +int	 sem_trywait __P((sem_t *));
   2.108 +int	 sem_post __P((sem_t *));
   2.109 +int	 sem_getvalue __P((sem_t *, int *));
   2.110 +__END_DECLS
   2.111 +
   2.112 +/* END of inlined semaphore.h */
   2.113 +
   2.114 +/* Wrapper around POSIX 1003.1b semaphores */
   2.115 +
   2.116 +struct SDL_semaphore {
   2.117 +	sem_t *sem;
   2.118 +	sem_t sem_data;
   2.119 +};
   2.120 +
   2.121 +/* Create a semaphore, initialized with value */
   2.122 +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
   2.123 +{
   2.124 +	SDL_sem *sem = (SDL_sem *) malloc(sizeof(SDL_sem));
   2.125 +	if ( sem ) {
   2.126 +		if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) {
   2.127 +			SDL_SetError("sem_init() failed");
   2.128 +			free(sem);
   2.129 +			sem = NULL;
   2.130 +		} else {
   2.131 +			sem->sem = &sem->sem_data;
   2.132 +		}
   2.133 +	} else {
   2.134 +		SDL_OutOfMemory();
   2.135 +	}
   2.136 +	return sem;
   2.137 +}
   2.138 +
   2.139 +void SDL_DestroySemaphore(SDL_sem *sem)
   2.140 +{
   2.141 +	if ( sem ) {
   2.142 +		sem_destroy(sem->sem);
   2.143 +		free(sem);
   2.144 +	}
   2.145 +}
   2.146 +
   2.147 +int SDL_SemTryWait(SDL_sem *sem)
   2.148 +{
   2.149 +	int retval;
   2.150 +
   2.151 +	if ( ! sem ) {
   2.152 +		SDL_SetError("Passed a NULL semaphore");
   2.153 +		return -1;
   2.154 +	}
   2.155 +	retval = SDL_MUTEX_TIMEDOUT;
   2.156 +	if ( sem_trywait(sem->sem) == 0 )
   2.157 +		retval = 0;
   2.158 +	return retval;
   2.159 +}
   2.160 +
   2.161 +int SDL_SemWait(SDL_sem *sem)
   2.162 +{
   2.163 +	int retval;
   2.164 +
   2.165 +	if ( ! sem ) {
   2.166 +		SDL_SetError("Passed a NULL semaphore");
   2.167 +		return -1;
   2.168 +	}
   2.169 +
   2.170 +	retval = sem_wait(sem->sem);
   2.171 +	if ( retval < 0 ) {
   2.172 +		SDL_SetError("sem_wait() failed");
   2.173 +	}
   2.174 +	return retval;
   2.175 +}
   2.176 +
   2.177 +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
   2.178 +{
   2.179 +	int retval;
   2.180 +
   2.181 +	if ( ! sem ) {
   2.182 +		SDL_SetError("Passed a NULL semaphore");
   2.183 +		return -1;
   2.184 +	}
   2.185 +
   2.186 +	/* Try the easy cases first */
   2.187 +	if ( timeout == 0 ) {
   2.188 +		return SDL_SemTryWait(sem);
   2.189 +	}
   2.190 +	if ( timeout == SDL_MUTEX_MAXWAIT ) {
   2.191 +		return SDL_SemWait(sem);
   2.192 +	}
   2.193 +
   2.194 +	/* Ack!  We have to busy wait... */
   2.195 +	timeout += SDL_GetTicks();
   2.196 +	do {
   2.197 +		retval = SDL_SemTryWait(sem);
   2.198 +		if ( retval == 0 ) {
   2.199 +			break;
   2.200 +		}
   2.201 +		SDL_Delay(1);
   2.202 +	} while ( SDL_GetTicks() < timeout );
   2.203 +
   2.204 +	return retval;
   2.205 +}
   2.206 +
   2.207 +Uint32 SDL_SemValue(SDL_sem *sem)
   2.208 +{
   2.209 +	int ret = 0;
   2.210 +	if ( sem ) {
   2.211 +		sem_getvalue(sem->sem, &ret);
   2.212 +		if ( ret < 0 ) {
   2.213 +			ret = 0;
   2.214 +		}
   2.215 +	}
   2.216 +	return (Uint32)ret;
   2.217 +}
   2.218 +
   2.219 +int SDL_SemPost(SDL_sem *sem)
   2.220 +{
   2.221 +	int retval;
   2.222 +
   2.223 +	if ( ! sem ) {
   2.224 +		SDL_SetError("Passed a NULL semaphore");
   2.225 +		return -1;
   2.226 +	}
   2.227 +
   2.228 +	retval = sem_post(sem->sem);
   2.229 +	if ( retval < 0 ) {
   2.230 +		SDL_SetError("sem_post() failed");
   2.231 +	}
   2.232 +	return retval;
   2.233 +}
   2.234 +
   2.235 +/* 
   2.236 + * BEGIN inlined uthread_sem.c.  This is done here so that no extra libraries
   2.237 + * or include files not present in BSD/OS are required
   2.238 +*/
   2.239 +
   2.240 +/*
   2.241 + * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
   2.242 + * All rights reserved.
   2.243 + * 
   2.244 + * Redistribution and use in source and binary forms, with or without
   2.245 + * modification, are permitted provided that the following conditions
   2.246 + * are met:
   2.247 + * 1. Redistributions of source code must retain the above copyright
   2.248 + *    notice(s), this list of conditions and the following disclaimer as
   2.249 + *    the first lines of this file unmodified other than the possible
   2.250 + *    addition of one or more copyright notices.
   2.251 + * 2. Redistributions in binary form must reproduce the above copyright
   2.252 + *    notice(s), this list of conditions and the following disclaimer in
   2.253 + *    the documentation and/or other materials provided with the
   2.254 + *    distribution.
   2.255 + * 
   2.256 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
   2.257 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   2.258 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   2.259 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
   2.260 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   2.261 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   2.262 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   2.263 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   2.264 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
   2.265 + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   2.266 + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   2.267 + *
   2.268 + * $FreeBSD: src/lib/libc_r/uthread/uthread_sem.c,v 1.3.2.1 2000/07/18 02:05:57 jasone Exp $
   2.269 + */
   2.270 +
   2.271 +#include <errno.h>
   2.272 +#include <semaphore.h>
   2.273 +#include <pthread.h>
   2.274 +
   2.275 +/* Begin thread_private.h kluge */
   2.276 +/*
   2.277 + * These come out of (or should go into) thread_private.h - rather than have 
   2.278 + * to copy (or symlink) the files from the source tree these definitions are 
   2.279 + * inlined here.  Obviously these go away when this module is part of libc.
   2.280 +*/
   2.281 +struct sem {
   2.282 +#define SEM_MAGIC       ((u_int32_t) 0x09fa4012)
   2.283 +        u_int32_t       magic;
   2.284 +        pthread_mutex_t lock;
   2.285 +        pthread_cond_t  gtzero;
   2.286 +        u_int32_t       count;
   2.287 +        u_int32_t       nwaiters;
   2.288 +};
   2.289 +
   2.290 +extern pthread_once_t _thread_init_once;
   2.291 +extern int _threads_initialized;
   2.292 +extern void  _thread_init __P((void));
   2.293 +#define THREAD_INIT() \
   2.294 +	(void) pthread_once(&_thread_init_once, _thread_init)
   2.295 +#define THREAD_SAFE() \
   2.296 +	(_threads_initialized != 0)
   2.297 +
   2.298 +#define _SEM_CHECK_VALIDITY(sem)		\
   2.299 +	if ((*(sem))->magic != SEM_MAGIC) {	\
   2.300 +		errno = EINVAL;			\
   2.301 +		retval = -1;			\
   2.302 +		goto RETURN;			\
   2.303 +	}
   2.304 +/* End thread_private.h kluge */
   2.305 +
   2.306 +int
   2.307 +sem_init(sem_t *sem, int pshared, unsigned int value)
   2.308 +{
   2.309 +	int	retval;
   2.310 +
   2.311 +	if (!THREAD_SAFE())
   2.312 +		THREAD_INIT();
   2.313 +
   2.314 +	/*
   2.315 +	 * Range check the arguments.
   2.316 +	 */
   2.317 +	if (pshared != 0) {
   2.318 +		/*
   2.319 +		 * The user wants a semaphore that can be shared among
   2.320 +		 * processes, which this implementation can't do.  Sounds like a
   2.321 +		 * permissions problem to me (yeah right).
   2.322 +		 */
   2.323 +		errno = EPERM;
   2.324 +		retval = -1;
   2.325 +		goto RETURN;
   2.326 +	}
   2.327 +
   2.328 +	if (value > SEM_VALUE_MAX) {
   2.329 +		errno = EINVAL;
   2.330 +		retval = -1;
   2.331 +		goto RETURN;
   2.332 +	}
   2.333 +
   2.334 +	*sem = (sem_t)malloc(sizeof(struct sem));
   2.335 +	if (*sem == NULL) {
   2.336 +		errno = ENOSPC;
   2.337 +		retval = -1;
   2.338 +		goto RETURN;
   2.339 +	}
   2.340 +
   2.341 +	/*
   2.342 +	 * Initialize the semaphore.
   2.343 +	 */
   2.344 +	if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) {
   2.345 +		free(*sem);
   2.346 +		errno = ENOSPC;
   2.347 +		retval = -1;
   2.348 +		goto RETURN;
   2.349 +	}
   2.350 +
   2.351 +	if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) {
   2.352 +		pthread_mutex_destroy(&(*sem)->lock);
   2.353 +		free(*sem);
   2.354 +		errno = ENOSPC;
   2.355 +		retval = -1;
   2.356 +		goto RETURN;
   2.357 +	}
   2.358 +	
   2.359 +	(*sem)->count = (u_int32_t)value;
   2.360 +	(*sem)->nwaiters = 0;
   2.361 +	(*sem)->magic = SEM_MAGIC;
   2.362 +
   2.363 +	retval = 0;
   2.364 +  RETURN:
   2.365 +	return retval;
   2.366 +}
   2.367 +
   2.368 +int
   2.369 +sem_destroy(sem_t *sem)
   2.370 +{
   2.371 +	int	retval;
   2.372 +	
   2.373 +	_SEM_CHECK_VALIDITY(sem);
   2.374 +
   2.375 +	/* Make sure there are no waiters. */
   2.376 +	pthread_mutex_lock(&(*sem)->lock);
   2.377 +	if ((*sem)->nwaiters > 0) {
   2.378 +		pthread_mutex_unlock(&(*sem)->lock);
   2.379 +		errno = EBUSY;
   2.380 +		retval = -1;
   2.381 +		goto RETURN;
   2.382 +	}
   2.383 +	pthread_mutex_unlock(&(*sem)->lock);
   2.384 +	
   2.385 +	pthread_mutex_destroy(&(*sem)->lock);
   2.386 +	pthread_cond_destroy(&(*sem)->gtzero);
   2.387 +	(*sem)->magic = 0;
   2.388 +
   2.389 +	free(*sem);
   2.390 +
   2.391 +	retval = 0;
   2.392 +  RETURN:
   2.393 +	return retval;
   2.394 +}
   2.395 +
   2.396 +sem_t *
   2.397 +sem_open(const char *name, int oflag, ...)
   2.398 +{
   2.399 +	errno = ENOSYS;
   2.400 +	return SEM_FAILED;
   2.401 +}
   2.402 +
   2.403 +int
   2.404 +sem_close(sem_t *sem)
   2.405 +{
   2.406 +	errno = ENOSYS;
   2.407 +	return -1;
   2.408 +}
   2.409 +
   2.410 +int
   2.411 +sem_unlink(const char *name)
   2.412 +{
   2.413 +	errno = ENOSYS;
   2.414 +	return -1;
   2.415 +}
   2.416 +
   2.417 +int
   2.418 +sem_wait(sem_t *sem)
   2.419 +{
   2.420 +	int	retval;
   2.421 +
   2.422 +	pthread_testcancel();
   2.423 +	
   2.424 +	_SEM_CHECK_VALIDITY(sem);
   2.425 +
   2.426 +	pthread_mutex_lock(&(*sem)->lock);
   2.427 +
   2.428 +	while ((*sem)->count == 0) {
   2.429 +		(*sem)->nwaiters++;
   2.430 +		pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock);
   2.431 +		(*sem)->nwaiters--;
   2.432 +	}
   2.433 +	(*sem)->count--;
   2.434 +
   2.435 +	pthread_mutex_unlock(&(*sem)->lock);
   2.436 +
   2.437 +	retval = 0;
   2.438 +  RETURN:
   2.439 +
   2.440 +	pthread_testcancel();
   2.441 +	return retval;
   2.442 +}
   2.443 +
   2.444 +int
   2.445 +sem_trywait(sem_t *sem)
   2.446 +{
   2.447 +	int	retval;
   2.448 +
   2.449 +	_SEM_CHECK_VALIDITY(sem);
   2.450 +
   2.451 +	pthread_mutex_lock(&(*sem)->lock);
   2.452 +
   2.453 +	if ((*sem)->count > 0) {
   2.454 +		(*sem)->count--;
   2.455 +		retval = 0;
   2.456 +	} else {
   2.457 +		errno = EAGAIN;
   2.458 +		retval = -1;
   2.459 +	}
   2.460 +	
   2.461 +	pthread_mutex_unlock(&(*sem)->lock);
   2.462 +
   2.463 +  RETURN:
   2.464 +	return retval;
   2.465 +}
   2.466 +
   2.467 +int
   2.468 +sem_post(sem_t *sem)
   2.469 +{
   2.470 +	int	retval;
   2.471 +
   2.472 +	_SEM_CHECK_VALIDITY(sem);
   2.473 +
   2.474 +	pthread_mutex_lock(&(*sem)->lock);
   2.475 +
   2.476 +	(*sem)->count++;
   2.477 +	if ((*sem)->nwaiters > 0) {
   2.478 +		/*
   2.479 +		 * We must use pthread_cond_broadcast() rather than
   2.480 +		 * pthread_cond_signal() in order to assure that the highest
   2.481 +		 * priority thread is run by the scheduler, since
   2.482 +		 * pthread_cond_signal() signals waiting threads in FIFO order.
   2.483 +		 */
   2.484 +		pthread_cond_broadcast(&(*sem)->gtzero);
   2.485 +	}
   2.486 +
   2.487 +	pthread_mutex_unlock(&(*sem)->lock);
   2.488 +
   2.489 +	retval = 0;
   2.490 +  RETURN:
   2.491 +	return retval;
   2.492 +}
   2.493 +
   2.494 +int
   2.495 +sem_getvalue(sem_t *sem, int *sval)
   2.496 +{
   2.497 +	int	retval;
   2.498 +
   2.499 +	_SEM_CHECK_VALIDITY(sem);
   2.500 +
   2.501 +	pthread_mutex_lock(&(*sem)->lock);
   2.502 +	*sval = (int)(*sem)->count;
   2.503 +	pthread_mutex_unlock(&(*sem)->lock);
   2.504 +
   2.505 +	retval = 0;
   2.506 +  RETURN:
   2.507 +	return retval;
   2.508 +}
   2.509 +
   2.510 +/* END of inlined uthread_sem.c */
   2.511 +#endif /* SDL_USE_PTHREADS */