1efaa6588SAlfred Perlstein /* 2efaa6588SAlfred Perlstein * Copyright (c) 2002 Alfred Perlstein <alfred@FreeBSD.org> 3efaa6588SAlfred Perlstein * All rights reserved. 4efaa6588SAlfred Perlstein * 5efaa6588SAlfred Perlstein * Redistribution and use in source and binary forms, with or without 6efaa6588SAlfred Perlstein * modification, are permitted provided that the following conditions 7efaa6588SAlfred Perlstein * are met: 8efaa6588SAlfred Perlstein * 1. Redistributions of source code must retain the above copyright 9efaa6588SAlfred Perlstein * notice, this list of conditions and the following disclaimer. 10efaa6588SAlfred Perlstein * 2. Redistributions in binary form must reproduce the above copyright 11efaa6588SAlfred Perlstein * notice, this list of conditions and the following disclaimer in the 12efaa6588SAlfred Perlstein * documentation and/or other materials provided with the distribution. 13efaa6588SAlfred Perlstein * 14efaa6588SAlfred Perlstein * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15efaa6588SAlfred Perlstein * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16efaa6588SAlfred Perlstein * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17efaa6588SAlfred Perlstein * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18efaa6588SAlfred Perlstein * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19efaa6588SAlfred Perlstein * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20efaa6588SAlfred Perlstein * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21efaa6588SAlfred Perlstein * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22efaa6588SAlfred Perlstein * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23efaa6588SAlfred Perlstein * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24efaa6588SAlfred Perlstein * SUCH DAMAGE. 25efaa6588SAlfred Perlstein * 26efaa6588SAlfred Perlstein * $FreeBSD$ 27efaa6588SAlfred Perlstein */ 28efaa6588SAlfred Perlstein 29efaa6588SAlfred Perlstein #include "opt_posix.h" 30efaa6588SAlfred Perlstein 31efaa6588SAlfred Perlstein #include <sys/param.h> 32efaa6588SAlfred Perlstein #include <sys/systm.h> 33efaa6588SAlfred Perlstein #include <sys/sysproto.h> 34efaa6588SAlfred Perlstein #include <sys/kernel.h> 35efaa6588SAlfred Perlstein #include <sys/proc.h> 36efaa6588SAlfred Perlstein #include <sys/lock.h> 37efaa6588SAlfred Perlstein #include <sys/mutex.h> 38efaa6588SAlfred Perlstein #include <sys/condvar.h> 39efaa6588SAlfred Perlstein #include <sys/sem.h> 40efaa6588SAlfred Perlstein #include <sys/uio.h> 41efaa6588SAlfred Perlstein #include <sys/syscall.h> 42efaa6588SAlfred Perlstein #include <sys/stat.h> 43efaa6588SAlfred Perlstein #include <sys/sysent.h> 44efaa6588SAlfred Perlstein #include <sys/sysctl.h> 45efaa6588SAlfred Perlstein #include <sys/malloc.h> 46efaa6588SAlfred Perlstein #include <sys/jail.h> 47efaa6588SAlfred Perlstein #include <sys/fcntl.h> 48efaa6588SAlfred Perlstein 49efaa6588SAlfred Perlstein #include <posix4/posix4.h> 50efaa6588SAlfred Perlstein #include <posix4/semaphore.h> 51efaa6588SAlfred Perlstein #include <posix4/_semaphore.h> 52efaa6588SAlfred Perlstein 53efaa6588SAlfred Perlstein static struct ksem *sem_lookup_byname(const char *name); 54efaa6588SAlfred Perlstein static int sem_create(struct thread *td, const char *name, 55efaa6588SAlfred Perlstein struct ksem **ksret, mode_t mode, unsigned int value); 56efaa6588SAlfred Perlstein static void sem_free(struct ksem *ksnew); 57efaa6588SAlfred Perlstein static int sem_perm(struct proc *p, struct ksem *ks); 58efaa6588SAlfred Perlstein static void sem_enter(struct proc *p, struct ksem *ks); 59efaa6588SAlfred Perlstein static int sem_leave(struct proc *p, struct ksem *ks); 60efaa6588SAlfred Perlstein static void sem_exithook(struct proc *p); 61efaa6588SAlfred Perlstein static int sem_hasopen(struct proc *p, struct ksem *ks); 62efaa6588SAlfred Perlstein 63efaa6588SAlfred Perlstein static int kern_sem_close(struct thread *td, semid_t id); 64efaa6588SAlfred Perlstein static int kern_sem_post(struct thread *td, semid_t id); 65efaa6588SAlfred Perlstein static int kern_sem_wait(struct thread *td, semid_t id, int tryflag); 66efaa6588SAlfred Perlstein static int kern_sem_init(struct thread *td, int dir, unsigned int value, 67efaa6588SAlfred Perlstein semid_t *idp); 68efaa6588SAlfred Perlstein static int kern_sem_open(struct thread *td, int dir, const char *name, 69efaa6588SAlfred Perlstein int oflag, mode_t mode, unsigned int value, semid_t *idp); 70efaa6588SAlfred Perlstein static int kern_sem_unlink(struct thread *td, const char *name); 71efaa6588SAlfred Perlstein 72efaa6588SAlfred Perlstein #ifndef SEM_MAX 73efaa6588SAlfred Perlstein #define SEM_MAX 30 74efaa6588SAlfred Perlstein #endif 75efaa6588SAlfred Perlstein 76efaa6588SAlfred Perlstein #define SEM_MAX_NAMELEN 14 77efaa6588SAlfred Perlstein 78efaa6588SAlfred Perlstein #define SEM_TO_ID(x) ((intptr_t)(x)) 79efaa6588SAlfred Perlstein #define ID_TO_SEM(x) id_to_sem(x) 80efaa6588SAlfred Perlstein 81efaa6588SAlfred Perlstein struct kuser { 82efaa6588SAlfred Perlstein pid_t ku_pid; 83efaa6588SAlfred Perlstein LIST_ENTRY(kuser) ku_next; 84efaa6588SAlfred Perlstein }; 85efaa6588SAlfred Perlstein 86efaa6588SAlfred Perlstein struct ksem { 87efaa6588SAlfred Perlstein LIST_ENTRY(ksem) ks_entry; /* global list entry */ 88efaa6588SAlfred Perlstein int ks_onlist; /* boolean if on a list (ks_entry) */ 89efaa6588SAlfred Perlstein char *ks_name; /* if named, this is the name */ 90efaa6588SAlfred Perlstein int ks_ref; /* number of references */ 91efaa6588SAlfred Perlstein mode_t ks_mode; /* protection bits */ 92efaa6588SAlfred Perlstein uid_t ks_uid; /* creator uid */ 93efaa6588SAlfred Perlstein gid_t ks_gid; /* creator gid */ 94efaa6588SAlfred Perlstein unsigned int ks_value; /* current value */ 95efaa6588SAlfred Perlstein struct cv ks_cv; /* waiters sleep here */ 96efaa6588SAlfred Perlstein int ks_waiters; /* number of waiters */ 97efaa6588SAlfred Perlstein LIST_HEAD(, kuser) ks_users; /* pids using this sem */ 98efaa6588SAlfred Perlstein }; 99efaa6588SAlfred Perlstein 100efaa6588SAlfred Perlstein /* 101efaa6588SAlfred Perlstein * available semaphores go here, this includes sem_init and any semaphores 102efaa6588SAlfred Perlstein * created via sem_open that have not yet been unlinked. 103efaa6588SAlfred Perlstein */ 104efaa6588SAlfred Perlstein LIST_HEAD(, ksem) ksem_head = LIST_HEAD_INITIALIZER(&ksem_head); 105efaa6588SAlfred Perlstein /* 106efaa6588SAlfred Perlstein * semaphores still in use but have been sem_unlink()'d go here. 107efaa6588SAlfred Perlstein */ 108efaa6588SAlfred Perlstein LIST_HEAD(, ksem) ksem_deadhead = LIST_HEAD_INITIALIZER(&ksem_deadhead); 109efaa6588SAlfred Perlstein 110efaa6588SAlfred Perlstein static struct mtx sem_lock; 111efaa6588SAlfred Perlstein static MALLOC_DEFINE(M_SEM, "sems", "semaphore data"); 112efaa6588SAlfred Perlstein 113efaa6588SAlfred Perlstein static int nsems = 0; 114efaa6588SAlfred Perlstein SYSCTL_DECL(_p1003_1b); 115efaa6588SAlfred Perlstein SYSCTL_INT(_p1003_1b, OID_AUTO, nsems, CTLFLAG_RD, &nsems, 0, ""); 116efaa6588SAlfred Perlstein 117c814aa3fSAlfred Perlstein #ifdef SEM_DEBUG 118c814aa3fSAlfred Perlstein #define DP(x) printf x 119c814aa3fSAlfred Perlstein #else 120c814aa3fSAlfred Perlstein #define DP(x) 121c814aa3fSAlfred Perlstein #endif 122c814aa3fSAlfred Perlstein 123efaa6588SAlfred Perlstein static __inline 124efaa6588SAlfred Perlstein void 125efaa6588SAlfred Perlstein sem_ref(struct ksem *ks) 126efaa6588SAlfred Perlstein { 127efaa6588SAlfred Perlstein 128efaa6588SAlfred Perlstein ks->ks_ref++; 129c814aa3fSAlfred Perlstein DP(("sem_ref: ks = %p, ref = %d\n", ks, ks->ks_ref)); 130efaa6588SAlfred Perlstein } 131efaa6588SAlfred Perlstein 132efaa6588SAlfred Perlstein static __inline 133efaa6588SAlfred Perlstein void 134efaa6588SAlfred Perlstein sem_rel(struct ksem *ks) 135efaa6588SAlfred Perlstein { 136efaa6588SAlfred Perlstein 137c814aa3fSAlfred Perlstein DP(("sem_rel: ks = %p, ref = %d\n", ks, ks->ks_ref - 1)); 138efaa6588SAlfred Perlstein if (--ks->ks_ref == 0) 139efaa6588SAlfred Perlstein sem_free(ks); 140efaa6588SAlfred Perlstein } 141efaa6588SAlfred Perlstein 142efaa6588SAlfred Perlstein static __inline struct ksem *id_to_sem(semid_t id); 143efaa6588SAlfred Perlstein 144efaa6588SAlfred Perlstein static __inline 145efaa6588SAlfred Perlstein struct ksem * 146efaa6588SAlfred Perlstein id_to_sem(id) 147efaa6588SAlfred Perlstein semid_t id; 148efaa6588SAlfred Perlstein { 149efaa6588SAlfred Perlstein struct ksem *ks; 150efaa6588SAlfred Perlstein 151c814aa3fSAlfred Perlstein DP(("id_to_sem: id = %0x,%p\n", id, (struct ksem *)id)); 152efaa6588SAlfred Perlstein LIST_FOREACH(ks, &ksem_head, ks_entry) { 153c814aa3fSAlfred Perlstein DP(("id_to_sem: ks = %p\n", ks)); 154efaa6588SAlfred Perlstein if (ks == (struct ksem *)id) 155efaa6588SAlfred Perlstein return (ks); 156efaa6588SAlfred Perlstein } 157efaa6588SAlfred Perlstein return (NULL); 158efaa6588SAlfred Perlstein } 159efaa6588SAlfred Perlstein 160c3053131SPoul-Henning Kamp static struct ksem * 161efaa6588SAlfred Perlstein sem_lookup_byname(name) 162efaa6588SAlfred Perlstein const char *name; 163efaa6588SAlfred Perlstein { 164efaa6588SAlfred Perlstein struct ksem *ks; 165efaa6588SAlfred Perlstein 166efaa6588SAlfred Perlstein LIST_FOREACH(ks, &ksem_head, ks_entry) 167efaa6588SAlfred Perlstein if (ks->ks_name != NULL && strcmp(ks->ks_name, name) == 0) 168efaa6588SAlfred Perlstein return (ks); 169efaa6588SAlfred Perlstein return (NULL); 170efaa6588SAlfred Perlstein } 171efaa6588SAlfred Perlstein 172c3053131SPoul-Henning Kamp static int 173efaa6588SAlfred Perlstein sem_create(td, name, ksret, mode, value) 174efaa6588SAlfred Perlstein struct thread *td; 175efaa6588SAlfred Perlstein const char *name; 176efaa6588SAlfred Perlstein struct ksem **ksret; 177efaa6588SAlfred Perlstein mode_t mode; 178efaa6588SAlfred Perlstein unsigned int value; 179efaa6588SAlfred Perlstein { 180efaa6588SAlfred Perlstein struct ksem *ret; 181efaa6588SAlfred Perlstein struct proc *p; 182efaa6588SAlfred Perlstein struct ucred *uc; 183efaa6588SAlfred Perlstein size_t len; 184efaa6588SAlfred Perlstein int error; 185efaa6588SAlfred Perlstein 186c814aa3fSAlfred Perlstein DP(("sem_create\n")); 187efaa6588SAlfred Perlstein p = td->td_proc; 188efaa6588SAlfred Perlstein uc = p->p_ucred; 189efaa6588SAlfred Perlstein if (value > SEM_VALUE_MAX) 190efaa6588SAlfred Perlstein return (EINVAL); 191efaa6588SAlfred Perlstein ret = malloc(sizeof(*ret), M_SEM, M_WAITOK | M_ZERO); 192efaa6588SAlfred Perlstein if (name != NULL) { 193efaa6588SAlfred Perlstein len = strlen(name); 194efaa6588SAlfred Perlstein if (len > SEM_MAX_NAMELEN) { 195efaa6588SAlfred Perlstein free(ret, M_SEM); 196efaa6588SAlfred Perlstein return (ENAMETOOLONG); 197efaa6588SAlfred Perlstein } 198efaa6588SAlfred Perlstein /* name must start with a '/' but not contain one. */ 199efaa6588SAlfred Perlstein if (*name != '/' || len < 2 || index(name + 1, '/') != NULL) { 200efaa6588SAlfred Perlstein free(ret, M_SEM); 201efaa6588SAlfred Perlstein return (EINVAL); 202efaa6588SAlfred Perlstein } 203efaa6588SAlfred Perlstein ret->ks_name = malloc(len + 1, M_SEM, M_WAITOK); 204efaa6588SAlfred Perlstein strcpy(ret->ks_name, name); 205efaa6588SAlfred Perlstein } else { 206efaa6588SAlfred Perlstein ret->ks_name = NULL; 207efaa6588SAlfred Perlstein } 208efaa6588SAlfred Perlstein ret->ks_mode = mode; 209efaa6588SAlfred Perlstein ret->ks_value = value; 210efaa6588SAlfred Perlstein ret->ks_ref = 1; 211efaa6588SAlfred Perlstein ret->ks_waiters = 0; 212efaa6588SAlfred Perlstein ret->ks_uid = uc->cr_uid; 213efaa6588SAlfred Perlstein ret->ks_gid = uc->cr_gid; 214efaa6588SAlfred Perlstein ret->ks_onlist = 0; 215efaa6588SAlfred Perlstein cv_init(&ret->ks_cv, "sem"); 216efaa6588SAlfred Perlstein LIST_INIT(&ret->ks_users); 217efaa6588SAlfred Perlstein if (name != NULL) 218efaa6588SAlfred Perlstein sem_enter(td->td_proc, ret); 219efaa6588SAlfred Perlstein *ksret = ret; 220efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 221efaa6588SAlfred Perlstein if (nsems >= p31b_getcfg(CTL_P1003_1B_SEM_NSEMS_MAX)) { 222efaa6588SAlfred Perlstein sem_leave(td->td_proc, ret); 223efaa6588SAlfred Perlstein sem_free(ret); 224efaa6588SAlfred Perlstein error = ENFILE; 225efaa6588SAlfred Perlstein } else { 226efaa6588SAlfred Perlstein nsems++; 227efaa6588SAlfred Perlstein error = 0; 228efaa6588SAlfred Perlstein } 229efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 230efaa6588SAlfred Perlstein return (error); 231efaa6588SAlfred Perlstein } 232efaa6588SAlfred Perlstein 233efaa6588SAlfred Perlstein #ifndef _SYS_SYSPROTO_H_ 234efaa6588SAlfred Perlstein struct ksem_init_args { 235efaa6588SAlfred Perlstein unsigned int value; 236efaa6588SAlfred Perlstein semid_t *idp; 237efaa6588SAlfred Perlstein }; 238efaa6588SAlfred Perlstein int ksem_init(struct thread *td, struct ksem_init_args *uap); 239efaa6588SAlfred Perlstein #endif 240efaa6588SAlfred Perlstein int 241efaa6588SAlfred Perlstein ksem_init(td, uap) 242efaa6588SAlfred Perlstein struct thread *td; 243efaa6588SAlfred Perlstein struct ksem_init_args *uap; 244efaa6588SAlfred Perlstein { 245efaa6588SAlfred Perlstein int error; 246efaa6588SAlfred Perlstein 247efaa6588SAlfred Perlstein error = kern_sem_init(td, UIO_USERSPACE, uap->value, uap->idp); 248efaa6588SAlfred Perlstein return (error); 249efaa6588SAlfred Perlstein } 250efaa6588SAlfred Perlstein 251efaa6588SAlfred Perlstein static int 252efaa6588SAlfred Perlstein kern_sem_init(td, dir, value, idp) 253efaa6588SAlfred Perlstein struct thread *td; 254efaa6588SAlfred Perlstein int dir; 255efaa6588SAlfred Perlstein unsigned int value; 256efaa6588SAlfred Perlstein semid_t *idp; 257efaa6588SAlfred Perlstein { 258efaa6588SAlfred Perlstein struct ksem *ks; 259efaa6588SAlfred Perlstein semid_t id; 260efaa6588SAlfred Perlstein int error; 261efaa6588SAlfred Perlstein 262efaa6588SAlfred Perlstein error = sem_create(td, NULL, &ks, S_IRWXU | S_IRWXG, value); 263efaa6588SAlfred Perlstein if (error) 264efaa6588SAlfred Perlstein return (error); 265efaa6588SAlfred Perlstein id = SEM_TO_ID(ks); 266efaa6588SAlfred Perlstein if (dir == UIO_USERSPACE) { 267efaa6588SAlfred Perlstein error = copyout(&id, idp, sizeof(id)); 268efaa6588SAlfred Perlstein if (error) { 269efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 270efaa6588SAlfred Perlstein sem_rel(ks); 271efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 272efaa6588SAlfred Perlstein return (error); 273efaa6588SAlfred Perlstein } 274efaa6588SAlfred Perlstein } else { 275efaa6588SAlfred Perlstein *idp = id; 276efaa6588SAlfred Perlstein } 277efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 278efaa6588SAlfred Perlstein LIST_INSERT_HEAD(&ksem_head, ks, ks_entry); 279efaa6588SAlfred Perlstein ks->ks_onlist = 1; 280efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 281efaa6588SAlfred Perlstein return (error); 282efaa6588SAlfred Perlstein } 283efaa6588SAlfred Perlstein 284efaa6588SAlfred Perlstein #ifndef _SYS_SYSPROTO_H_ 285efaa6588SAlfred Perlstein struct ksem_open_args { 286efaa6588SAlfred Perlstein char *name; 287efaa6588SAlfred Perlstein int oflag; 288efaa6588SAlfred Perlstein mode_t mode; 289efaa6588SAlfred Perlstein unsigned int value; 290efaa6588SAlfred Perlstein semid_t *idp; 291efaa6588SAlfred Perlstein }; 292efaa6588SAlfred Perlstein int ksem_open(struct thread *td, struct ksem_open_args *uap); 293efaa6588SAlfred Perlstein #endif 294efaa6588SAlfred Perlstein int 295efaa6588SAlfred Perlstein ksem_open(td, uap) 296efaa6588SAlfred Perlstein struct thread *td; 297efaa6588SAlfred Perlstein struct ksem_open_args *uap; 298efaa6588SAlfred Perlstein { 299efaa6588SAlfred Perlstein char name[SEM_MAX_NAMELEN + 1]; 300efaa6588SAlfred Perlstein size_t done; 301efaa6588SAlfred Perlstein int error; 302efaa6588SAlfred Perlstein 303efaa6588SAlfred Perlstein error = copyinstr(uap->name, name, SEM_MAX_NAMELEN + 1, &done); 304efaa6588SAlfred Perlstein if (error) 305efaa6588SAlfred Perlstein return (error); 306c814aa3fSAlfred Perlstein DP((">>> sem_open start\n")); 307efaa6588SAlfred Perlstein error = kern_sem_open(td, UIO_USERSPACE, 308efaa6588SAlfred Perlstein name, uap->oflag, uap->mode, uap->value, uap->idp); 309c814aa3fSAlfred Perlstein DP(("<<< sem_open end\n")); 310efaa6588SAlfred Perlstein return (error); 311efaa6588SAlfred Perlstein } 312efaa6588SAlfred Perlstein 313efaa6588SAlfred Perlstein static int 314efaa6588SAlfred Perlstein kern_sem_open(td, dir, name, oflag, mode, value, idp) 315efaa6588SAlfred Perlstein struct thread *td; 316efaa6588SAlfred Perlstein int dir; 317efaa6588SAlfred Perlstein const char *name; 318efaa6588SAlfred Perlstein int oflag; 319efaa6588SAlfred Perlstein mode_t mode; 320efaa6588SAlfred Perlstein unsigned int value; 321efaa6588SAlfred Perlstein semid_t *idp; 322efaa6588SAlfred Perlstein { 323efaa6588SAlfred Perlstein struct ksem *ksnew, *ks; 324efaa6588SAlfred Perlstein int error; 325efaa6588SAlfred Perlstein semid_t id; 326efaa6588SAlfred Perlstein 327efaa6588SAlfred Perlstein ksnew = NULL; 328efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 329efaa6588SAlfred Perlstein ks = sem_lookup_byname(name); 330efaa6588SAlfred Perlstein /* 331efaa6588SAlfred Perlstein * If we found it but O_EXCL is set, error. 332efaa6588SAlfred Perlstein */ 333efaa6588SAlfred Perlstein if (ks != NULL && (oflag & O_EXCL) != 0) { 334efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 335efaa6588SAlfred Perlstein return (EEXIST); 336efaa6588SAlfred Perlstein } 337efaa6588SAlfred Perlstein /* 338efaa6588SAlfred Perlstein * If we didn't find it... 339efaa6588SAlfred Perlstein */ 340efaa6588SAlfred Perlstein if (ks == NULL) { 341efaa6588SAlfred Perlstein /* 342efaa6588SAlfred Perlstein * didn't ask for creation? error. 343efaa6588SAlfred Perlstein */ 344efaa6588SAlfred Perlstein if ((oflag & O_CREAT) == 0) { 345efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 346efaa6588SAlfred Perlstein return (ENOENT); 347efaa6588SAlfred Perlstein } 348efaa6588SAlfred Perlstein /* 349efaa6588SAlfred Perlstein * We may block during creation, so drop the lock. 350efaa6588SAlfred Perlstein */ 351efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 352efaa6588SAlfred Perlstein error = sem_create(td, name, &ksnew, mode, value); 353efaa6588SAlfred Perlstein if (error != 0) 354efaa6588SAlfred Perlstein return (error); 355efaa6588SAlfred Perlstein id = SEM_TO_ID(ksnew); 356efaa6588SAlfred Perlstein if (dir == UIO_USERSPACE) { 357c814aa3fSAlfred Perlstein DP(("about to copyout! %d to %p\n", id, idp)); 358efaa6588SAlfred Perlstein error = copyout(&id, idp, sizeof(id)); 359efaa6588SAlfred Perlstein if (error) { 360efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 361efaa6588SAlfred Perlstein sem_leave(td->td_proc, ksnew); 362efaa6588SAlfred Perlstein sem_rel(ksnew); 363efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 364efaa6588SAlfred Perlstein return (error); 365efaa6588SAlfred Perlstein } 366efaa6588SAlfred Perlstein } else { 367c814aa3fSAlfred Perlstein DP(("about to set! %d to %p\n", id, idp)); 368efaa6588SAlfred Perlstein *idp = id; 369efaa6588SAlfred Perlstein } 370efaa6588SAlfred Perlstein /* 371efaa6588SAlfred Perlstein * We need to make sure we haven't lost a race while 372efaa6588SAlfred Perlstein * allocating during creation. 373efaa6588SAlfred Perlstein */ 374efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 375efaa6588SAlfred Perlstein ks = sem_lookup_byname(name); 376efaa6588SAlfred Perlstein if (ks != NULL) { 377efaa6588SAlfred Perlstein /* we lost... */ 378efaa6588SAlfred Perlstein sem_leave(td->td_proc, ksnew); 379efaa6588SAlfred Perlstein sem_rel(ksnew); 380efaa6588SAlfred Perlstein /* we lost and we can't loose... */ 381efaa6588SAlfred Perlstein if ((oflag & O_EXCL) != 0) { 382efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 383efaa6588SAlfred Perlstein return (EEXIST); 384efaa6588SAlfred Perlstein } 385efaa6588SAlfred Perlstein } else { 386c814aa3fSAlfred Perlstein DP(("sem_create: about to add to list...\n")); 387efaa6588SAlfred Perlstein LIST_INSERT_HEAD(&ksem_head, ksnew, ks_entry); 388c814aa3fSAlfred Perlstein DP(("sem_create: setting list bit...\n")); 389efaa6588SAlfred Perlstein ksnew->ks_onlist = 1; 390c814aa3fSAlfred Perlstein DP(("sem_create: done, about to unlock...\n")); 391efaa6588SAlfred Perlstein } 392efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 393efaa6588SAlfred Perlstein } else { 394efaa6588SAlfred Perlstein /* 395efaa6588SAlfred Perlstein * if we aren't the creator, then enforce permissions. 396efaa6588SAlfred Perlstein */ 397efaa6588SAlfred Perlstein error = sem_perm(td->td_proc, ks); 398efaa6588SAlfred Perlstein if (!error) 399efaa6588SAlfred Perlstein sem_ref(ks); 400efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 401efaa6588SAlfred Perlstein if (error) 402efaa6588SAlfred Perlstein return (error); 403efaa6588SAlfred Perlstein id = SEM_TO_ID(ks); 404efaa6588SAlfred Perlstein if (dir == UIO_USERSPACE) { 405efaa6588SAlfred Perlstein error = copyout(&id, idp, sizeof(id)); 406efaa6588SAlfred Perlstein if (error) { 407efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 408efaa6588SAlfred Perlstein sem_rel(ks); 409efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 410efaa6588SAlfred Perlstein return (error); 411efaa6588SAlfred Perlstein } 412efaa6588SAlfred Perlstein } else { 413efaa6588SAlfred Perlstein *idp = id; 414efaa6588SAlfred Perlstein } 415efaa6588SAlfred Perlstein sem_enter(td->td_proc, ks); 416efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 417efaa6588SAlfred Perlstein sem_rel(ks); 418efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 419efaa6588SAlfred Perlstein } 420efaa6588SAlfred Perlstein return (error); 421efaa6588SAlfred Perlstein } 422efaa6588SAlfred Perlstein 423c3053131SPoul-Henning Kamp static int 424efaa6588SAlfred Perlstein sem_perm(p, ks) 425efaa6588SAlfred Perlstein struct proc *p; 426efaa6588SAlfred Perlstein struct ksem *ks; 427efaa6588SAlfred Perlstein { 428efaa6588SAlfred Perlstein struct ucred *uc; 429efaa6588SAlfred Perlstein 430efaa6588SAlfred Perlstein uc = p->p_ucred; 431c814aa3fSAlfred Perlstein DP(("sem_perm: uc(%d,%d) ks(%d,%d,%o)\n", 432efaa6588SAlfred Perlstein uc->cr_uid, uc->cr_gid, 433c814aa3fSAlfred Perlstein ks->ks_uid, ks->ks_gid, ks->ks_mode)); 434efaa6588SAlfred Perlstein if ((uc->cr_uid == ks->ks_uid && (ks->ks_mode & S_IWUSR) != 0) || 435efaa6588SAlfred Perlstein (uc->cr_gid == ks->ks_gid && (ks->ks_mode & S_IWGRP) != 0) || 436efaa6588SAlfred Perlstein (ks->ks_mode & S_IWOTH) != 0 || suser_cred(uc, 0) == 0) 437efaa6588SAlfred Perlstein return (0); 438efaa6588SAlfred Perlstein return (EPERM); 439efaa6588SAlfred Perlstein } 440efaa6588SAlfred Perlstein 441c3053131SPoul-Henning Kamp static void 442efaa6588SAlfred Perlstein sem_free(struct ksem *ks) 443efaa6588SAlfred Perlstein { 444efaa6588SAlfred Perlstein 445efaa6588SAlfred Perlstein nsems--; 446efaa6588SAlfred Perlstein if (ks->ks_onlist) 447efaa6588SAlfred Perlstein LIST_REMOVE(ks, ks_entry); 448efaa6588SAlfred Perlstein if (ks->ks_name != NULL) 449efaa6588SAlfred Perlstein free(ks->ks_name, M_SEM); 450efaa6588SAlfred Perlstein cv_destroy(&ks->ks_cv); 451efaa6588SAlfred Perlstein free(ks, M_SEM); 452efaa6588SAlfred Perlstein } 453efaa6588SAlfred Perlstein 454efaa6588SAlfred Perlstein static __inline struct kuser *sem_getuser(struct proc *p, struct ksem *ks); 455efaa6588SAlfred Perlstein 456efaa6588SAlfred Perlstein static __inline struct kuser * 457efaa6588SAlfred Perlstein sem_getuser(p, ks) 458efaa6588SAlfred Perlstein struct proc *p; 459efaa6588SAlfred Perlstein struct ksem *ks; 460efaa6588SAlfred Perlstein { 461efaa6588SAlfred Perlstein struct kuser *k; 462efaa6588SAlfred Perlstein 463efaa6588SAlfred Perlstein LIST_FOREACH(k, &ks->ks_users, ku_next) 464efaa6588SAlfred Perlstein if (k->ku_pid == p->p_pid) 465efaa6588SAlfred Perlstein return (k); 466efaa6588SAlfred Perlstein return (NULL); 467efaa6588SAlfred Perlstein } 468efaa6588SAlfred Perlstein 469c3053131SPoul-Henning Kamp static int 470efaa6588SAlfred Perlstein sem_hasopen(p, ks) 471efaa6588SAlfred Perlstein struct proc *p; 472efaa6588SAlfred Perlstein struct ksem *ks; 473efaa6588SAlfred Perlstein { 474efaa6588SAlfred Perlstein 475efaa6588SAlfred Perlstein return ((ks->ks_name == NULL && sem_perm(p, ks)) 476efaa6588SAlfred Perlstein || sem_getuser(p, ks) != NULL); 477efaa6588SAlfred Perlstein } 478efaa6588SAlfred Perlstein 479c3053131SPoul-Henning Kamp static int 480efaa6588SAlfred Perlstein sem_leave(p, ks) 481efaa6588SAlfred Perlstein struct proc *p; 482efaa6588SAlfred Perlstein struct ksem *ks; 483efaa6588SAlfred Perlstein { 484efaa6588SAlfred Perlstein struct kuser *k; 485efaa6588SAlfred Perlstein 486c814aa3fSAlfred Perlstein DP(("sem_leave: ks = %p\n", ks)); 487efaa6588SAlfred Perlstein k = sem_getuser(p, ks); 488c814aa3fSAlfred Perlstein DP(("sem_leave: ks = %p, k = %p\n", ks, k)); 489efaa6588SAlfred Perlstein if (k != NULL) { 490efaa6588SAlfred Perlstein LIST_REMOVE(k, ku_next); 491efaa6588SAlfred Perlstein sem_rel(ks); 492c814aa3fSAlfred Perlstein DP(("sem_leave: about to free k\n")); 493efaa6588SAlfred Perlstein free(k, M_SEM); 494c814aa3fSAlfred Perlstein DP(("sem_leave: returning\n")); 495efaa6588SAlfred Perlstein return (0); 496efaa6588SAlfred Perlstein } 497b3890a1cSAlfred Perlstein return (EINVAL); 498efaa6588SAlfred Perlstein } 499efaa6588SAlfred Perlstein 500c3053131SPoul-Henning Kamp static void 501efaa6588SAlfred Perlstein sem_enter(p, ks) 502efaa6588SAlfred Perlstein struct proc *p; 503efaa6588SAlfred Perlstein struct ksem *ks; 504efaa6588SAlfred Perlstein { 505efaa6588SAlfred Perlstein struct kuser *ku, *k; 506efaa6588SAlfred Perlstein 507efaa6588SAlfred Perlstein ku = malloc(sizeof(*ku), M_SEM, M_WAITOK); 508efaa6588SAlfred Perlstein ku->ku_pid = p->p_pid; 509efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 510efaa6588SAlfred Perlstein k = sem_getuser(p, ks); 511efaa6588SAlfred Perlstein if (k != NULL) { 512efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 513efaa6588SAlfred Perlstein free(ku, M_TEMP); 514efaa6588SAlfred Perlstein return; 515efaa6588SAlfred Perlstein } 516efaa6588SAlfred Perlstein LIST_INSERT_HEAD(&ks->ks_users, ku, ku_next); 517efaa6588SAlfred Perlstein sem_ref(ks); 518efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 519efaa6588SAlfred Perlstein } 520efaa6588SAlfred Perlstein 521efaa6588SAlfred Perlstein #ifndef _SYS_SYSPROTO_H_ 522efaa6588SAlfred Perlstein struct ksem_unlink_args { 523efaa6588SAlfred Perlstein char *name; 524efaa6588SAlfred Perlstein }; 525efaa6588SAlfred Perlstein int ksem_unlink(struct thread *td, struct ksem_unlink_args *uap); 526efaa6588SAlfred Perlstein #endif 527efaa6588SAlfred Perlstein 528efaa6588SAlfred Perlstein int 529efaa6588SAlfred Perlstein ksem_unlink(td, uap) 530efaa6588SAlfred Perlstein struct thread *td; 531efaa6588SAlfred Perlstein struct ksem_unlink_args *uap; 532efaa6588SAlfred Perlstein { 533efaa6588SAlfred Perlstein char name[SEM_MAX_NAMELEN + 1]; 534efaa6588SAlfred Perlstein size_t done; 535efaa6588SAlfred Perlstein int error; 536efaa6588SAlfred Perlstein 537efaa6588SAlfred Perlstein error = copyinstr(uap->name, name, SEM_MAX_NAMELEN + 1, &done); 538efaa6588SAlfred Perlstein return (error ? error : 539efaa6588SAlfred Perlstein kern_sem_unlink(td, name)); 540efaa6588SAlfred Perlstein } 541efaa6588SAlfred Perlstein 542efaa6588SAlfred Perlstein static int 543efaa6588SAlfred Perlstein kern_sem_unlink(td, name) 544efaa6588SAlfred Perlstein struct thread *td; 545efaa6588SAlfred Perlstein const char *name; 546efaa6588SAlfred Perlstein { 547efaa6588SAlfred Perlstein struct ksem *ks; 548efaa6588SAlfred Perlstein int error; 549efaa6588SAlfred Perlstein 550efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 551efaa6588SAlfred Perlstein ks = sem_lookup_byname(name); 552efaa6588SAlfred Perlstein if (ks == NULL) 553efaa6588SAlfred Perlstein error = ENOENT; 554efaa6588SAlfred Perlstein else 555efaa6588SAlfred Perlstein error = sem_perm(td->td_proc, ks); 556c814aa3fSAlfred Perlstein DP(("sem_unlink: '%s' ks = %p, error = %d\n", name, ks, error)); 557efaa6588SAlfred Perlstein if (error == 0) { 558efaa6588SAlfred Perlstein LIST_REMOVE(ks, ks_entry); 559efaa6588SAlfred Perlstein LIST_INSERT_HEAD(&ksem_deadhead, ks, ks_entry); 560efaa6588SAlfred Perlstein sem_rel(ks); 561efaa6588SAlfred Perlstein } 562efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 563efaa6588SAlfred Perlstein return (error); 564efaa6588SAlfred Perlstein } 565efaa6588SAlfred Perlstein 566efaa6588SAlfred Perlstein #ifndef _SYS_SYSPROTO_H_ 567efaa6588SAlfred Perlstein struct ksem_close_args { 568efaa6588SAlfred Perlstein semid_t id; 569efaa6588SAlfred Perlstein }; 570efaa6588SAlfred Perlstein int ksem_close(struct thread *td, struct ksem_close_args *uap); 571efaa6588SAlfred Perlstein #endif 572efaa6588SAlfred Perlstein 573efaa6588SAlfred Perlstein int 574efaa6588SAlfred Perlstein ksem_close(struct thread *td, struct ksem_close_args *uap) 575efaa6588SAlfred Perlstein { 576efaa6588SAlfred Perlstein 577efaa6588SAlfred Perlstein return (kern_sem_close(td, uap->id)); 578efaa6588SAlfred Perlstein } 579efaa6588SAlfred Perlstein 580c3053131SPoul-Henning Kamp static int 581efaa6588SAlfred Perlstein kern_sem_close(td, id) 582efaa6588SAlfred Perlstein struct thread *td; 583efaa6588SAlfred Perlstein semid_t id; 584efaa6588SAlfred Perlstein { 585efaa6588SAlfred Perlstein struct ksem *ks; 586efaa6588SAlfred Perlstein int error; 587efaa6588SAlfred Perlstein 588efaa6588SAlfred Perlstein error = EINVAL; 589efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 590efaa6588SAlfred Perlstein ks = ID_TO_SEM(id); 591efaa6588SAlfred Perlstein /* this is not a valid operation for unnamed sems */ 592efaa6588SAlfred Perlstein if (ks != NULL && ks->ks_name != NULL) 593b3890a1cSAlfred Perlstein error = sem_leave(td->td_proc, ks); 594efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 595b3890a1cSAlfred Perlstein return (error); 596efaa6588SAlfred Perlstein } 597efaa6588SAlfred Perlstein 598efaa6588SAlfred Perlstein #ifndef _SYS_SYSPROTO_H_ 599efaa6588SAlfred Perlstein struct ksem_post_args { 600efaa6588SAlfred Perlstein semid_t id; 601efaa6588SAlfred Perlstein }; 602efaa6588SAlfred Perlstein int ksem_post(struct thread *td, struct ksem_post_args *uap); 603efaa6588SAlfred Perlstein #endif 604efaa6588SAlfred Perlstein int 605efaa6588SAlfred Perlstein ksem_post(td, uap) 606efaa6588SAlfred Perlstein struct thread *td; 607efaa6588SAlfred Perlstein struct ksem_post_args *uap; 608efaa6588SAlfred Perlstein { 609efaa6588SAlfred Perlstein 610efaa6588SAlfred Perlstein return (kern_sem_post(td, uap->id)); 611efaa6588SAlfred Perlstein } 612efaa6588SAlfred Perlstein 613c3053131SPoul-Henning Kamp static int 614efaa6588SAlfred Perlstein kern_sem_post(td, id) 615efaa6588SAlfred Perlstein struct thread *td; 616efaa6588SAlfred Perlstein semid_t id; 617efaa6588SAlfred Perlstein { 618efaa6588SAlfred Perlstein struct ksem *ks; 619efaa6588SAlfred Perlstein int error; 620efaa6588SAlfred Perlstein 621efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 622efaa6588SAlfred Perlstein ks = ID_TO_SEM(id); 623efaa6588SAlfred Perlstein if (ks == NULL || !sem_hasopen(td->td_proc, ks)) { 624efaa6588SAlfred Perlstein error = EINVAL; 625efaa6588SAlfred Perlstein goto err; 626efaa6588SAlfred Perlstein } 627efaa6588SAlfred Perlstein if (ks->ks_value == SEM_VALUE_MAX) { 628efaa6588SAlfred Perlstein error = EOVERFLOW; 629efaa6588SAlfred Perlstein goto err; 630efaa6588SAlfred Perlstein } 631efaa6588SAlfred Perlstein ++ks->ks_value; 632efaa6588SAlfred Perlstein if (ks->ks_waiters > 0) 633efaa6588SAlfred Perlstein cv_signal(&ks->ks_cv); 634efaa6588SAlfred Perlstein error = 0; 635efaa6588SAlfred Perlstein err: 636efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 637efaa6588SAlfred Perlstein return (error); 638efaa6588SAlfred Perlstein } 639efaa6588SAlfred Perlstein 640efaa6588SAlfred Perlstein #ifndef _SYS_SYSPROTO_H_ 641efaa6588SAlfred Perlstein struct ksem_wait_args { 642efaa6588SAlfred Perlstein semid_t id; 643efaa6588SAlfred Perlstein }; 644efaa6588SAlfred Perlstein int ksem_wait(struct thread *td, struct ksem_wait_args *uap); 645efaa6588SAlfred Perlstein #endif 646efaa6588SAlfred Perlstein 647efaa6588SAlfred Perlstein int 648efaa6588SAlfred Perlstein ksem_wait(td, uap) 649efaa6588SAlfred Perlstein struct thread *td; 650efaa6588SAlfred Perlstein struct ksem_wait_args *uap; 651efaa6588SAlfred Perlstein { 652efaa6588SAlfred Perlstein 653efaa6588SAlfred Perlstein return (kern_sem_wait(td, uap->id, 0)); 654efaa6588SAlfred Perlstein } 655efaa6588SAlfred Perlstein 656efaa6588SAlfred Perlstein #ifndef _SYS_SYSPROTO_H_ 657efaa6588SAlfred Perlstein struct ksem_trywait_args { 658efaa6588SAlfred Perlstein semid_t id; 659efaa6588SAlfred Perlstein }; 660efaa6588SAlfred Perlstein int ksem_trywait(struct thread *td, struct ksem_trywait_args *uap); 661efaa6588SAlfred Perlstein #endif 662efaa6588SAlfred Perlstein int 663efaa6588SAlfred Perlstein ksem_trywait(td, uap) 664efaa6588SAlfred Perlstein struct thread *td; 665efaa6588SAlfred Perlstein struct ksem_trywait_args *uap; 666efaa6588SAlfred Perlstein { 667efaa6588SAlfred Perlstein 668efaa6588SAlfred Perlstein return (kern_sem_wait(td, uap->id, 1)); 669efaa6588SAlfred Perlstein } 670efaa6588SAlfred Perlstein 671c3053131SPoul-Henning Kamp static int 672efaa6588SAlfred Perlstein kern_sem_wait(td, id, tryflag) 673efaa6588SAlfred Perlstein struct thread *td; 674efaa6588SAlfred Perlstein semid_t id; 675efaa6588SAlfred Perlstein int tryflag; 676efaa6588SAlfred Perlstein { 677efaa6588SAlfred Perlstein struct ksem *ks; 678efaa6588SAlfred Perlstein int error; 679efaa6588SAlfred Perlstein 680c814aa3fSAlfred Perlstein DP((">>> kern_sem_wait entered!\n")); 681efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 682efaa6588SAlfred Perlstein ks = ID_TO_SEM(id); 683efaa6588SAlfred Perlstein if (ks == NULL) { 684c814aa3fSAlfred Perlstein DP(("kern_sem_wait ks == NULL\n")); 685efaa6588SAlfred Perlstein error = EINVAL; 686efaa6588SAlfred Perlstein goto err; 687efaa6588SAlfred Perlstein } 688efaa6588SAlfred Perlstein sem_ref(ks); 689efaa6588SAlfred Perlstein if (!sem_hasopen(td->td_proc, ks)) { 690c814aa3fSAlfred Perlstein DP(("kern_sem_wait hasopen failed\n")); 691efaa6588SAlfred Perlstein error = EINVAL; 692efaa6588SAlfred Perlstein goto err; 693efaa6588SAlfred Perlstein } 694c814aa3fSAlfred Perlstein DP(("kern_sem_wait value = %d, tryflag %d\n", ks->ks_value, tryflag)); 695efaa6588SAlfred Perlstein if (ks->ks_value == 0) { 696efaa6588SAlfred Perlstein ks->ks_waiters++; 697efaa6588SAlfred Perlstein error = tryflag ? EAGAIN : cv_wait_sig(&ks->ks_cv, &sem_lock); 698efaa6588SAlfred Perlstein ks->ks_waiters--; 699efaa6588SAlfred Perlstein if (error) 700efaa6588SAlfred Perlstein goto err; 701efaa6588SAlfred Perlstein } 702efaa6588SAlfred Perlstein ks->ks_value--; 703efaa6588SAlfred Perlstein error = 0; 704efaa6588SAlfred Perlstein err: 705efaa6588SAlfred Perlstein if (ks != NULL) 706efaa6588SAlfred Perlstein sem_rel(ks); 707efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 708c814aa3fSAlfred Perlstein DP(("<<< kern_sem_wait leaving, error = %d\n", error)); 709efaa6588SAlfred Perlstein return (error); 710efaa6588SAlfred Perlstein } 711efaa6588SAlfred Perlstein 712efaa6588SAlfred Perlstein #ifndef _SYS_SYSPROTO_H_ 713efaa6588SAlfred Perlstein struct ksem_getvalue_args { 714efaa6588SAlfred Perlstein semid_t id; 715efaa6588SAlfred Perlstein int *val; 716efaa6588SAlfred Perlstein }; 717efaa6588SAlfred Perlstein int ksem_getvalue(struct thread *td, struct ksem_getvalue_args *uap); 718efaa6588SAlfred Perlstein #endif 719efaa6588SAlfred Perlstein int 720efaa6588SAlfred Perlstein ksem_getvalue(td, uap) 721efaa6588SAlfred Perlstein struct thread *td; 722efaa6588SAlfred Perlstein struct ksem_getvalue_args *uap; 723efaa6588SAlfred Perlstein { 724efaa6588SAlfred Perlstein struct ksem *ks; 725efaa6588SAlfred Perlstein int error, val; 726efaa6588SAlfred Perlstein 727efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 728efaa6588SAlfred Perlstein ks = ID_TO_SEM(uap->id); 729efaa6588SAlfred Perlstein if (ks == NULL || !sem_hasopen(td->td_proc, ks)) { 730efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 731efaa6588SAlfred Perlstein return (EINVAL); 732efaa6588SAlfred Perlstein } 733efaa6588SAlfred Perlstein val = ks->ks_value; 734efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 735efaa6588SAlfred Perlstein error = copyout(&val, uap->val, sizeof(val)); 736efaa6588SAlfred Perlstein return (error); 737efaa6588SAlfred Perlstein } 738efaa6588SAlfred Perlstein 739efaa6588SAlfred Perlstein #ifndef _SYS_SYSPROTO_H_ 740efaa6588SAlfred Perlstein struct ksem_destroy_args { 741efaa6588SAlfred Perlstein semid_t id; 742efaa6588SAlfred Perlstein }; 743efaa6588SAlfred Perlstein int ksem_destroy(struct thread *td, struct ksem_destroy_args *uap); 744efaa6588SAlfred Perlstein #endif 745efaa6588SAlfred Perlstein int 746efaa6588SAlfred Perlstein ksem_destroy(td, uap) 747efaa6588SAlfred Perlstein struct thread *td; 748efaa6588SAlfred Perlstein struct ksem_destroy_args *uap; 749efaa6588SAlfred Perlstein { 750efaa6588SAlfred Perlstein struct ksem *ks; 751efaa6588SAlfred Perlstein int error; 752efaa6588SAlfred Perlstein 753efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 754efaa6588SAlfred Perlstein ks = ID_TO_SEM(uap->id); 755efaa6588SAlfred Perlstein if (ks == NULL || !sem_hasopen(td->td_proc, ks) || 756efaa6588SAlfred Perlstein ks->ks_name != NULL) { 757efaa6588SAlfred Perlstein error = EINVAL; 758efaa6588SAlfred Perlstein goto err; 759efaa6588SAlfred Perlstein } 760efaa6588SAlfred Perlstein if (ks->ks_waiters != 0) { 761efaa6588SAlfred Perlstein error = EBUSY; 762efaa6588SAlfred Perlstein goto err; 763efaa6588SAlfred Perlstein } 764efaa6588SAlfred Perlstein sem_rel(ks); 765efaa6588SAlfred Perlstein error = 0; 766efaa6588SAlfred Perlstein err: 767efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 768efaa6588SAlfred Perlstein return (error); 769efaa6588SAlfred Perlstein } 770efaa6588SAlfred Perlstein 771c3053131SPoul-Henning Kamp static void 772efaa6588SAlfred Perlstein sem_exithook(p) 773efaa6588SAlfred Perlstein struct proc *p; 774efaa6588SAlfred Perlstein { 775efaa6588SAlfred Perlstein struct ksem *ks, *ksnext; 776efaa6588SAlfred Perlstein 777efaa6588SAlfred Perlstein mtx_lock(&sem_lock); 778efaa6588SAlfred Perlstein ks = LIST_FIRST(&ksem_head); 779efaa6588SAlfred Perlstein while (ks != NULL) { 780efaa6588SAlfred Perlstein ksnext = LIST_NEXT(ks, ks_entry); 781efaa6588SAlfred Perlstein sem_leave(p, ks); 782efaa6588SAlfred Perlstein ks = ksnext; 783efaa6588SAlfred Perlstein } 784efaa6588SAlfred Perlstein ks = LIST_FIRST(&ksem_deadhead); 785efaa6588SAlfred Perlstein while (ks != NULL) { 786efaa6588SAlfred Perlstein ksnext = LIST_NEXT(ks, ks_entry); 787efaa6588SAlfred Perlstein sem_leave(p, ks); 788efaa6588SAlfred Perlstein ks = ksnext; 789efaa6588SAlfred Perlstein } 790efaa6588SAlfred Perlstein mtx_unlock(&sem_lock); 791efaa6588SAlfred Perlstein } 792efaa6588SAlfred Perlstein 793efaa6588SAlfred Perlstein static int 794efaa6588SAlfred Perlstein sem_modload(struct module *module, int cmd, void *arg) 795efaa6588SAlfred Perlstein { 796efaa6588SAlfred Perlstein int error = 0; 797efaa6588SAlfred Perlstein 798efaa6588SAlfred Perlstein switch (cmd) { 799efaa6588SAlfred Perlstein case MOD_LOAD: 800efaa6588SAlfred Perlstein mtx_init(&sem_lock, "sem", "semaphore", MTX_DEF); 801efaa6588SAlfred Perlstein p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, SEM_MAX); 802efaa6588SAlfred Perlstein p31b_setcfg(CTL_P1003_1B_SEM_VALUE_MAX, SEM_VALUE_MAX); 803efaa6588SAlfred Perlstein at_exec(&sem_exithook); 804efaa6588SAlfred Perlstein at_exit(&sem_exithook); 805efaa6588SAlfred Perlstein break; 806efaa6588SAlfred Perlstein case MOD_UNLOAD: 807efaa6588SAlfred Perlstein if (nsems != 0) { 808efaa6588SAlfred Perlstein error = EOPNOTSUPP; 809efaa6588SAlfred Perlstein break; 810efaa6588SAlfred Perlstein } 811efaa6588SAlfred Perlstein rm_at_exit(&sem_exithook); 812efaa6588SAlfred Perlstein rm_at_exec(&sem_exithook); 813efaa6588SAlfred Perlstein mtx_destroy(&sem_lock); 814efaa6588SAlfred Perlstein break; 815efaa6588SAlfred Perlstein case MOD_SHUTDOWN: 816efaa6588SAlfred Perlstein break; 817efaa6588SAlfred Perlstein default: 818efaa6588SAlfred Perlstein error = EINVAL; 819efaa6588SAlfred Perlstein break; 820efaa6588SAlfred Perlstein } 821efaa6588SAlfred Perlstein return (error); 822efaa6588SAlfred Perlstein } 823efaa6588SAlfred Perlstein 824efaa6588SAlfred Perlstein static moduledata_t sem_mod = { 825efaa6588SAlfred Perlstein "sem", 826efaa6588SAlfred Perlstein &sem_modload, 827efaa6588SAlfred Perlstein NULL 828efaa6588SAlfred Perlstein }; 829efaa6588SAlfred Perlstein 830efaa6588SAlfred Perlstein SYSCALL_MODULE_HELPER(ksem_init); 831efaa6588SAlfred Perlstein SYSCALL_MODULE_HELPER(ksem_open); 832efaa6588SAlfred Perlstein SYSCALL_MODULE_HELPER(ksem_unlink); 833efaa6588SAlfred Perlstein SYSCALL_MODULE_HELPER(ksem_close); 834efaa6588SAlfred Perlstein SYSCALL_MODULE_HELPER(ksem_post); 835efaa6588SAlfred Perlstein SYSCALL_MODULE_HELPER(ksem_wait); 836efaa6588SAlfred Perlstein SYSCALL_MODULE_HELPER(ksem_trywait); 837efaa6588SAlfred Perlstein SYSCALL_MODULE_HELPER(ksem_getvalue); 838efaa6588SAlfred Perlstein SYSCALL_MODULE_HELPER(ksem_destroy); 839efaa6588SAlfred Perlstein 840efaa6588SAlfred Perlstein DECLARE_MODULE(sem, sem_mod, SI_SUB_SYSV_SEM, SI_ORDER_FIRST); 841efaa6588SAlfred Perlstein MODULE_VERSION(sem, 1); 842