Index: include/Makefile =================================================================== --- include/Makefile (revision 200821) +++ include/Makefile (working copy) @@ -18,7 +18,7 @@ netdb.h nl_types.h nlist.h nss.h nsswitch.h paths.h \ printf.h proc_service.h pthread.h \ pthread_np.h pwd.h ranlib.h readpassphrase.h regex.h regexp.h \ - res_update.h resolv.h runetype.h search.h setjmp.h \ + res_update.h resolv.h runetype.h search.h semaphore.h setjmp.h \ signal.h spawn.h stab.h \ stdbool.h stddef.h stdio.h stdlib.h string.h stringlist.h \ strings.h sysexits.h tar.h termios.h tgmath.h \ @@ -28,7 +28,7 @@ MHDRS= float.h floatingpoint.h stdarg.h -PHDRS= sched.h semaphore.h _semaphore.h +PHDRS= sched.h _semaphore.h LHDRS= aio.h errno.h fcntl.h linker_set.h poll.h stdint.h syslog.h \ ucontext.h Index: include/semaphore.h =================================================================== --- include/semaphore.h (revision 0) +++ include/semaphore.h (revision 0) @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009 David Xu + * + * 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 unmodified, 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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$ + */ + +/* semaphore.h: POSIX 1003.1b semaphores */ + +#ifndef _SEMAPHORE_H_ +#define _SEMAPHORE_H_ + +#include +#include +#include + +struct _sem { + uint32_t magic; + struct _usem data; +}; + +typedef struct _sem sem_t; + +#define SEM_FAILED ((sem_t *)0) +#define SEM_VALUE_MAX __INT_MAX + +struct timespec; + +__BEGIN_DECLS +int sem_close(sem_t *); +int sem_destroy(sem_t *); +int sem_getvalue(sem_t * __restrict, int * __restrict); +int sem_init(sem_t *, int, unsigned int); +sem_t *sem_open(const char *, int, ...); +int sem_post(sem_t *); +int sem_timedwait(sem_t * __restrict, const struct timespec * __restrict); +int sem_trywait(sem_t *); +int sem_unlink(const char *); +int sem_wait(sem_t *); +__END_DECLS + +#endif /* !_SEMAPHORE_H_ */ Index: lib/libc/gen/sem.c =================================================================== --- lib/libc/gen/sem.c (revision 200821) +++ lib/libc/gen/sem.c (working copy) @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Jason Evans . + * Copyright (C) 2009 David Xu . * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,333 +29,103 @@ * $FreeBSD$ */ -/* - * Some notes about this implementation. - * - * This is mostly a simple implementation of POSIX semaphores that - * does not need threading. Any semaphore created is a kernel-based - * semaphore regardless of the pshared attribute. This is necessary - * because libc's stub for pthread_cond_wait() doesn't really wait, - * and it is not worth the effort impose this behavior on libc. - * - * All functions here are designed to be thread-safe so that a - * threads library need not provide wrappers except to make - * sem_wait() and sem_timedwait() cancellation points or to - * provide a faster userland implementation for non-pshared - * semaphores. - * - * Also, this implementation of semaphores cannot really support - * real pshared semaphores. The sem_t is an allocated object - * and can't be seen by other processes when placed in shared - * memory. It should work across forks as long as the semaphore - * is created before any forks. - * - * The function sem_init() should be overridden by a threads - * library if it wants to provide a different userland version - * of semaphores. The functions sem_wait() and sem_timedwait() - * need to be wrapped to provide cancellation points. The function - * sem_post() may need to be wrapped to be signal-safe. - */ #include "namespace.h" #include -#include -#include -#include -#include #include -#include +#include #include -#include -#include <_semaphore.h> #include "un-namespace.h" -#include "libc_private.h" -static sem_t sem_alloc(unsigned int value, semid_t semid, int system_sem); -static void sem_free(sem_t sem); +__weak_reference(_sem_init, sem_init); +__weak_reference(_sem_close, sem_close); +__weak_reference(_sem_destroy, sem_destroy); +__weak_reference(_sem_getvalue, sem_getvalue); +__weak_reference(_sem_open, sem_open); +__weak_reference(_sem_trywait, sem_trywait); +__weak_reference(_sem_wait, sem_wait); +__weak_reference(_sem_timedwait, sem_timedwait); +__weak_reference(_sem_post, sem_post); +__weak_reference(_sem_unlink, sem_unlink); -static LIST_HEAD(, sem) named_sems = LIST_HEAD_INITIALIZER(&named_sems); -static pthread_mutex_t named_sems_mtx = PTHREAD_MUTEX_INITIALIZER; - -__weak_reference(__sem_init, sem_init); -__weak_reference(__sem_destroy, sem_destroy); -__weak_reference(__sem_open, sem_open); -__weak_reference(__sem_close, sem_close); -__weak_reference(__sem_unlink, sem_unlink); -__weak_reference(__sem_wait, sem_wait); -__weak_reference(__sem_trywait, sem_trywait); -__weak_reference(__sem_timedwait, sem_timedwait); -__weak_reference(__sem_post, sem_post); -__weak_reference(__sem_getvalue, sem_getvalue); - - -static inline int -sem_check_validity(sem_t *sem) +static +void report_error(const char *func) { - - if ((sem != NULL) && ((*sem)->magic == SEM_MAGIC)) - return (0); - else { - errno = EINVAL; - return (-1); - } + fprintf(stderr, "%s() is not implemented, please link program against libpthread.\n", func); + abort(); } -static void -sem_free(sem_t sem) +int +_sem_init(sem_t *sem, int pshared, unsigned int value) { - - _pthread_mutex_destroy(&sem->lock); - _pthread_cond_destroy(&sem->gtzero); - sem->magic = 0; - free(sem); + report_error(__func__); + return (-1); } -static sem_t -sem_alloc(unsigned int value, semid_t semid, int system_sem) +sem_t * +_sem_open(const char *name, int flags, ...) { - sem_t sem; - - if (value > SEM_VALUE_MAX) { - errno = EINVAL; - return (NULL); - } - - sem = (sem_t)malloc(sizeof(struct sem)); - if (sem == NULL) { - errno = ENOSPC; - return (NULL); - } - - sem->count = (u_int32_t)value; - sem->nwaiters = 0; - sem->magic = SEM_MAGIC; - sem->semid = semid; - sem->syssem = system_sem; - sem->lock = PTHREAD_MUTEX_INITIALIZER; - sem->gtzero = PTHREAD_COND_INITIALIZER; - return (sem); + report_error(__func__); + return (NULL); } int -__sem_init(sem_t *sem, int pshared, unsigned int value) +_sem_close(sem_t *sem) { - semid_t semid; - - /* - * We always have to create the kernel semaphore if the - * threads library isn't present since libc's version of - * pthread_cond_wait() is just a stub that doesn't really - * wait. - */ - if (ksem_init(&semid, value) != 0) - return (-1); - - (*sem) = sem_alloc(value, semid, 1); - if ((*sem) == NULL) { - ksem_destroy(semid); - return (-1); - } - return (0); + report_error(__func__); + return (-1); } int -__sem_destroy(sem_t *sem) +_sem_unlink(const char *name) { - int retval; - - if (sem_check_validity(sem) != 0) - return (-1); - - _pthread_mutex_lock(&(*sem)->lock); - /* - * If this is a system semaphore let the kernel track it otherwise - * make sure there are no waiters. - */ - if ((*sem)->syssem != 0) - retval = ksem_destroy((*sem)->semid); - else if ((*sem)->nwaiters > 0) { - errno = EBUSY; - retval = -1; - } - else { - retval = 0; - (*sem)->magic = 0; - } - _pthread_mutex_unlock(&(*sem)->lock); - - if (retval == 0) { - _pthread_mutex_destroy(&(*sem)->lock); - _pthread_cond_destroy(&(*sem)->gtzero); - sem_free(*sem); - } - return (retval); + report_error(__func__); + return (-1); } -sem_t * -__sem_open(const char *name, int oflag, ...) -{ - sem_t *sem; - sem_t s; - semid_t semid; - mode_t mode; - unsigned int value; - - mode = 0; - value = 0; - - if ((oflag & O_CREAT) != 0) { - va_list ap; - - va_start(ap, oflag); - mode = va_arg(ap, int); - value = va_arg(ap, unsigned int); - va_end(ap); - } - /* - * we can be lazy and let the kernel handle the "oflag", - * we'll just merge duplicate IDs into our list. - */ - if (ksem_open(&semid, name, oflag, mode, value) == -1) - return (SEM_FAILED); - /* - * search for a duplicate ID, we must return the same sem_t * - * if we locate one. - */ - _pthread_mutex_lock(&named_sems_mtx); - LIST_FOREACH(s, &named_sems, entry) { - if (s->semid == semid) { - sem = s->backpointer; - _pthread_mutex_unlock(&named_sems_mtx); - return (sem); - } - } - sem = (sem_t *)malloc(sizeof(*sem)); - if (sem == NULL) - goto err; - *sem = sem_alloc(value, semid, 1); - if ((*sem) == NULL) - goto err; - LIST_INSERT_HEAD(&named_sems, *sem, entry); - (*sem)->backpointer = sem; - _pthread_mutex_unlock(&named_sems_mtx); - return (sem); -err: - _pthread_mutex_unlock(&named_sems_mtx); - ksem_close(semid); - if (sem != NULL) { - if (*sem != NULL) - sem_free(*sem); - else - errno = ENOSPC; - free(sem); - } else { - errno = ENOSPC; - } - return (SEM_FAILED); -} - int -__sem_close(sem_t *sem) +_sem_destroy(sem_t *sem) { - - if (sem_check_validity(sem) != 0) - return (-1); - - if ((*sem)->syssem == 0) { - errno = EINVAL; - return (-1); - } - - _pthread_mutex_lock(&named_sems_mtx); - if (ksem_close((*sem)->semid) != 0) { - _pthread_mutex_unlock(&named_sems_mtx); - return (-1); - } - LIST_REMOVE((*sem), entry); - _pthread_mutex_unlock(&named_sems_mtx); - sem_free(*sem); - *sem = NULL; - free(sem); - return (0); + report_error(__func__); + return (-1); } int -__sem_unlink(const char *name) +_sem_getvalue(sem_t * __restrict sem, int * __restrict sval) { - - return (ksem_unlink(name)); + report_error(__func__); + return (-1); } int -__sem_wait(sem_t *sem) +_sem_trywait(sem_t *sem) { - - if (sem_check_validity(sem) != 0) - return (-1); - - return (ksem_wait((*sem)->semid)); + report_error(__func__); + return (-1); } int -__sem_trywait(sem_t *sem) +_sem_wait(sem_t *sem) { - int retval; - - if (sem_check_validity(sem) != 0) - return (-1); - - if ((*sem)->syssem != 0) - retval = ksem_trywait((*sem)->semid); - else { - _pthread_mutex_lock(&(*sem)->lock); - if ((*sem)->count > 0) { - (*sem)->count--; - retval = 0; - } else { - errno = EAGAIN; - retval = -1; - } - _pthread_mutex_unlock(&(*sem)->lock); - } - return (retval); + report_error(__func__); + return (-1); } int -__sem_timedwait(sem_t * __restrict sem, - const struct timespec * __restrict abs_timeout) +_sem_timedwait(sem_t * __restrict sem, + const struct timespec * __restrict abstime) { - if (sem_check_validity(sem) != 0) - return (-1); - - return (ksem_timedwait((*sem)->semid, abs_timeout)); + report_error(__func__); + return (-1); } -int -__sem_post(sem_t *sem) -{ +/* + * sem_post() is required to be safe to call from within + * signal handlers, these code should work as that. + */ - if (sem_check_validity(sem) != 0) - return (-1); - - return (ksem_post((*sem)->semid)); -} - int -__sem_getvalue(sem_t * __restrict sem, int * __restrict sval) +_sem_post(sem_t *sem) { - int retval; - - if (sem_check_validity(sem) != 0) - return (-1); - - if ((*sem)->syssem != 0) - retval = ksem_getvalue((*sem)->semid, sval); - else { - _pthread_mutex_lock(&(*sem)->lock); - *sval = (int)(*sem)->count; - _pthread_mutex_unlock(&(*sem)->lock); - - retval = 0; - } - return (retval); + report_error(__func__); + return (-1); } Index: lib/libc/gen/Makefile.inc =================================================================== --- lib/libc/gen/Makefile.inc (revision 200821) +++ lib/libc/gen/Makefile.inc (working copy) @@ -25,7 +25,7 @@ pause.c pmadvise.c popen.c posix_spawn.c \ psignal.c pw_scan.c pwcache.c \ raise.c readdir.c readpassphrase.c rewinddir.c \ - scandir.c seed48.c seekdir.c sem.c semctl.c \ + scandir.c seed48.c seekdir.c sem.c sem_compat.c semctl.c \ setdomainname.c sethostname.c setjmperr.c setmode.c \ setproctitle.c setprogname.c siginterrupt.c siglist.c signal.c \ sigsetops.c sleep.c srand48.c statvfs.c stringlist.c strtofflags.c \ Index: lib/libc/gen/Symbol.map =================================================================== --- lib/libc/gen/Symbol.map (revision 200821) +++ lib/libc/gen/Symbol.map (working copy) @@ -236,16 +236,6 @@ seekdir; user_from_uid; group_from_gid; - sem_init; - sem_destroy; - sem_open; - sem_close; - sem_unlink; - sem_wait; - sem_trywait; - sem_timedwait; - sem_post; - sem_getvalue; setdomainname; sethostname; longjmperror; @@ -368,6 +358,16 @@ FBSD_1.2 { basename_r; getpagesizes; + sem_close; + sem_destroy; + sem_getvalue; + sem_init; + sem_open; + sem_timedwait; + sem_trywait; + sem_post; + sem_wait; + sem_unlink; }; FBSDprivate_1.0 { @@ -456,16 +456,6 @@ __pw_scan; /* Used by (at least) libutil */ __raise; _raise; - __sem_init; - __sem_destroy; - __sem_open; - __sem_close; - __sem_unlink; - __sem_wait; - __sem_trywait; - __sem_timedwait; - __sem_post; - __sem_getvalue; __sleep; _sleep; _rtld_allocate_tls; Index: lib/libc/gen/sem_compat.c =================================================================== --- lib/libc/gen/sem_compat.c (revision 200821) +++ lib/libc/gen/sem_compat.c (working copy) @@ -60,9 +60,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -70,24 +70,37 @@ #include "un-namespace.h" #include "libc_private.h" +#define SYM_FB10(sym) __CONCAT(sym, _fb10) +#define SYM_FBP10(sym) __CONCAT(sym, _fbp10) +#define WEAK_REF(sym, alias) __weak_reference(sym, alias) +#define SYM_COMPAT(sym, impl, ver) __sym_compat(sym, impl, ver) +#define SYM_DEFAULT(sym, impl, ver) __sym_default(sym, impl, ver) + +#define FB10_COMPAT(func, sym) \ + WEAK_REF(func, SYM_FB10(sym)); \ + SYM_COMPAT(sym, SYM_FB10(sym), FBSD_1.0) + +#define FB10_COMPAT_PRIVATE(func, sym) \ + WEAK_REF(func, SYM_FBP10(sym)); \ + SYM_DEFAULT(sym, SYM_FBP10(sym), FBSDprivate_1.0) + static sem_t sem_alloc(unsigned int value, semid_t semid, int system_sem); static void sem_free(sem_t sem); static LIST_HEAD(, sem) named_sems = LIST_HEAD_INITIALIZER(&named_sems); static pthread_mutex_t named_sems_mtx = PTHREAD_MUTEX_INITIALIZER; -__weak_reference(__sem_init, sem_init); -__weak_reference(__sem_destroy, sem_destroy); -__weak_reference(__sem_open, sem_open); -__weak_reference(__sem_close, sem_close); -__weak_reference(__sem_unlink, sem_unlink); -__weak_reference(__sem_wait, sem_wait); -__weak_reference(__sem_trywait, sem_trywait); -__weak_reference(__sem_timedwait, sem_timedwait); -__weak_reference(__sem_post, sem_post); -__weak_reference(__sem_getvalue, sem_getvalue); +FB10_COMPAT(_sem_init_compat, sem_init); +FB10_COMPAT(_sem_destroy_compat, sem_destroy); +FB10_COMPAT(_sem_open_compat, sem_open); +FB10_COMPAT(_sem_close_compat, sem_close); +FB10_COMPAT(_sem_unlink_compat, sem_unlink); +FB10_COMPAT(_sem_wait_compat, sem_wait); +FB10_COMPAT(_sem_trywait_compat, sem_trywait); +FB10_COMPAT(_sem_timedwait_compat, sem_timedwait); +FB10_COMPAT(_sem_post_compat, sem_post); +FB10_COMPAT(_sem_getvalue_compat, sem_getvalue); - static inline int sem_check_validity(sem_t *sem) { @@ -137,7 +150,7 @@ } int -__sem_init(sem_t *sem, int pshared, unsigned int value) +_sem_init_compat(sem_t *sem, int pshared, unsigned int value) { semid_t semid; @@ -159,7 +172,7 @@ } int -__sem_destroy(sem_t *sem) +_sem_destroy_compat(sem_t *sem) { int retval; @@ -192,7 +205,7 @@ } sem_t * -__sem_open(const char *name, int oflag, ...) +_sem_open_compat(const char *name, int oflag, ...) { sem_t *sem; sem_t s; @@ -255,7 +268,7 @@ } int -__sem_close(sem_t *sem) +_sem_close_compat(sem_t *sem) { if (sem_check_validity(sem) != 0) @@ -280,14 +293,14 @@ } int -__sem_unlink(const char *name) +_sem_unlink_compat(const char *name) { return (ksem_unlink(name)); } int -__sem_wait(sem_t *sem) +_sem_wait_compat(sem_t *sem) { if (sem_check_validity(sem) != 0) @@ -297,7 +310,7 @@ } int -__sem_trywait(sem_t *sem) +_sem_trywait_compat(sem_t *sem) { int retval; @@ -321,7 +334,7 @@ } int -__sem_timedwait(sem_t * __restrict sem, +_sem_timedwait_compat(sem_t * __restrict sem, const struct timespec * __restrict abs_timeout) { if (sem_check_validity(sem) != 0) @@ -331,7 +344,7 @@ } int -__sem_post(sem_t *sem) +_sem_post_compat(sem_t *sem) { if (sem_check_validity(sem) != 0) @@ -341,7 +354,7 @@ } int -__sem_getvalue(sem_t * __restrict sem, int * __restrict sval) +_sem_getvalue_compat(sem_t * __restrict sem, int * __restrict sval) { int retval; Property changes on: lib/libc/gen/sem_compat.c ___________________________________________________________________ Added: svn:mergeinfo Merged /user/netchild/misc/src/lib/libc/gen/sem.c:r183949 Index: lib/libthr/pthread.map =================================================================== --- lib/libthr/pthread.map (revision 200821) +++ lib/libthr/pthread.map (working copy) @@ -145,13 +145,6 @@ recvfrom; recvmsg; select; - sem_destroy; - sem_getvalue; - sem_init; - sem_post; - sem_timedwait; - sem_trywait; - sem_wait; sendmsg; sendto; sigaction; @@ -348,13 +341,16 @@ _pthread_timedjoin_np; _pthread_yield; _raise; + _sem_close; _sem_destroy; _sem_getvalue; _sem_init; + _sem_open; _sem_post; _sem_timedwait; _sem_trywait; _sem_wait; + _sem_unlink; _sigaction; _sigprocmask; _sigsuspend; @@ -410,4 +406,14 @@ FBSD_1.2 { openat; + sem_close; + sem_destroy; + sem_getvalue; + sem_init; + sem_open; + sem_post; + sem_timedwait; + sem_trywait; + sem_wait; + sem_unlink; }; Index: lib/libthr/thread/thr_sem.c =================================================================== --- lib/libthr/thread/thr_sem.c (revision 200827) +++ lib/libthr/thread/thr_sem.c (working copy) @@ -1,6 +1,5 @@ /* - * Copyright (C) 2005 David Xu . - * Copyright (C) 2000 Jason Evans . + * Copyright (C) 2009 David Xu . * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,32 +32,48 @@ #include "namespace.h" #include #include +#include #include #include #include -#include +#include #include +#include #include -#include <_semaphore.h> +#include #include "un-namespace.h" #include "thr_private.h" - -__weak_reference(_sem_init, sem_init); +__weak_reference(_sem_close, sem_close); __weak_reference(_sem_destroy, sem_destroy); __weak_reference(_sem_getvalue, sem_getvalue); +__weak_reference(_sem_init, sem_init); +__weak_reference(_sem_open, sem_open); +__weak_reference(_sem_post, sem_post); +__weak_reference(_sem_timedwait, sem_timedwait); __weak_reference(_sem_trywait, sem_trywait); +__weak_reference(_sem_unlink, sem_unlink); __weak_reference(_sem_wait, sem_wait); -__weak_reference(_sem_timedwait, sem_timedwait); -__weak_reference(_sem_post, sem_post); +#define SEM_PREFIX "/tmp/.semaphore" +#define SEM_MAGIC ((u_int32_t) 0x73656d31) +struct sem_nameinfo { + int open_count; + char *path; + sem_t *sem; + LIST_ENTRY(sem_nameinfo) next; +}; + +static struct umutex sem_llock = DEFAULT_UMUTEX; +static LIST_HEAD(,sem_nameinfo) sem_list = LIST_HEAD_INITIALIZER(sem_list); + static inline int sem_check_validity(sem_t *sem) { - if ((sem != NULL) && ((*sem)->magic == SEM_MAGIC)) + if ((sem != NULL) && (sem->magic == SEM_MAGIC)) return (0); else { errno = EINVAL; @@ -66,91 +81,184 @@ } } -static sem_t -sem_alloc(unsigned int value, semid_t semid, int system_sem) +int +_sem_init(sem_t *sem, int pshared, unsigned int value) { - sem_t sem; - if (value > SEM_VALUE_MAX) { errno = EINVAL; + return (-1); + } + + bzero(sem, sizeof(sem_t)); + sem->magic = SEM_MAGIC; + sem->data.s_count = (u_int32_t)value; + sem->data.s_has_waiters = 0; + sem->data.s_flags = pshared ? USYNC_PROCESS_SHARED : 0; + return (0); +} + +sem_t * +_sem_open(const char *name, int flags, ...) +{ + va_list ap; + struct sem_nameinfo *ni = NULL; + sem_t *sem = NULL; + int fd = -1, mode, len; + + if (name[0] != '/') { + errno = EINVAL; return (NULL); } - sem = (sem_t)malloc(sizeof(struct sem)); - if (sem == NULL) { - errno = ENOSPC; + if (flags & ~(O_CREAT|O_EXCL)) { + errno = EINVAL; return (NULL); } - bzero(sem, sizeof(*sem)); - /* - * Fortunatly count and nwaiters are adjacency, so we can - * use umtx_wait to wait on it, umtx_wait needs an address - * can be accessed as a long interger. - */ - sem->count = (u_int32_t)value; - sem->nwaiters = 0; - sem->magic = SEM_MAGIC; - sem->semid = semid; - sem->syssem = system_sem; + + len = strlen(SEM_PREFIX); + THR_LOCK_ACQUIRE(_get_curthread(), &sem_llock); + LIST_FOREACH(ni, &sem_list, next) { + if (strcmp(name, ni->path+len) == 0) { + ni->open_count++; + sem = ni->sem; + THR_LOCK_RELEASE(_get_curthread(), &sem_llock); + return (sem); + } + } + + if (flags & O_CREAT) { + va_start(ap, flags); + mode = va_arg(ap, int); + va_end(ap); + } + + len = sizeof(*ni) + strlen(name) + strlen(SEM_PREFIX) + 1; + ni = (struct sem_nameinfo *)malloc(len); + if (ni == NULL) { + errno = ENOSPC; + goto error; + } + + ni->path = (char *)(ni+1); + strcpy(ni->path, SEM_PREFIX); + strcat(ni->path, name); + fd = _open(ni->path, flags|O_RDWR, mode); + if (fd == -1) + goto error; + if (ftruncate(fd, sizeof(sem_t))) + goto error; + sem = (sem_t *)mmap(NULL, sizeof(sem_t), + PROT_READ|PROT_WRITE, + MAP_SHARED|MAP_NOSYNC, fd, 0); + if (sem == MAP_FAILED) { + sem = NULL; + if (errno == ENOMEM) + errno = ENOSPC; + goto error; + } + if (sem->magic != SEM_MAGIC) { + flock(fd, LOCK_EX); + if (sem->magic != SEM_MAGIC) { + sem->data.s_has_waiters = 0; + sem->data.s_count = 0; + sem->data.s_flags = USYNC_PROCESS_SHARED | SEM_NAMED; + wmb(); + sem->magic = SEM_MAGIC; + } + flock(fd, LOCK_UN); + } + ni->open_count = 1; + ni->sem = sem; + LIST_INSERT_HEAD(&sem_list, ni, next); + THR_LOCK_RELEASE(_get_curthread(), &sem_llock); + close(fd); return (sem); + +error: + THR_LOCK_RELEASE(_get_curthread(), &sem_llock); + if (fd != -1) + close(fd); + if (sem != NULL) + munmap(sem, sizeof(sem_t)); + free(ni); + return (NULL); } int -_sem_init(sem_t *sem, int pshared, unsigned int value) +_sem_close(sem_t *sem) { - semid_t semid; + struct sem_nameinfo *ni; - semid = (semid_t)SEM_USER; - if ((pshared != 0) && (ksem_init(&semid, value) != 0)) + if (sem_check_validity(sem) != 0) return (-1); - (*sem) = sem_alloc(value, semid, pshared); - if ((*sem) == NULL) { - if (pshared != 0) - ksem_destroy(semid); + if (!(sem->data.s_flags & SEM_NAMED)) { + errno = EINVAL; return (-1); } - return (0); + + THR_LOCK_ACQUIRE(_get_curthread(), &sem_llock); + LIST_FOREACH(ni, &sem_list, next) { + if (sem == ni->sem) { + if (--ni->open_count > 0) { + THR_LOCK_RELEASE(_get_curthread(), &sem_llock); + return (0); + } + else + break; + } + } + + if (ni) { + LIST_REMOVE(ni, next); + THR_LOCK_RELEASE(_get_curthread(), &sem_llock); + munmap(sem, sizeof(*sem)); /* the semaphore no longer exists */ + free(ni); + return (0); + } + THR_LOCK_RELEASE(_get_curthread(), &sem_llock); + return (-1); } int +_sem_unlink(const char *name) +{ + char path[PATH_MAX]; + + if (name[0] != '/') { + errno = ENOENT; + return -1; + } + + strcpy(path, SEM_PREFIX); + strlcat(path, name, sizeof(path)); + return unlink(path); +} + +int _sem_destroy(sem_t *sem) { - int retval; if (sem_check_validity(sem) != 0) return (-1); - /* - * If this is a system semaphore let the kernel track it otherwise - * make sure there are no waiters. - */ - if ((*sem)->syssem != 0) - retval = ksem_destroy((*sem)->semid); - else { - retval = 0; - (*sem)->magic = 0; + if (sem->data.s_flags & SEM_NAMED) { + errno = EINVAL; + return (-1); } - if (retval == 0) - free(*sem); - return (retval); + sem->magic = 0; + return (0); } int _sem_getvalue(sem_t * __restrict sem, int * __restrict sval) { - int retval; if (sem_check_validity(sem) != 0) return (-1); - if ((*sem)->syssem != 0) - retval = ksem_getvalue((*sem)->semid, sval); - else { - *sval = (int)(*sem)->count; - retval = 0; - } - return (retval); + *sval = (int)sem->data.s_count; + return (0); } int @@ -161,11 +269,8 @@ if (sem_check_validity(sem) != 0) return (-1); - if ((*sem)->syssem != 0) - return (ksem_trywait((*sem)->semid)); - - while ((val = (*sem)->count) > 0) { - if (atomic_cmpset_acq_int(&(*sem)->count, val, val - 1)) + while ((val = sem->data.s_count) > 0) { + if (atomic_cmpset_acq_int(&sem->data.s_count, val, val - 1)) return (0); } errno = EAGAIN; @@ -177,44 +282,14 @@ { sem_t *sem = arg; - atomic_add_int(&(*sem)->nwaiters, -1); - if ((*sem)->nwaiters && (*sem)->count) - _thr_umtx_wake(&(*sem)->count, 1, 0); + if (sem->data.s_has_waiters && sem->data.s_count) + _thr_usem_wake(&sem->data); } int _sem_wait(sem_t *sem) { - struct pthread *curthread; - int val, retval; - - if (sem_check_validity(sem) != 0) - return (-1); - - curthread = _get_curthread(); - if ((*sem)->syssem != 0) { - _thr_cancel_enter(curthread); - retval = ksem_wait((*sem)->semid); - _thr_cancel_leave(curthread); - return (retval); - } - - _pthread_testcancel(); - do { - while ((val = (*sem)->count) > 0) { - if (atomic_cmpset_acq_int(&(*sem)->count, val, val - 1)) - return (0); - } - atomic_add_int(&(*sem)->nwaiters, 1); - THR_CLEANUP_PUSH(curthread, sem_cancel_handler, sem); - _thr_cancel_enter(curthread); - retval = _thr_umtx_wait_uint(&(*sem)->count, 0, NULL, 0); - _thr_cancel_leave(curthread); - THR_CLEANUP_POP(curthread, 0); - atomic_add_int(&(*sem)->nwaiters, -1); - } while (retval == 0); - errno = retval; - return (-1); + return _sem_timedwait(sem, NULL); } int @@ -229,12 +304,6 @@ return (-1); curthread = _get_curthread(); - if ((*sem)->syssem != 0) { - _thr_cancel_enter(curthread); - retval = ksem_timedwait((*sem)->semid, abstime); - _thr_cancel_leave(curthread); - return (retval); - } /* * The timeout argument is only supposed to @@ -242,23 +311,23 @@ */ _pthread_testcancel(); do { - while ((val = (*sem)->count) > 0) { - if (atomic_cmpset_acq_int(&(*sem)->count, val, val - 1)) + while ((val = sem->data.s_count) > 0) { + if (atomic_cmpset_acq_int(&sem->data.s_count, val, val - 1)) return (0); } - if (abstime == NULL) { - errno = EINVAL; - return (-1); + if (abstime != NULL) { + if (abstime->tv_nsec >= 1000000000 || abstime->tv_nsec < 0) { + errno = EINVAL; + return (-1); + } + clock_gettime(CLOCK_REALTIME, &ts); + TIMESPEC_SUB(&ts2, abstime, &ts); } - clock_gettime(CLOCK_REALTIME, &ts); - TIMESPEC_SUB(&ts2, abstime, &ts); - atomic_add_int(&(*sem)->nwaiters, 1); THR_CLEANUP_PUSH(curthread, sem_cancel_handler, sem); _thr_cancel_enter(curthread); - retval = _thr_umtx_wait_uint((uint32_t*)&(*sem)->count, 0, &ts2, 0); + retval = _thr_usem_wait(&sem->data, abstime ? &ts2 : NULL); _thr_cancel_leave(curthread); THR_CLEANUP_POP(curthread, 0); - atomic_add_int(&(*sem)->nwaiters, -1); } while (retval == 0); errno = retval; return (-1); @@ -277,15 +346,31 @@ if (sem_check_validity(sem) != 0) return (-1); - if ((*sem)->syssem != 0) - return (ksem_post((*sem)->semid)); - - atomic_add_rel_int(&(*sem)->count, 1); - - if ((*sem)->nwaiters) { - retval = _thr_umtx_wake(&(*sem)->count, 1, 0); - if (retval != 0) + atomic_add_rel_int(&sem->data.s_count, 1); + if (sem->data.s_has_waiters) { + retval = _thr_usem_wake(&sem->data); + if (retval != 0) { + errno = retval; retval = -1; + } } return (retval); } + +void +_thr_sem_prefork() +{ + THR_LOCK_ACQUIRE(_get_curthread(), &sem_llock); +} + +void +_thr_sem_postfork() +{ + THR_LOCK_ACQUIRE(_get_curthread(), &sem_llock); +} + +void +_thr_sem_child_postfork() +{ + _thr_umutex_init(&sem_llock); +} Index: lib/libthr/thread/Makefile.inc =================================================================== --- lib/libthr/thread/Makefile.inc (revision 200821) +++ lib/libthr/thread/Makefile.inc (working copy) @@ -41,6 +41,7 @@ thr_rwlockattr.c \ thr_self.c \ thr_sem.c \ + thr_sem_compat.c \ thr_setprio.c \ thr_setschedparam.c \ thr_sig.c \ Index: lib/libthr/thread/thr_sem_compat.c =================================================================== --- lib/libthr/thread/thr_sem_compat.c (revision 200821) +++ lib/libthr/thread/thr_sem_compat.c (working copy) @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include <_semaphore.h> @@ -45,14 +44,22 @@ #include "thr_private.h" -__weak_reference(_sem_init, sem_init); -__weak_reference(_sem_destroy, sem_destroy); -__weak_reference(_sem_getvalue, sem_getvalue); -__weak_reference(_sem_trywait, sem_trywait); -__weak_reference(_sem_wait, sem_wait); -__weak_reference(_sem_timedwait, sem_timedwait); -__weak_reference(_sem_post, sem_post); +FB10_COMPAT(_sem_init_compat10, sem_init); +FB10_COMPAT(_sem_destroy_compat10, sem_destroy); +FB10_COMPAT(_sem_getvalue_compat10, sem_getvalue); +FB10_COMPAT(_sem_trywait_compat10, sem_trywait); +FB10_COMPAT(_sem_wait_compat10, sem_wait); +FB10_COMPAT(_sem_timedwait_compat10, sem_timedwait); +FB10_COMPAT(_sem_post_compat10, sem_post); +int _sem_init_compat10(sem_t *sem, int pshared, unsigned int value); +int _sem_destroy_compat10(sem_t *sem); +int _sem_getvalue_compat10(sem_t * __restrict sem, int * __restrict sval); +int _sem_trywait_compat10(sem_t *sem); +int _sem_post_compat10(sem_t *sem); +int _sem_wait_compat10(sem_t *sem); +int _sem_timedwait_compat10(sem_t * __restrict sem, + const struct timespec * __restrict abstime); static inline int sem_check_validity(sem_t *sem) @@ -96,7 +103,7 @@ } int -_sem_init(sem_t *sem, int pshared, unsigned int value) +_sem_init_compat10(sem_t *sem, int pshared, unsigned int value) { semid_t semid; @@ -114,7 +121,7 @@ } int -_sem_destroy(sem_t *sem) +_sem_destroy_compat10(sem_t *sem) { int retval; @@ -137,7 +144,7 @@ } int -_sem_getvalue(sem_t * __restrict sem, int * __restrict sval) +_sem_getvalue_compat10(sem_t * __restrict sem, int * __restrict sval) { int retval; @@ -154,7 +161,7 @@ } int -_sem_trywait(sem_t *sem) +_sem_trywait_compat10(sem_t *sem) { int val; @@ -183,7 +190,7 @@ } int -_sem_wait(sem_t *sem) +_sem_wait_compat10(sem_t *sem) { struct pthread *curthread; int val, retval; @@ -218,7 +225,7 @@ } int -_sem_timedwait(sem_t * __restrict sem, +_sem_timedwait_compat10(sem_t * __restrict sem, const struct timespec * __restrict abstime) { struct timespec ts, ts2; @@ -270,7 +277,7 @@ */ int -_sem_post(sem_t *sem) +_sem_post_compat10(sem_t *sem) { int retval = 0; Property changes on: lib/libthr/thread/thr_sem_compat.c ___________________________________________________________________ Added: svn:mergeinfo Index: lib/libthr/thread/thr_private.h =================================================================== --- lib/libthr/thread/thr_private.h (revision 200821) +++ lib/libthr/thread/thr_private.h (working copy) @@ -52,6 +52,20 @@ #include #include +#define SYM_FB10(sym) __CONCAT(sym, _fb10) +#define SYM_FBP10(sym) __CONCAT(sym, _fbp10) +#define WEAK_REF(sym, alias) __weak_reference(sym, alias) +#define SYM_COMPAT(sym, impl, ver) __sym_compat(sym, impl, ver) +#define SYM_DEFAULT(sym, impl, ver) __sym_default(sym, impl, ver) + +#define FB10_COMPAT(func, sym) \ + WEAK_REF(func, SYM_FB10(sym)); \ + SYM_COMPAT(sym, SYM_FB10(sym), FBSD_1.0) + +#define FB10_COMPAT_PRIVATE(func, sym) \ + WEAK_REF(func, SYM_FBP10(sym)); \ + SYM_DEFAULT(sym, SYM_FBP10(sym), FBSDprivate_1.0) + #ifndef __hidden #define __hidden __attribute__((visibility("hidden"))) #endif @@ -660,6 +674,9 @@ void _thread_bp_create(void); void _thread_bp_death(void); int _sched_yield(void); +void _thr_sem_prefork(void); +void _thr_sem_postfork(void); +void _thr_sem_child_postfork(void); void _pthread_cleanup_push(void (*)(void *), void *); void _pthread_cleanup_pop(int); Index: lib/libthr/thread/thr_umtx.c =================================================================== --- lib/libthr/thread/thr_umtx.c (revision 200821) +++ lib/libthr/thread/thr_umtx.c (working copy) @@ -201,6 +201,24 @@ } int +_thr_usem_wait(struct _usem *sem, const struct timespec *timeout) +{ + if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 && + timeout->tv_nsec <= 0))) + return (ETIMEDOUT); + return _umtx_op_err(sem, UMTX_OP_SEM_WAIT, 0, NULL, + __DECONST(void*, timeout)); +} + +int +_thr_usem_wake(struct _usem *sem) +{ + if (!sem->s_has_waiters) + return (0); + return _umtx_op_err(sem, UMTX_OP_SEM_WAKE, 0, NULL, NULL); +} + +int __thr_rwlock_rdlock(struct urwlock *rwlock, int flags, struct timespec *tsp) { return _umtx_op_err(rwlock, UMTX_OP_RW_RDLOCK, flags, NULL, tsp); Index: lib/libthr/thread/thr_umtx.h =================================================================== --- lib/libthr/thread/thr_umtx.h (revision 200821) +++ lib/libthr/thread/thr_umtx.h (working copy) @@ -58,6 +58,9 @@ int __thr_rwlock_wrlock(struct urwlock *rwlock, struct timespec *tsp) __hidden; int __thr_rwlock_unlock(struct urwlock *rwlock) __hidden; +int _thr_usem_wait(struct _usem *sem, const struct timespec *timeout) __hidden; +int _thr_usem_wake(struct _usem *sem) __hidden; + static inline int _thr_umutex_trylock(struct umutex *mtx, uint32_t id) { Index: ObsoleteFiles.inc =================================================================== --- ObsoleteFiles.inc (revision 200821) +++ ObsoleteFiles.inc (working copy) @@ -14,6 +14,8 @@ # The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last. # +# 20091222: removal of /sys/sys/semaphore.h. +OLD_FILES+=usr/include/sys/semaphore.h # 20091202: unify rc.firewall and rc.firewall6. OLD_FILES+=etc/rc.d/ip6fw OLD_FILES+=etc/rc.firewall6 Index: etc/rc.d/cleartmp =================================================================== --- etc/rc.d/cleartmp (revision 200821) +++ etc/rc.d/cleartmp (working copy) @@ -24,6 +24,9 @@ local x11_socket_dirs="${tmp}/.X11-unix ${tmp}/.XIM-unix \ ${tmp}/.ICE-unix ${tmp}/.font-unix" + # Named-semaphore IPC related directory to create in /tmp. + local semaphore_dir="${tmp}/.semaphore" + if checkyesno ${rcvar1}; then check_startmsgs && echo "Clearing ${tmp}." @@ -41,16 +44,30 @@ ! \( \( -name quota.user -or -name quota.group \) \ -type f -user root \) \ -prune -exec rm -rf -- {} + - elif checkyesno clear_tmp_X; then - # Remove X lock files, since they will prevent you from - # restarting X. Remove other X related directories. - check_startmsgs && echo "Clearing ${tmp} (X related)." - rm -rf ${tmp}/.X[0-9]-lock ${x11_socket_dirs} + else + if checkyesno clear_tmp_X; then + # Remove X lock files, since they will prevent you from + # restarting X. Remove other X related directories. + check_startmsgs && echo "Clearing ${tmp} (X related)." + rm -rf ${tmp}/.X[0-9]-lock ${x11_socket_dirs} + fi + + if checkyesno clear_tmp_semaphore; then + check_startmsgs &&\ + echo "Clearing ${tmp} (semaphore related)." + rm -rf ${semaphore_dir} + fi fi if checkyesno clear_tmp_X; then # Create X related directories with proper permissions. mkdir -m 1777 ${x11_socket_dirs} fi + if checkyesno ${rcvar1} || + checkyesno clear_tmp_semaphore; then + # Create named-semaphore IPC related directory with proper + # permissions. + mkdir -m 1777 ${semaphore_dir} + fi } load_rc_config $name Index: etc/mtree/BSD.root.dist =================================================================== --- etc/mtree/BSD.root.dist (revision 200821) +++ etc/mtree/BSD.root.dist (working copy) @@ -86,6 +86,8 @@ sbin .. tmp mode=01777 + .semaphore mode=01777 + .. .. usr .. Index: sys/kern/kern_umtx.c =================================================================== --- sys/kern/kern_umtx.c (revision 200821) +++ sys/kern/kern_umtx.c (working copy) @@ -2759,6 +2759,110 @@ return (error); } +static int +do_sem_wait(struct thread *td, struct _usem *sem, struct timespec *timeout) +{ + struct umtx_q *uq; + struct timeval tv; + struct timespec cts, ets, tts; + uint32_t flags, count; + int error; + + uq = td->td_umtxq; + flags = fuword32(&sem->s_flags); + error = umtx_key_get(sem, TYPE_CV, GET_SHARE(flags), &uq->uq_key); + if (error != 0) + return (error); + umtxq_lock(&uq->uq_key); + umtxq_busy(&uq->uq_key); + umtxq_insert(uq); + umtxq_unlock(&uq->uq_key); + + count = fuword32(__DEVOLATILE(uint32_t *, &sem->s_count)); + if (count != 0) { + umtxq_lock(&uq->uq_key); + umtxq_unbusy(&uq->uq_key); + umtxq_remove(uq); + umtxq_unlock(&uq->uq_key); + umtx_key_release(&uq->uq_key); + return (0); + } + + /* + * The magic thing is we should set c_has_waiters to 1 before + * releasing user mutex. + */ + suword32(__DEVOLATILE(uint32_t *, &sem->s_has_waiters), 1); + + umtxq_lock(&uq->uq_key); + umtxq_unbusy(&uq->uq_key); + umtxq_unlock(&uq->uq_key); + + umtxq_lock(&uq->uq_key); + if (timeout == NULL) { + error = umtxq_sleep(uq, "usem", 0); + } else { + getnanouptime(&ets); + timespecadd(&ets, timeout); + TIMESPEC_TO_TIMEVAL(&tv, timeout); + for (;;) { + error = umtxq_sleep(uq, "usem", tvtohz(&tv)); + if (error != ETIMEDOUT) + break; + getnanouptime(&cts); + if (timespeccmp(&cts, &ets, >=)) { + error = ETIMEDOUT; + break; + } + tts = ets; + timespecsub(&tts, &cts); + TIMESPEC_TO_TIMEVAL(&tv, &tts); + } + } + + if (error != 0) { + if ((uq->uq_flags & UQF_UMTXQ) == 0) { + if (!umtxq_signal(&uq->uq_key, 1)) + error = 0; + } + if (error == ERESTART) + error = EINTR; + } + umtxq_remove(uq); + umtxq_unlock(&uq->uq_key); + umtx_key_release(&uq->uq_key); + return (error); +} + +/* + * Signal a userland condition variable. + */ +static int +do_sem_wake(struct thread *td, struct _usem *sem) +{ + struct umtx_key key; + int error, cnt, nwake; + uint32_t flags; + + flags = fuword32(&sem->s_flags); + if ((error = umtx_key_get(sem, TYPE_CV, GET_SHARE(flags), &key)) != 0) + return (error); + umtxq_lock(&key); + umtxq_busy(&key); + cnt = umtxq_count(&key); + nwake = umtxq_signal(&key, 1); + if (cnt <= nwake) { + umtxq_unlock(&key); + error = suword32( + __DEVOLATILE(uint32_t *, &sem->s_has_waiters), 0); + umtxq_lock(&key); + } + umtxq_unbusy(&key); + umtxq_unlock(&key); + umtx_key_release(&key); + return (error); +} + int _umtx_lock(struct thread *td, struct _umtx_lock_args *uap) /* struct umtx *umtx */ @@ -3031,6 +3135,35 @@ return do_rw_unlock(td, uap->obj); } +static int +__umtx_op_sem_wait(struct thread *td, struct _umtx_op_args *uap) +{ + struct timespec *ts, timeout; + int error; + + /* Allow a null timespec (wait forever). */ + if (uap->uaddr2 == NULL) + ts = NULL; + else { + error = copyin(uap->uaddr2, &timeout, + sizeof(timeout)); + if (error != 0) + return (error); + if (timeout.tv_nsec >= 1000000000 || + timeout.tv_nsec < 0) { + return (EINVAL); + } + ts = &timeout; + } + return (do_sem_wait(td, uap->obj, ts)); +} + +static int +__umtx_op_sem_wake(struct thread *td, struct _umtx_op_args *uap) +{ + return do_sem_wake(td, uap->obj); +} + typedef int (*_umtx_op_func)(struct thread *td, struct _umtx_op_args *uap); static _umtx_op_func op_table[] = { @@ -3052,7 +3185,9 @@ __umtx_op_wait_uint_private, /* UMTX_OP_WAIT_UINT_PRIVATE */ __umtx_op_wake_private, /* UMTX_OP_WAKE_PRIVATE */ __umtx_op_wait_umutex, /* UMTX_OP_UMUTEX_WAIT */ - __umtx_op_wake_umutex /* UMTX_OP_UMUTEX_WAKE */ + __umtx_op_wake_umutex, /* UMTX_OP_UMUTEX_WAKE */ + __umtx_op_sem_wait, /* UMTX_OP_SEM_WAIT */ + __umtx_op_sem_wake /* UMTX_OP_SEM_WAKE */ }; int @@ -3274,6 +3409,27 @@ return do_wait(td, uap->obj, uap->val, ts, 1, 1); } +static int +__umtx_op_sem_wait_compat32(struct thread *td, struct _umtx_op_args *uap) +{ + struct timespec *ts, timeout; + int error; + + /* Allow a null timespec (wait forever). */ + if (uap->uaddr2 == NULL) + ts = NULL; + else { + error = copyin_timeout32(uap->uaddr2, &timeout); + if (error != 0) + return (error); + if (timeout.tv_nsec >= 1000000000 || + timeout.tv_nsec < 0) + return (EINVAL); + ts = &timeout; + } + return (do_sem_wait(td, uap->obj, ts)); +} + static _umtx_op_func op_table_compat32[] = { __umtx_op_lock_umtx_compat32, /* UMTX_OP_LOCK */ __umtx_op_unlock_umtx_compat32, /* UMTX_OP_UNLOCK */ @@ -3293,7 +3449,9 @@ __umtx_op_wait_uint_private_compat32, /* UMTX_OP_WAIT_UINT_PRIVATE */ __umtx_op_wake_private, /* UMTX_OP_WAKE_PRIVATE */ __umtx_op_wait_umutex_compat32, /* UMTX_OP_UMUTEX_WAIT */ - __umtx_op_wake_umutex /* UMTX_OP_UMUTEX_WAKE */ + __umtx_op_wake_umutex, /* UMTX_OP_UMUTEX_WAKE */ + __umtx_op_sem_wait_compat32, /* UMTX_OP_SEM_WAIT */ + __umtx_op_sem_wake /* UMTX_OP_SEM_WAKE */ }; int Index: sys/kern/uipc_sem.c =================================================================== --- sys/kern/uipc_sem.c (revision 200821) +++ sys/kern/uipc_sem.c (working copy) @@ -51,7 +51,6 @@ #include #include #include -#include #include #include #include Index: sys/sys/_semaphore.h =================================================================== --- sys/sys/_semaphore.h (revision 200821) +++ sys/sys/_semaphore.h (working copy) @@ -31,6 +31,9 @@ typedef intptr_t semid_t; struct timespec; +#define SEM_FAILED ((sem_t *)0) +#define SEM_VALUE_MAX __INT_MAX + #ifndef _KERNEL #include @@ -52,6 +55,8 @@ struct sem **backpointer; }; +typedef struct sem* sem_t; + __BEGIN_DECLS int ksem_close(semid_t id); Index: sys/sys/_umtx.h =================================================================== --- sys/sys/_umtx.h (revision 0) +++ sys/sys/_umtx.h (revision 0) @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2002, Jeffrey Roberson + * 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 unmodified, 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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: head/sys/sys/umtx.h 179970 2008-06-24 07:32:12Z davidxu $ + * + */ + +#ifndef _SYS__UMTX_H_ +#define _SYS__UMTX_H_ + +#include +#include + +struct umtx { + volatile unsigned long u_owner; /* Owner of the mutex. */ +}; + +struct umutex { + volatile __lwpid_t m_owner; /* Owner of the mutex */ + uint32_t m_flags; /* Flags of the mutex */ + uint32_t m_ceilings[2]; /* Priority protect ceiling */ + uint32_t m_spare[4]; +}; + +struct ucond { + volatile uint32_t c_has_waiters; /* Has waiters in kernel */ + uint32_t c_flags; /* Flags of the condition variable */ + uint32_t c_spare[2]; /* Spare space */ +}; + +struct urwlock { + volatile int32_t rw_state; + uint32_t rw_flags; + uint32_t rw_blocked_readers; + uint32_t rw_blocked_writers; + uint32_t rw_spare[4]; +}; + +struct _usem { + volatile uint32_t s_has_waiters; + volatile uint32_t s_count; + uint32_t s_flags; +}; + +#endif /* !_SYS__UMTX_H_ */ Index: sys/sys/umtx.h =================================================================== --- sys/sys/umtx.h (revision 200821) +++ sys/sys/umtx.h (working copy) @@ -31,19 +31,12 @@ #define _SYS_UMTX_H_ #include +#include #include -/* - * See pthread_* - */ +#define UMTX_UNOWNED 0x0 +#define UMTX_CONTESTED LONG_MIN -#define UMTX_UNOWNED 0x0 -#define UMTX_CONTESTED LONG_MIN - -struct umtx { - volatile u_long u_owner; /* Owner of the mutex. */ -}; - #define USYNC_PROCESS_SHARED 0x0001 /* Process shared sync objs */ #define UMUTEX_UNOWNED 0x0 @@ -53,27 +46,6 @@ #define UMUTEX_PRIO_INHERIT 0x0004 /* Priority inherited mutex */ #define UMUTEX_PRIO_PROTECT 0x0008 /* Priority protect mutex */ -struct umutex { - volatile __lwpid_t m_owner; /* Owner of the mutex */ - uint32_t m_flags; /* Flags of the mutex */ - uint32_t m_ceilings[2]; /* Priority protect ceiling */ - uint32_t m_spare[4]; -}; - -struct ucond { - volatile uint32_t c_has_waiters; /* Has waiters in kernel */ - uint32_t c_flags; /* Flags of the condition variable */ - uint32_t c_spare[2]; /* Spare space */ -}; - -struct urwlock { - volatile int32_t rw_state; - uint32_t rw_flags; - uint32_t rw_blocked_readers; - uint32_t rw_blocked_writers; - uint32_t rw_spare[4]; -}; - /* urwlock flags */ #define URWLOCK_PREFER_READER 0x0002 @@ -83,6 +55,9 @@ #define URWLOCK_MAX_READERS 0x1fffffffU #define URWLOCK_READER_COUNT(c) ((c) & URWLOCK_MAX_READERS) +/* _usem flags */ +#define SEM_NAMED 0x0002 + /* op code for _umtx_op */ #define UMTX_OP_LOCK 0 #define UMTX_OP_UNLOCK 1 @@ -100,10 +75,12 @@ #define UMTX_OP_RW_WRLOCK 13 #define UMTX_OP_RW_UNLOCK 14 #define UMTX_OP_WAIT_UINT_PRIVATE 15 -#define UMTX_OP_WAKE_PRIVATE 16 -#define UMTX_OP_MUTEX_WAIT 17 -#define UMTX_OP_MUTEX_WAKE 18 -#define UMTX_OP_MAX 19 +#define UMTX_OP_WAKE_PRIVATE 16 +#define UMTX_OP_MUTEX_WAIT 17 +#define UMTX_OP_MUTEX_WAKE 18 +#define UMTX_OP_SEM_WAIT 19 +#define UMTX_OP_SEM_WAKE 20 +#define UMTX_OP_MAX 21 /* flags for UMTX_OP_CV_WAIT */ #define UMTX_CHECK_UNPARKING 0x01 Index: sys/sys/semaphore.h =================================================================== --- sys/sys/semaphore.h (revision 200821) +++ sys/sys/semaphore.h (working copy) @@ -1,69 +0,0 @@ -/*- - * 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$ - */ - -/* semaphore.h: POSIX 1003.1b semaphores */ - -#ifndef _SEMAPHORE_H_ -#define _SEMAPHORE_H_ - -#include - -/* Opaque type definition. */ -struct sem; -typedef struct sem * sem_t; - -#define SEM_FAILED ((sem_t *)0) -#define SEM_VALUE_MAX __INT_MAX - -#ifndef _KERNEL -#include - -struct timespec; - -__BEGIN_DECLS -int sem_close(sem_t *); -int sem_destroy(sem_t *); -int sem_getvalue(sem_t * __restrict, int * __restrict); -int sem_init(sem_t *, int, unsigned int); -sem_t *sem_open(const char *, int, ...); -int sem_post(sem_t *); -int sem_timedwait(sem_t * __restrict, const struct timespec * __restrict); -int sem_trywait(sem_t *); -int sem_unlink(const char *); -int sem_wait(sem_t *); -__END_DECLS - -#endif - -#endif /* !_SEMAPHORE_H_ */