changeset 256:640dcf27d2f7

*** empty log message ***
author Sam Lantinga <slouken@libsdl.org>
date Mon, 17 Dec 2001 19:56:28 +0000
parents dcb5e869f8b5
children 9ac9ab945955
files src/thread/Makefile.am src/thread/bsdi/SDL_syssem.c
diffstat 2 files changed, 509 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/thread/Makefile.am	Sun Dec 16 20:00:27 2001 +0000
+++ b/src/thread/Makefile.am	Mon Dec 17 19:56:28 2001 +0000
@@ -6,6 +6,7 @@
 ARCH_SUBDIRS = $(srcdir)/generic	\
                $(srcdir)/amigaos	\
                $(srcdir)/beos		\
+               $(srcdir)/bsdi		\
                $(srcdir)/epoc		\
                $(srcdir)/irix		\
                $(srcdir)/linux		\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/thread/bsdi/SDL_syssem.c	Mon Dec 17 19:56:28 2001 +0000
@@ -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 <stdlib.h>
+#include "SDL_error.h"
+#include "SDL_thread.h"
+#include "SDL_timer.h"
+
+#ifdef SDL_USE_PTHREADS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>			/* For getpid() */
+#include <pthread.h>
+
+
+/*
+ * 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 <machine/limits.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+/* Opaque type definition. */
+struct sem;
+typedef struct sem *sem_t;
+
+#define SEM_FAILED	((sem_t *)0)
+#define SEM_VALUE_MAX	UINT_MAX
+
+#include <sys/cdefs.h>
+
+__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 <jasone@freebsd.org>.
+ * 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 <errno.h>
+#include <semaphore.h>
+#include <pthread.h>
+
+/* 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 */