diff options
author | jasone <jasone@FreeBSD.org> | 2000-01-20 07:54:49 +0000 |
---|---|---|
committer | jasone <jasone@FreeBSD.org> | 2000-01-20 07:54:49 +0000 |
commit | 3daa9aa7192b6e32accee24548c7ea2a2c8847f8 (patch) | |
tree | d88a1880f596f77559e42bd51724390d0cf860ff /lib | |
parent | 9408134d9b43b47844401716af02afa4dc37b348 (diff) | |
download | FreeBSD-src-3daa9aa7192b6e32accee24548c7ea2a2c8847f8.zip FreeBSD-src-3daa9aa7192b6e32accee24548c7ea2a2c8847f8.tar.gz |
Add sem_*() functions. Named semaphores and process-shared semaphores
are not supported by this implementation, and the error return values
from sem_init(), sem_open(), sem_close(), and sem_unlink() reflect this.
Approved by: jkh
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc_r/uthread/Makefile.inc | 1 | ||||
-rw-r--r-- | lib/libc_r/uthread/pthread_private.h | 12 | ||||
-rw-r--r-- | lib/libc_r/uthread/uthread_sem.c | 224 | ||||
-rw-r--r-- | lib/libkse/thread/Makefile.inc | 1 | ||||
-rw-r--r-- | lib/libkse/thread/thr_private.h | 12 | ||||
-rw-r--r-- | lib/libkse/thread/thr_sem.c | 224 | ||||
-rw-r--r-- | lib/libpthread/thread/Makefile.inc | 1 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_private.h | 12 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_sem.c | 224 |
9 files changed, 711 insertions, 0 deletions
diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc index f46f007..2a13365 100644 --- a/lib/libc_r/uthread/Makefile.inc +++ b/lib/libc_r/uthread/Makefile.inc @@ -88,6 +88,7 @@ SRCS+= \ uthread_rwlockattr.c \ uthread_select.c \ uthread_self.c \ + uthread_sem.c \ uthread_sendmsg.c \ uthread_sendto.c \ uthread_seterrno.c \ diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h index 560ea44..00ca3b0 100644 --- a/lib/libc_r/uthread/pthread_private.h +++ b/lib/libc_r/uthread/pthread_private.h @@ -309,6 +309,18 @@ struct pthread_cond_attr { 0, _SPINLOCK_INITIALIZER } /* + * Semaphore definitions. + */ +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; +}; + +/* * Cleanup definitions. */ struct pthread_cleanup { diff --git a/lib/libc_r/uthread/uthread_sem.c b/lib/libc_r/uthread/uthread_sem.c new file mode 100644 index 0000000..8adb0d4 --- /dev/null +++ b/lib/libc_r/uthread/uthread_sem.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2000 Jason Evans <jasone@canonware.com>. + * 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$ + */ + +#include <errno.h> +#ifdef _THREAD_SAFE +#include <semaphore.h> +#include <pthread.h> +#include "pthread_private.h" + +#define _SEM_CHECK_VALIDITY(sem) \ + if ((*(sem))->magic != SEM_MAGIC) { \ + retval = EINVAL; \ + goto RETURN; \ + } + +int +sem_init(sem_t *sem, int pshared, unsigned int value) +{ + int retval; + + /* + * 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). + */ + retval = EPERM; + goto RETURN; + } + + if (value > SEM_VALUE_MAX) { + retval = EINVAL; + goto RETURN; + } + + *sem = (sem_t)malloc(sizeof(struct sem)); + if (*sem == NULL) { + retval = ENOSPC; + goto RETURN; + } + + /* + * Initialize the semaphore. + */ + retval = pthread_mutex_init(&(*sem)->lock, NULL); + if (retval != 0) { + free(*sem); + goto RETURN; + } + + retval = pthread_cond_init(&(*sem)->gtzero, NULL); + if (retval != 0) { + pthread_mutex_destroy(&(*sem)->lock); + free(*sem); + goto RETURN; + } + + (*sem)->count = (u_int32_t)value; + (*sem)->nwaiters = 0; + (*sem)->magic = SEM_MAGIC; + + 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); + retval = EBUSY; + 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; + + _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: + 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 + retval = EAGAIN; + + 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) + pthread_cond_signal(&(*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; +} +#endif diff --git a/lib/libkse/thread/Makefile.inc b/lib/libkse/thread/Makefile.inc index f46f007..2a13365 100644 --- a/lib/libkse/thread/Makefile.inc +++ b/lib/libkse/thread/Makefile.inc @@ -88,6 +88,7 @@ SRCS+= \ uthread_rwlockattr.c \ uthread_select.c \ uthread_self.c \ + uthread_sem.c \ uthread_sendmsg.c \ uthread_sendto.c \ uthread_seterrno.c \ diff --git a/lib/libkse/thread/thr_private.h b/lib/libkse/thread/thr_private.h index 560ea44..00ca3b0 100644 --- a/lib/libkse/thread/thr_private.h +++ b/lib/libkse/thread/thr_private.h @@ -309,6 +309,18 @@ struct pthread_cond_attr { 0, _SPINLOCK_INITIALIZER } /* + * Semaphore definitions. + */ +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; +}; + +/* * Cleanup definitions. */ struct pthread_cleanup { diff --git a/lib/libkse/thread/thr_sem.c b/lib/libkse/thread/thr_sem.c new file mode 100644 index 0000000..8adb0d4 --- /dev/null +++ b/lib/libkse/thread/thr_sem.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2000 Jason Evans <jasone@canonware.com>. + * 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$ + */ + +#include <errno.h> +#ifdef _THREAD_SAFE +#include <semaphore.h> +#include <pthread.h> +#include "pthread_private.h" + +#define _SEM_CHECK_VALIDITY(sem) \ + if ((*(sem))->magic != SEM_MAGIC) { \ + retval = EINVAL; \ + goto RETURN; \ + } + +int +sem_init(sem_t *sem, int pshared, unsigned int value) +{ + int retval; + + /* + * 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). + */ + retval = EPERM; + goto RETURN; + } + + if (value > SEM_VALUE_MAX) { + retval = EINVAL; + goto RETURN; + } + + *sem = (sem_t)malloc(sizeof(struct sem)); + if (*sem == NULL) { + retval = ENOSPC; + goto RETURN; + } + + /* + * Initialize the semaphore. + */ + retval = pthread_mutex_init(&(*sem)->lock, NULL); + if (retval != 0) { + free(*sem); + goto RETURN; + } + + retval = pthread_cond_init(&(*sem)->gtzero, NULL); + if (retval != 0) { + pthread_mutex_destroy(&(*sem)->lock); + free(*sem); + goto RETURN; + } + + (*sem)->count = (u_int32_t)value; + (*sem)->nwaiters = 0; + (*sem)->magic = SEM_MAGIC; + + 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); + retval = EBUSY; + 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; + + _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: + 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 + retval = EAGAIN; + + 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) + pthread_cond_signal(&(*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; +} +#endif diff --git a/lib/libpthread/thread/Makefile.inc b/lib/libpthread/thread/Makefile.inc index f46f007..2a13365 100644 --- a/lib/libpthread/thread/Makefile.inc +++ b/lib/libpthread/thread/Makefile.inc @@ -88,6 +88,7 @@ SRCS+= \ uthread_rwlockattr.c \ uthread_select.c \ uthread_self.c \ + uthread_sem.c \ uthread_sendmsg.c \ uthread_sendto.c \ uthread_seterrno.c \ diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h index 560ea44..00ca3b0 100644 --- a/lib/libpthread/thread/thr_private.h +++ b/lib/libpthread/thread/thr_private.h @@ -309,6 +309,18 @@ struct pthread_cond_attr { 0, _SPINLOCK_INITIALIZER } /* + * Semaphore definitions. + */ +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; +}; + +/* * Cleanup definitions. */ struct pthread_cleanup { diff --git a/lib/libpthread/thread/thr_sem.c b/lib/libpthread/thread/thr_sem.c new file mode 100644 index 0000000..8adb0d4 --- /dev/null +++ b/lib/libpthread/thread/thr_sem.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2000 Jason Evans <jasone@canonware.com>. + * 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$ + */ + +#include <errno.h> +#ifdef _THREAD_SAFE +#include <semaphore.h> +#include <pthread.h> +#include "pthread_private.h" + +#define _SEM_CHECK_VALIDITY(sem) \ + if ((*(sem))->magic != SEM_MAGIC) { \ + retval = EINVAL; \ + goto RETURN; \ + } + +int +sem_init(sem_t *sem, int pshared, unsigned int value) +{ + int retval; + + /* + * 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). + */ + retval = EPERM; + goto RETURN; + } + + if (value > SEM_VALUE_MAX) { + retval = EINVAL; + goto RETURN; + } + + *sem = (sem_t)malloc(sizeof(struct sem)); + if (*sem == NULL) { + retval = ENOSPC; + goto RETURN; + } + + /* + * Initialize the semaphore. + */ + retval = pthread_mutex_init(&(*sem)->lock, NULL); + if (retval != 0) { + free(*sem); + goto RETURN; + } + + retval = pthread_cond_init(&(*sem)->gtzero, NULL); + if (retval != 0) { + pthread_mutex_destroy(&(*sem)->lock); + free(*sem); + goto RETURN; + } + + (*sem)->count = (u_int32_t)value; + (*sem)->nwaiters = 0; + (*sem)->magic = SEM_MAGIC; + + 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); + retval = EBUSY; + 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; + + _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: + 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 + retval = EAGAIN; + + 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) + pthread_cond_signal(&(*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; +} +#endif |