From 12ed647be1cd55c291cdc1c212e41394b0abdba5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 17 Dec 2001 19:56:28 +0000 Subject: [PATCH] *** empty log message *** --- src/thread/Makefile.am | 1 + src/thread/bsdi/SDL_syssem.c | 508 +++++++++++++++++++++++++++++++++++ 2 files changed, 509 insertions(+) create mode 100644 src/thread/bsdi/SDL_syssem.c diff --git a/src/thread/Makefile.am b/src/thread/Makefile.am index 59f0126ce..98194a502 100644 --- a/src/thread/Makefile.am +++ b/src/thread/Makefile.am @@ -6,6 +6,7 @@ noinst_LTLIBRARIES = libthread.la ARCH_SUBDIRS = $(srcdir)/generic \ $(srcdir)/amigaos \ $(srcdir)/beos \ + $(srcdir)/bsdi \ $(srcdir)/epoc \ $(srcdir)/irix \ $(srcdir)/linux \ diff --git a/src/thread/bsdi/SDL_syssem.c b/src/thread/bsdi/SDL_syssem.c new file mode 100644 index 000000000..56faeef2e --- /dev/null +++ b/src/thread/bsdi/SDL_syssem.c @@ -0,0 +1,508 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@devolution.com +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id$"; +#endif + +#include +#include "SDL_error.h" +#include "SDL_thread.h" +#include "SDL_timer.h" + +#ifdef SDL_USE_PTHREADS + +#include +#include +#include /* For getpid() */ +#include + + +/* + * This is semaphore.h inlined here so that BSD/OS POSIX semaphore are + * completely selfcontained without requiring any additional include files + * or libraries not present in the stock system +*/ + +/* semaphore.h: POSIX 1003.1b semaphores */ + +/*- + * Copyright (c) 1996, 1997 + * HD Associates, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by HD Associates, Inc + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/posix4/semaphore.h,v 1.6 2000/01/20 07:55:42 jasone Exp $ + */ + +#include + +#include +#include + +/* Opaque type definition. */ +struct sem; +typedef struct sem *sem_t; + +#define SEM_FAILED ((sem_t *)0) +#define SEM_VALUE_MAX UINT_MAX + +#include + +__BEGIN_DECLS +int sem_init __P((sem_t *, int, unsigned int)); +int sem_destroy __P((sem_t *)); +sem_t *sem_open __P((const char *, int, ...)); +int sem_close __P((sem_t *)); +int sem_unlink __P((const char *)); +int sem_wait __P((sem_t *)); +int sem_trywait __P((sem_t *)); +int sem_post __P((sem_t *)); +int sem_getvalue __P((sem_t *, int *)); +__END_DECLS + +/* END of inlined semaphore.h */ + +/* Wrapper around POSIX 1003.1b semaphores */ + +struct SDL_semaphore { + sem_t *sem; + sem_t sem_data; +}; + +/* Create a semaphore, initialized with value */ +SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem = (SDL_sem *) malloc(sizeof(SDL_sem)); + if ( sem ) { + if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) { + SDL_SetError("sem_init() failed"); + free(sem); + sem = NULL; + } else { + sem->sem = &sem->sem_data; + } + } else { + SDL_OutOfMemory(); + } + return sem; +} + +void SDL_DestroySemaphore(SDL_sem *sem) +{ + if ( sem ) { + sem_destroy(sem->sem); + free(sem); + } +} + +int SDL_SemTryWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + retval = SDL_MUTEX_TIMEDOUT; + if ( sem_trywait(sem->sem) == 0 ) + retval = 0; + return retval; +} + +int SDL_SemWait(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = sem_wait(sem->sem); + if ( retval < 0 ) { + SDL_SetError("sem_wait() failed"); + } + return retval; +} + +int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + /* Try the easy cases first */ + if ( timeout == 0 ) { + return SDL_SemTryWait(sem); + } + if ( timeout == SDL_MUTEX_MAXWAIT ) { + return SDL_SemWait(sem); + } + + /* Ack! We have to busy wait... */ + timeout += SDL_GetTicks(); + do { + retval = SDL_SemTryWait(sem); + if ( retval == 0 ) { + break; + } + SDL_Delay(1); + } while ( SDL_GetTicks() < timeout ); + + return retval; +} + +Uint32 SDL_SemValue(SDL_sem *sem) +{ + int ret = 0; + if ( sem ) { + sem_getvalue(sem->sem, &ret); + if ( ret < 0 ) { + ret = 0; + } + } + return (Uint32)ret; +} + +int SDL_SemPost(SDL_sem *sem) +{ + int retval; + + if ( ! sem ) { + SDL_SetError("Passed a NULL semaphore"); + return -1; + } + + retval = sem_post(sem->sem); + if ( retval < 0 ) { + SDL_SetError("sem_post() failed"); + } + return retval; +} + +/* + * BEGIN inlined uthread_sem.c. This is done here so that no extra libraries + * or include files not present in BSD/OS are required +*/ + +/* + * Copyright (C) 2000 Jason Evans . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/lib/libc_r/uthread/uthread_sem.c,v 1.3.2.1 2000/07/18 02:05:57 jasone Exp $ + */ + +#include +#include +#include + +/* Begin thread_private.h kluge */ +/* + * These come out of (or should go into) thread_private.h - rather than have + * to copy (or symlink) the files from the source tree these definitions are + * inlined here. Obviously these go away when this module is part of libc. +*/ +struct sem { +#define SEM_MAGIC ((u_int32_t) 0x09fa4012) + u_int32_t magic; + pthread_mutex_t lock; + pthread_cond_t gtzero; + u_int32_t count; + u_int32_t nwaiters; +}; + +extern pthread_once_t _thread_init_once; +extern int _threads_initialized; +extern void _thread_init __P((void)); +#define THREAD_INIT() \ + (void) pthread_once(&_thread_init_once, _thread_init) +#define THREAD_SAFE() \ + (_threads_initialized != 0) + +#define _SEM_CHECK_VALIDITY(sem) \ + if ((*(sem))->magic != SEM_MAGIC) { \ + errno = EINVAL; \ + retval = -1; \ + goto RETURN; \ + } +/* End thread_private.h kluge */ + +int +sem_init(sem_t *sem, int pshared, unsigned int value) +{ + int retval; + + if (!THREAD_SAFE()) + THREAD_INIT(); + + /* + * Range check the arguments. + */ + if (pshared != 0) { + /* + * The user wants a semaphore that can be shared among + * processes, which this implementation can't do. Sounds like a + * permissions problem to me (yeah right). + */ + errno = EPERM; + retval = -1; + goto RETURN; + } + + if (value > SEM_VALUE_MAX) { + errno = EINVAL; + retval = -1; + goto RETURN; + } + + *sem = (sem_t)malloc(sizeof(struct sem)); + if (*sem == NULL) { + errno = ENOSPC; + retval = -1; + goto RETURN; + } + + /* + * Initialize the semaphore. + */ + if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) { + free(*sem); + errno = ENOSPC; + retval = -1; + goto RETURN; + } + + if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) { + pthread_mutex_destroy(&(*sem)->lock); + free(*sem); + errno = ENOSPC; + retval = -1; + goto RETURN; + } + + (*sem)->count = (u_int32_t)value; + (*sem)->nwaiters = 0; + (*sem)->magic = SEM_MAGIC; + + retval = 0; + RETURN: + return retval; +} + +int +sem_destroy(sem_t *sem) +{ + int retval; + + _SEM_CHECK_VALIDITY(sem); + + /* Make sure there are no waiters. */ + pthread_mutex_lock(&(*sem)->lock); + if ((*sem)->nwaiters > 0) { + pthread_mutex_unlock(&(*sem)->lock); + errno = EBUSY; + retval = -1; + goto RETURN; + } + pthread_mutex_unlock(&(*sem)->lock); + + pthread_mutex_destroy(&(*sem)->lock); + pthread_cond_destroy(&(*sem)->gtzero); + (*sem)->magic = 0; + + free(*sem); + + retval = 0; + RETURN: + return retval; +} + +sem_t * +sem_open(const char *name, int oflag, ...) +{ + errno = ENOSYS; + return SEM_FAILED; +} + +int +sem_close(sem_t *sem) +{ + errno = ENOSYS; + return -1; +} + +int +sem_unlink(const char *name) +{ + errno = ENOSYS; + return -1; +} + +int +sem_wait(sem_t *sem) +{ + int retval; + + pthread_testcancel(); + + _SEM_CHECK_VALIDITY(sem); + + pthread_mutex_lock(&(*sem)->lock); + + while ((*sem)->count == 0) { + (*sem)->nwaiters++; + pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock); + (*sem)->nwaiters--; + } + (*sem)->count--; + + pthread_mutex_unlock(&(*sem)->lock); + + retval = 0; + RETURN: + + pthread_testcancel(); + return retval; +} + +int +sem_trywait(sem_t *sem) +{ + int retval; + + _SEM_CHECK_VALIDITY(sem); + + pthread_mutex_lock(&(*sem)->lock); + + if ((*sem)->count > 0) { + (*sem)->count--; + retval = 0; + } else { + errno = EAGAIN; + retval = -1; + } + + pthread_mutex_unlock(&(*sem)->lock); + + RETURN: + return retval; +} + +int +sem_post(sem_t *sem) +{ + int retval; + + _SEM_CHECK_VALIDITY(sem); + + pthread_mutex_lock(&(*sem)->lock); + + (*sem)->count++; + if ((*sem)->nwaiters > 0) { + /* + * We must use pthread_cond_broadcast() rather than + * pthread_cond_signal() in order to assure that the highest + * priority thread is run by the scheduler, since + * pthread_cond_signal() signals waiting threads in FIFO order. + */ + pthread_cond_broadcast(&(*sem)->gtzero); + } + + pthread_mutex_unlock(&(*sem)->lock); + + retval = 0; + RETURN: + return retval; +} + +int +sem_getvalue(sem_t *sem, int *sval) +{ + int retval; + + _SEM_CHECK_VALIDITY(sem); + + pthread_mutex_lock(&(*sem)->lock); + *sval = (int)(*sem)->count; + pthread_mutex_unlock(&(*sem)->lock); + + retval = 0; + RETURN: + return retval; +} + +/* END of inlined uthread_sem.c */ +#endif /* SDL_USE_PTHREADS */