Home | History | Annotate | Download | only in sys
      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