1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #pragma weak _semctl = semctl 33 #pragma weak _semctl64 = semctl64 34 #pragma weak _semget = semget 35 #pragma weak _semop = semop 36 #pragma weak _semids = semids 37 #pragma weak _semtimedop = semtimedop 38 39 #include "lint.h" 40 #include <sys/types.h> 41 #include <sys/ipc.h> 42 #include <sys/ipc_impl.h> 43 #include <sys/sem.h> 44 #include <sys/sem_impl.h> 45 #include <sys/syscall.h> 46 #include <stdarg.h> 47 #include <errno.h> 48 49 union semun { 50 int val; 51 struct semid_ds *buf; 52 struct semid_ds64 *buf64; 53 ushort_t *array; 54 }; 55 56 /* 57 * The kernel implementation of semsys expects an argument containing the 58 * value of the semun argument, but the Sparc compiler passes a pointer 59 * to it, since it is a union. So, we convert here and pass the value, 60 * but to keep the naive user from being penalized for the counterintuitive 61 * behaviour of the Sparc compiler, we ignore the union if it will not be 62 * used by the system call (to protect the caller from SIGSEGVs, e.g. 63 * semctl(semid, semnum, cmd, NULL); which would otherwise always result 64 * in a segmentation violation). We do this partly for consistency, since 65 * the ICL port did it. This all works just fine for the Intel compiler, 66 * which actually does pass the union by value. 67 */ 68 int 69 semctl(int semid, int semnum, int cmd, ...) 70 { 71 uintptr_t arg; 72 va_list ap; 73 74 switch (cmd) { 75 case SETVAL: 76 va_start(ap, cmd); 77 arg = (uintptr_t)va_arg(ap, union semun).val; 78 va_end(ap); 79 break; 80 case GETALL: 81 case SETALL: 82 va_start(ap, cmd); 83 arg = (uintptr_t)va_arg(ap, union semun).array; 84 va_end(ap); 85 break; 86 case IPC_STAT: 87 case IPC_SET: 88 va_start(ap, cmd); 89 arg = (uintptr_t)va_arg(ap, union semun).buf; 90 va_end(ap); 91 break; 92 case IPC_SET64: 93 case IPC_STAT64: 94 (void) __set_errno(EINVAL); 95 return (-1); 96 default: 97 arg = 0; 98 break; 99 } 100 101 return (syscall(SYS_semsys, SEMCTL, semid, semnum, cmd, arg)); 102 } 103 104 int 105 semctl64(int semid, int semnum, int cmd, ...) 106 { 107 struct semid_ds64 *buf; 108 va_list ap; 109 110 if (cmd != IPC_SET64 && cmd != IPC_STAT64) { 111 (void) __set_errno(EINVAL); 112 return (-1); 113 } 114 115 va_start(ap, cmd); 116 buf = va_arg(ap, union semun).buf64; 117 va_end(ap); 118 119 return (syscall(SYS_semsys, SEMCTL, semid, semnum, cmd, buf)); 120 } 121 122 int 123 semget(key_t key, int nsems, int semflg) 124 { 125 return (syscall(SYS_semsys, SEMGET, key, nsems, semflg)); 126 } 127 128 int 129 semop(int semid, struct sembuf *sops, size_t nsops) 130 { 131 return (syscall(SYS_semsys, SEMOP, semid, sops, nsops)); 132 } 133 134 int 135 semids(int *buf, uint_t nids, uint_t *pnids) 136 { 137 return (syscall(SYS_semsys, SEMIDS, buf, nids, pnids)); 138 } 139 140 int 141 semtimedop(int semid, struct sembuf *sops, size_t nsops, 142 const timespec_t *timeout) 143 { 144 return (syscall(SYS_semsys, SEMTIMEDOP, semid, sops, nsops, 145 timeout)); 146 } 147