Added SYSV ipcs.
Obtained from: NetBSD and FreeBSD-1.1.5
This commit is contained in:
parent
a78a18e9b9
commit
3d903220e4
@ -68,6 +68,11 @@ kern/subr_xxx.c standard
|
||||
kern/sys_generic.c standard
|
||||
kern/sys_process.c standard
|
||||
kern/sys_socket.c standard
|
||||
kern/sysv_ipc.c optional sysvshm
|
||||
kern/sysv_ipc.c optional sysvmsg
|
||||
kern/sysv_ipc.c optional sysvsem
|
||||
kern/sysv_msg.c optional sysvmsg
|
||||
kern/sysv_sem.c optional sysvsem
|
||||
kern/sysv_shm.c optional sysvshm
|
||||
kern/tty.c standard
|
||||
kern/tty_compat.c standard
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)param.c 8.2 (Berkeley) 1/21/94
|
||||
* $Id$
|
||||
* $Id: param.c,v 1.3 1994/08/02 07:38:30 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -56,6 +56,12 @@
|
||||
#include <machine/vmparam.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
#ifdef SYSVSEM
|
||||
#include "sys/sem.h"
|
||||
#endif
|
||||
#ifdef SYSVMSG
|
||||
#include "sys/msg.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* System parameter formulae.
|
||||
@ -105,6 +111,43 @@ struct shminfo shminfo = {
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Values in support of System V compatible semaphores.
|
||||
*/
|
||||
|
||||
#ifdef SYSVSEM
|
||||
|
||||
struct seminfo seminfo = {
|
||||
SEMMAP, /* # of entries in semaphore map */
|
||||
SEMMNI, /* # of semaphore identifiers */
|
||||
SEMMNS, /* # of semaphores in system */
|
||||
SEMMNU, /* # of undo structures in system */
|
||||
SEMMSL, /* max # of semaphores per id */
|
||||
SEMOPM, /* max # of operations per semop call */
|
||||
SEMUME, /* max # of undo entries per process */
|
||||
SEMUSZ, /* size in bytes of undo structure */
|
||||
SEMVMX, /* semaphore maximum value */
|
||||
SEMAEM /* adjust on exit max value */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Values in support of System V compatible messages.
|
||||
*/
|
||||
|
||||
#ifdef SYSVMSG
|
||||
|
||||
struct msginfo msginfo = {
|
||||
MSGMAX, /* max chars in a message */
|
||||
MSGMNI, /* # of message queue identifiers */
|
||||
MSGMNB, /* max chars in a queue */
|
||||
MSGTQL, /* max messages in system */
|
||||
MSGSSZ, /* size of a message segment */
|
||||
/* (must be small power of 2 greater than 4) */
|
||||
MSGSEG /* number of message segments */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These are initialized at bootstrap time
|
||||
* to values dependent on memory size
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)init_main.c 8.9 (Berkeley) 1/21/94
|
||||
* $Id: init_main.c,v 1.8 1994/09/01 05:12:37 davidg Exp $
|
||||
* $Id: init_main.c,v 1.9 1994/09/01 11:20:11 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -239,6 +239,21 @@ main(framep)
|
||||
/* Initialize clists. */
|
||||
clist_init();
|
||||
|
||||
#ifdef SYSVSHM
|
||||
/* Initialize System V style shared memory. */
|
||||
shminit();
|
||||
#endif
|
||||
|
||||
#ifdef SYSVSEM
|
||||
/* Initialize System V style semaphores. */
|
||||
seminit();
|
||||
#endif
|
||||
|
||||
#ifdef SYSVMSG
|
||||
/* Initialize System V style message queues. */
|
||||
msginit();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Attach pseudo-devices.
|
||||
*/
|
||||
|
@ -2,7 +2,7 @@
|
||||
* System call switch table.
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* created from $Id: syscalls.master,v 1.6 1994/09/01 05:12:42 davidg Exp $
|
||||
* created from $Id: syscalls.master,v 1.7 1994/09/13 00:48:19 wollman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -142,6 +142,14 @@ int setdomainname();
|
||||
int uname();
|
||||
int sysarch();
|
||||
int rtprio();
|
||||
#ifdef SYSVSEM
|
||||
int semsys();
|
||||
#else
|
||||
#endif
|
||||
#ifdef SYSVMSG
|
||||
int msgsys();
|
||||
#else
|
||||
#endif
|
||||
#ifdef SYSVSHM
|
||||
int shmsys();
|
||||
#else
|
||||
@ -237,6 +245,12 @@ int ogetdirentries();
|
||||
#ifdef NFS
|
||||
#else
|
||||
#endif
|
||||
#ifdef SYSVSEM
|
||||
#else
|
||||
#endif
|
||||
#ifdef SYSVMSG
|
||||
#else
|
||||
#endif
|
||||
#ifdef SYSVSHM
|
||||
#else
|
||||
#endif
|
||||
@ -441,8 +455,16 @@ struct sysent sysent[] = {
|
||||
{ 2, rtprio }, /* 166 = rtprio */
|
||||
{ 0, nosys }, /* 167 = nosys */
|
||||
{ 0, nosys }, /* 168 = nosys */
|
||||
#ifdef SYSVSEM
|
||||
{ 5, semsys }, /* 169 = semsys */
|
||||
#else
|
||||
{ 0, nosys }, /* 169 = nosys */
|
||||
#endif
|
||||
#ifdef SYSVMSG
|
||||
{ 6, msgsys }, /* 170 = msgsys */
|
||||
#else
|
||||
{ 0, nosys }, /* 170 = nosys */
|
||||
#endif
|
||||
#ifdef SYSVSHM
|
||||
{ 4, shmsys }, /* 171 = shmsys */
|
||||
#else
|
||||
|
@ -28,7 +28,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: kern_exec.c,v 1.4 1994/08/18 22:34:59 wollman Exp $
|
||||
* $Id: kern_exec.c,v 1.5 1994/08/24 10:53:53 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -338,6 +338,8 @@ exec_new_vmspace(iparams)
|
||||
iparams->vmspace_destroyed = 1;
|
||||
|
||||
/* Blow away entire process VM */
|
||||
if (vmspace->vm_shm)
|
||||
shmexit(iparams->proc);
|
||||
vm_deallocate(&vmspace->vm_map, 0, USRSTACK);
|
||||
|
||||
/* Allocate a new stack */
|
||||
|
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)param.c 8.2 (Berkeley) 1/21/94
|
||||
* $Id$
|
||||
* $Id: param.c,v 1.3 1994/08/02 07:38:30 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -56,6 +56,12 @@
|
||||
#include <machine/vmparam.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
#ifdef SYSVSEM
|
||||
#include "sys/sem.h"
|
||||
#endif
|
||||
#ifdef SYSVMSG
|
||||
#include "sys/msg.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* System parameter formulae.
|
||||
@ -105,6 +111,43 @@ struct shminfo shminfo = {
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Values in support of System V compatible semaphores.
|
||||
*/
|
||||
|
||||
#ifdef SYSVSEM
|
||||
|
||||
struct seminfo seminfo = {
|
||||
SEMMAP, /* # of entries in semaphore map */
|
||||
SEMMNI, /* # of semaphore identifiers */
|
||||
SEMMNS, /* # of semaphores in system */
|
||||
SEMMNU, /* # of undo structures in system */
|
||||
SEMMSL, /* max # of semaphores per id */
|
||||
SEMOPM, /* max # of operations per semop call */
|
||||
SEMUME, /* max # of undo entries per process */
|
||||
SEMUSZ, /* size in bytes of undo structure */
|
||||
SEMVMX, /* semaphore maximum value */
|
||||
SEMAEM /* adjust on exit max value */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Values in support of System V compatible messages.
|
||||
*/
|
||||
|
||||
#ifdef SYSVMSG
|
||||
|
||||
struct msginfo msginfo = {
|
||||
MSGMAX, /* max chars in a message */
|
||||
MSGMNI, /* # of message queue identifiers */
|
||||
MSGMNB, /* max chars in a queue */
|
||||
MSGTQL, /* max messages in system */
|
||||
MSGSSZ, /* size of a message segment */
|
||||
/* (must be small power of 2 greater than 4) */
|
||||
MSGSEG /* number of message segments */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These are initialized at bootstrap time
|
||||
* to values dependent on memory size
|
||||
|
@ -2,7 +2,7 @@
|
||||
* System call names.
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* created from $Id: syscalls.master,v 1.6 1994/09/01 05:12:42 davidg Exp $
|
||||
* created from $Id: syscalls.master,v 1.7 1994/09/13 00:48:19 wollman Exp $
|
||||
*/
|
||||
|
||||
char *syscallnames[] = {
|
||||
@ -195,8 +195,16 @@ char *syscallnames[] = {
|
||||
"rtprio", /* 166 = rtprio */
|
||||
"#167", /* 167 = nosys */
|
||||
"#168", /* 168 = nosys */
|
||||
#ifdef SYSVSEM
|
||||
"semsys", /* 169 = semsys */
|
||||
#else
|
||||
"#169", /* 169 = nosys */
|
||||
#endif
|
||||
#ifdef SYSVMSG
|
||||
"msgsys", /* 170 = msgsys */
|
||||
#else
|
||||
"#170", /* 170 = nosys */
|
||||
#endif
|
||||
#ifdef SYSVSHM
|
||||
"shmsys", /* 171 = shmsys */
|
||||
#else
|
||||
|
@ -1,4 +1,4 @@
|
||||
$Id: syscalls.master,v 1.6 1994/09/01 05:12:42 davidg Exp $
|
||||
$Id: syscalls.master,v 1.7 1994/09/13 00:48:19 wollman Exp $
|
||||
; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94
|
||||
;
|
||||
; System call name/number master file.
|
||||
@ -222,8 +222,16 @@
|
||||
166 STD 2 BSD rtprio
|
||||
167 UNIMPL 0 NOHIDE nosys
|
||||
168 UNIMPL 0 NOHIDE nosys
|
||||
#ifdef SYSVSEM
|
||||
169 STD 5 BSD semsys
|
||||
#else
|
||||
169 UNIMPL 0 NOHIDE nosys
|
||||
#endif
|
||||
#ifdef SYSVMSG
|
||||
170 STD 6 BSD msgsys
|
||||
#else
|
||||
170 UNIMPL 0 NOHIDE nosys
|
||||
#endif
|
||||
#ifdef SYSVSHM
|
||||
171 STD 4 BSD shmsys
|
||||
#else
|
||||
|
69
sys/kern/sysv_ipc.c
Normal file
69
sys/kern/sysv_ipc.c
Normal file
@ -0,0 +1,69 @@
|
||||
/* $Id$ */
|
||||
/* $NetBSD: sysv_ipc.c,v 1.7 1994/06/29 06:33:11 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
|
||||
* 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 Herb Peyerl.
|
||||
* 4. The name of Herb Peyerl may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
/*
|
||||
* Check for ipc permission
|
||||
*/
|
||||
|
||||
int
|
||||
ipcperm(cred, perm, mode)
|
||||
struct ucred *cred;
|
||||
struct ipc_perm *perm;
|
||||
int mode;
|
||||
{
|
||||
|
||||
if (cred->cr_uid == 0)
|
||||
return (0);
|
||||
|
||||
/* Check for user match. */
|
||||
if (cred->cr_uid != perm->cuid && cred->cr_uid != perm->uid) {
|
||||
if (mode & IPC_M)
|
||||
return (EPERM);
|
||||
/* Check for group match. */
|
||||
mode >>= 3;
|
||||
if (!groupmember(perm->gid, cred) &&
|
||||
!groupmember(perm->cgid, cred))
|
||||
/* Check for `other' match. */
|
||||
mode >>= 3;
|
||||
}
|
||||
|
||||
if (mode & IPC_M)
|
||||
return (0);
|
||||
return ((mode & perm->mode) == mode ? 0 : EACCES);
|
||||
}
|
1006
sys/kern/sysv_msg.c
Normal file
1006
sys/kern/sysv_msg.c
Normal file
File diff suppressed because it is too large
Load Diff
939
sys/kern/sysv_sem.c
Normal file
939
sys/kern/sysv_sem.c
Normal file
@ -0,0 +1,939 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Implementation of SVID semaphores
|
||||
*
|
||||
* Author: Daniel Boulet
|
||||
*
|
||||
* This software is provided ``AS IS'' without any warranties of any kind.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sem.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
static int semctl(), semget(), semop(), semconfig();
|
||||
int (*semcalls[])() = { semctl, semget, semop, semconfig };
|
||||
int semtot = 0;
|
||||
|
||||
static struct proc *semlock_holder = NULL;
|
||||
|
||||
int
|
||||
seminit()
|
||||
{
|
||||
register int i;
|
||||
vm_offset_t whocares1, whocares2;
|
||||
|
||||
if (sema == NULL)
|
||||
panic("sema is NULL");
|
||||
if (semu == NULL)
|
||||
panic("semu is NULL");
|
||||
|
||||
for (i = 0; i < seminfo.semmni; i++) {
|
||||
sema[i].sem_base = 0;
|
||||
sema[i].sem_perm.mode = 0;
|
||||
}
|
||||
for (i = 0; i < seminfo.semmnu; i++) {
|
||||
register struct sem_undo *suptr = SEMU(i);
|
||||
suptr->un_proc = NULL;
|
||||
}
|
||||
semu_list = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Entry point for all SEM calls
|
||||
*/
|
||||
|
||||
struct semsys_args {
|
||||
u_int which;
|
||||
};
|
||||
|
||||
int
|
||||
semsys(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct semsys_args *uap;
|
||||
int *retval;
|
||||
{
|
||||
|
||||
while (semlock_holder != NULL && semlock_holder != p)
|
||||
sleep((caddr_t)&semlock_holder, (PZERO - 4));
|
||||
|
||||
if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0]))
|
||||
return (EINVAL);
|
||||
return ((*semcalls[uap->which])(p, &uap[1], retval));
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock or unlock the entire semaphore facility.
|
||||
*
|
||||
* This will probably eventually evolve into a general purpose semaphore
|
||||
* facility status enquiry mechanism (I don't like the "read /dev/kmem"
|
||||
* approach currently taken by ipcs and the amount of info that we want
|
||||
* to be able to extract for ipcs is probably beyond what the capability
|
||||
* of the getkerninfo facility.
|
||||
*
|
||||
* At the time that the current version of semconfig was written, ipcs is
|
||||
* the only user of the semconfig facility. It uses it to ensure that the
|
||||
* semaphore facility data structures remain static while it fishes around
|
||||
* in /dev/kmem.
|
||||
*/
|
||||
|
||||
struct semconfig_args {
|
||||
semconfig_ctl_t flag;
|
||||
};
|
||||
|
||||
int
|
||||
semconfig(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct semconfig_args *uap;
|
||||
int *retval;
|
||||
{
|
||||
int eval = 0;
|
||||
|
||||
switch (uap->flag) {
|
||||
case SEM_CONFIG_FREEZE:
|
||||
semlock_holder = p;
|
||||
break;
|
||||
|
||||
case SEM_CONFIG_THAW:
|
||||
semlock_holder = NULL;
|
||||
wakeup((caddr_t)&semlock_holder);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("semconfig: unknown flag parameter value (%d) - ignored\n",
|
||||
uap->flag);
|
||||
eval = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
*retval = 0;
|
||||
return(eval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new sem_undo structure for a process
|
||||
* (returns ptr to structure or NULL if no more room)
|
||||
*/
|
||||
|
||||
struct sem_undo *
|
||||
semu_alloc(p)
|
||||
struct proc *p;
|
||||
{
|
||||
register int i;
|
||||
register struct sem_undo *suptr;
|
||||
register struct sem_undo **supptr;
|
||||
int attempt;
|
||||
|
||||
/*
|
||||
* Try twice to allocate something.
|
||||
* (we'll purge any empty structures after the first pass so
|
||||
* two passes are always enough)
|
||||
*/
|
||||
|
||||
for (attempt = 0; attempt < 2; attempt++) {
|
||||
/*
|
||||
* Look for a free structure.
|
||||
* Fill it in and return it if we find one.
|
||||
*/
|
||||
|
||||
for (i = 0; i < seminfo.semmnu; i++) {
|
||||
suptr = SEMU(i);
|
||||
if (suptr->un_proc == NULL) {
|
||||
suptr->un_next = semu_list;
|
||||
semu_list = suptr;
|
||||
suptr->un_cnt = 0;
|
||||
suptr->un_proc = p;
|
||||
return(suptr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We didn't find a free one, if this is the first attempt
|
||||
* then try to free some structures.
|
||||
*/
|
||||
|
||||
if (attempt == 0) {
|
||||
/* All the structures are in use - try to free some */
|
||||
int did_something = 0;
|
||||
|
||||
supptr = &semu_list;
|
||||
while ((suptr = *supptr) != NULL) {
|
||||
if (suptr->un_cnt == 0) {
|
||||
suptr->un_proc = NULL;
|
||||
*supptr = suptr->un_next;
|
||||
did_something = 1;
|
||||
} else
|
||||
supptr = &(suptr->un_next);
|
||||
}
|
||||
|
||||
/* If we didn't free anything then just give-up */
|
||||
if (!did_something)
|
||||
return(NULL);
|
||||
} else {
|
||||
/*
|
||||
* The second pass failed even though we freed
|
||||
* something after the first pass!
|
||||
* This is IMPOSSIBLE!
|
||||
*/
|
||||
panic("semu_alloc - second attempt failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust a particular entry for a particular proc
|
||||
*/
|
||||
|
||||
int
|
||||
semundo_adjust(p, supptr, semid, semnum, adjval)
|
||||
register struct proc *p;
|
||||
struct sem_undo **supptr;
|
||||
int semid, semnum;
|
||||
int adjval;
|
||||
{
|
||||
register struct sem_undo *suptr;
|
||||
register struct undo *sunptr;
|
||||
int i;
|
||||
|
||||
/* Look for and remember the sem_undo if the caller doesn't provide
|
||||
it */
|
||||
|
||||
suptr = *supptr;
|
||||
if (suptr == NULL) {
|
||||
for (suptr = semu_list; suptr != NULL;
|
||||
suptr = suptr->un_next) {
|
||||
if (suptr->un_proc == p) {
|
||||
*supptr = suptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (suptr == NULL) {
|
||||
if (adjval == 0)
|
||||
return(0);
|
||||
suptr = semu_alloc(p);
|
||||
if (suptr == NULL)
|
||||
return(ENOSPC);
|
||||
*supptr = suptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the requested entry and adjust it (delete if adjval becomes
|
||||
* 0).
|
||||
*/
|
||||
sunptr = &suptr->un_ent[0];
|
||||
for (i = 0; i < suptr->un_cnt; i++, sunptr++) {
|
||||
if (sunptr->un_id != semid || sunptr->un_num != semnum)
|
||||
continue;
|
||||
if (adjval == 0)
|
||||
sunptr->un_adjval = 0;
|
||||
else
|
||||
sunptr->un_adjval += adjval;
|
||||
if (sunptr->un_adjval == 0) {
|
||||
suptr->un_cnt--;
|
||||
if (i < suptr->un_cnt)
|
||||
suptr->un_ent[i] =
|
||||
suptr->un_ent[suptr->un_cnt];
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Didn't find the right entry - create it */
|
||||
if (adjval == 0)
|
||||
return(0);
|
||||
if (suptr->un_cnt != SEMUME) {
|
||||
sunptr = &suptr->un_ent[suptr->un_cnt];
|
||||
suptr->un_cnt++;
|
||||
sunptr->un_adjval = adjval;
|
||||
sunptr->un_id = semid; sunptr->un_num = semnum;
|
||||
} else
|
||||
return(EINVAL);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
semundo_clear(semid, semnum)
|
||||
int semid, semnum;
|
||||
{
|
||||
register struct sem_undo *suptr;
|
||||
|
||||
for (suptr = semu_list; suptr != NULL; suptr = suptr->un_next) {
|
||||
register struct undo *sunptr = &suptr->un_ent[0];
|
||||
register int i = 0;
|
||||
|
||||
while (i < suptr->un_cnt) {
|
||||
if (sunptr->un_id == semid) {
|
||||
if (semnum == -1 || sunptr->un_num == semnum) {
|
||||
suptr->un_cnt--;
|
||||
if (i < suptr->un_cnt) {
|
||||
suptr->un_ent[i] =
|
||||
suptr->un_ent[suptr->un_cnt];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (semnum != -1)
|
||||
break;
|
||||
}
|
||||
i++, sunptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct semctl_args {
|
||||
int semid;
|
||||
int semnum;
|
||||
int cmd;
|
||||
union semun *arg;
|
||||
};
|
||||
|
||||
int
|
||||
semctl(p, uap, retval)
|
||||
struct proc *p;
|
||||
register struct semctl_args *uap;
|
||||
int *retval;
|
||||
{
|
||||
int semid = uap->semid;
|
||||
int semnum = uap->semnum;
|
||||
int cmd = uap->cmd;
|
||||
union semun *arg = uap->arg;
|
||||
union semun real_arg;
|
||||
struct ucred *cred = p->p_ucred;
|
||||
int i, rval, eval;
|
||||
struct semid_ds sbuf;
|
||||
register struct semid_ds *semaptr;
|
||||
|
||||
#ifdef SEM_DEBUG
|
||||
printf("call to semctl(%d, %d, %d, 0x%x)\n", semid, semnum, cmd, arg);
|
||||
#endif
|
||||
|
||||
semid = IPCID_TO_IX(semid);
|
||||
if (semid < 0 || semid >= seminfo.semmsl)
|
||||
return(EINVAL);
|
||||
|
||||
semaptr = &sema[semid];
|
||||
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
|
||||
semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid))
|
||||
return(EINVAL);
|
||||
|
||||
eval = 0;
|
||||
rval = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case IPC_RMID:
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_M)))
|
||||
return(eval);
|
||||
semaptr->sem_perm.cuid = cred->cr_uid;
|
||||
semaptr->sem_perm.uid = cred->cr_uid;
|
||||
semtot -= semaptr->sem_nsems;
|
||||
for (i = semaptr->sem_base - sem; i < semtot; i++)
|
||||
sem[i] = sem[i + semaptr->sem_nsems];
|
||||
for (i = 0; i < seminfo.semmni; i++) {
|
||||
if ((sema[i].sem_perm.mode & SEM_ALLOC) &&
|
||||
sema[i].sem_base > semaptr->sem_base)
|
||||
sema[i].sem_base -= semaptr->sem_nsems;
|
||||
}
|
||||
semaptr->sem_perm.mode = 0;
|
||||
semundo_clear(semid, -1);
|
||||
wakeup((caddr_t)semaptr);
|
||||
break;
|
||||
|
||||
case IPC_SET:
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_M)))
|
||||
return(eval);
|
||||
if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
return(eval);
|
||||
if ((eval = copyin(real_arg.buf, (caddr_t)&sbuf,
|
||||
sizeof(sbuf))) != 0)
|
||||
return(eval);
|
||||
semaptr->sem_perm.uid = sbuf.sem_perm.uid;
|
||||
semaptr->sem_perm.gid = sbuf.sem_perm.gid;
|
||||
semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) |
|
||||
(sbuf.sem_perm.mode & 0777);
|
||||
semaptr->sem_ctime = time.tv_sec;
|
||||
break;
|
||||
|
||||
case IPC_STAT:
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
|
||||
return(eval);
|
||||
if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
return(eval);
|
||||
eval = copyout((caddr_t)semaptr, real_arg.buf,
|
||||
sizeof(struct semid_ds));
|
||||
break;
|
||||
|
||||
case GETNCNT:
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
|
||||
return(eval);
|
||||
if (semnum < 0 || semnum >= semaptr->sem_nsems)
|
||||
return(EINVAL);
|
||||
rval = semaptr->sem_base[semnum].semncnt;
|
||||
break;
|
||||
|
||||
case GETPID:
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
|
||||
return(eval);
|
||||
if (semnum < 0 || semnum >= semaptr->sem_nsems)
|
||||
return(EINVAL);
|
||||
rval = semaptr->sem_base[semnum].sempid;
|
||||
break;
|
||||
|
||||
case GETVAL:
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
|
||||
return(eval);
|
||||
if (semnum < 0 || semnum >= semaptr->sem_nsems)
|
||||
return(EINVAL);
|
||||
rval = semaptr->sem_base[semnum].semval;
|
||||
break;
|
||||
|
||||
case GETALL:
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
|
||||
return(eval);
|
||||
if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
return(eval);
|
||||
for (i = 0; i < semaptr->sem_nsems; i++) {
|
||||
eval = copyout((caddr_t)&semaptr->sem_base[i].semval,
|
||||
&real_arg.array[i], sizeof(real_arg.array[0]));
|
||||
if (eval != 0)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case GETZCNT:
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
|
||||
return(eval);
|
||||
if (semnum < 0 || semnum >= semaptr->sem_nsems)
|
||||
return(EINVAL);
|
||||
rval = semaptr->sem_base[semnum].semzcnt;
|
||||
break;
|
||||
|
||||
case SETVAL:
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_W)))
|
||||
return(eval);
|
||||
if (semnum < 0 || semnum >= semaptr->sem_nsems)
|
||||
return(EINVAL);
|
||||
if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
return(eval);
|
||||
semaptr->sem_base[semnum].semval = real_arg.val;
|
||||
semundo_clear(semid, semnum);
|
||||
wakeup((caddr_t)semaptr);
|
||||
break;
|
||||
|
||||
case SETALL:
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_W)))
|
||||
return(eval);
|
||||
if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
return(eval);
|
||||
for (i = 0; i < semaptr->sem_nsems; i++) {
|
||||
eval = copyin(&real_arg.array[i],
|
||||
(caddr_t)&semaptr->sem_base[i].semval,
|
||||
sizeof(real_arg.array[0]));
|
||||
if (eval != 0)
|
||||
break;
|
||||
}
|
||||
semundo_clear(semid, -1);
|
||||
wakeup((caddr_t)semaptr);
|
||||
break;
|
||||
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
if (eval == 0)
|
||||
*retval = rval;
|
||||
return(eval);
|
||||
}
|
||||
|
||||
struct semget_args {
|
||||
key_t key;
|
||||
int nsems;
|
||||
int semflg;
|
||||
};
|
||||
|
||||
int
|
||||
semget(p, uap, retval)
|
||||
struct proc *p;
|
||||
register struct semget_args *uap;
|
||||
int *retval;
|
||||
{
|
||||
int semid, eval;
|
||||
int key = uap->key;
|
||||
int nsems = uap->nsems;
|
||||
int semflg = uap->semflg;
|
||||
struct ucred *cred = p->p_ucred;
|
||||
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semget(0x%x, %d, 0%o)\n", key, nsems, semflg);
|
||||
#endif
|
||||
|
||||
if (key != IPC_PRIVATE) {
|
||||
for (semid = 0; semid < seminfo.semmni; semid++) {
|
||||
if ((sema[semid].sem_perm.mode & SEM_ALLOC) &&
|
||||
sema[semid].sem_perm.key == key)
|
||||
break;
|
||||
}
|
||||
if (semid < seminfo.semmni) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("found public key\n");
|
||||
#endif
|
||||
if ((eval = ipcperm(cred, &sema[semid].sem_perm,
|
||||
semflg & 0700)))
|
||||
return(eval);
|
||||
if (nsems > 0 && sema[semid].sem_nsems < nsems) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("too small\n");
|
||||
#endif
|
||||
return(EINVAL);
|
||||
}
|
||||
if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("not exclusive\n");
|
||||
#endif
|
||||
return(EEXIST);
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SEM_DEBUG
|
||||
printf("need to allocate the semid_ds\n");
|
||||
#endif
|
||||
if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) {
|
||||
if (nsems <= 0 || nsems > seminfo.semmsl) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("nsems out of range (0<%d<=%d)\n", nsems,
|
||||
seminfo.semmsl);
|
||||
#endif
|
||||
return(EINVAL);
|
||||
}
|
||||
if (nsems > seminfo.semmns - semtot) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("not enough semaphores left (need %d, got %d)\n",
|
||||
nsems, seminfo.semmns - semtot);
|
||||
#endif
|
||||
return(ENOSPC);
|
||||
}
|
||||
for (semid = 0; semid < seminfo.semmni; semid++) {
|
||||
if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0)
|
||||
break;
|
||||
}
|
||||
if (semid == seminfo.semmni) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("no more semid_ds's available\n");
|
||||
#endif
|
||||
return(ENOSPC);
|
||||
}
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semid %d is available\n", semid);
|
||||
#endif
|
||||
sema[semid].sem_perm.key = key;
|
||||
sema[semid].sem_perm.cuid = cred->cr_uid;
|
||||
sema[semid].sem_perm.uid = cred->cr_uid;
|
||||
sema[semid].sem_perm.cgid = cred->cr_gid;
|
||||
sema[semid].sem_perm.gid = cred->cr_gid;
|
||||
sema[semid].sem_perm.mode = (semflg & 0777) | SEM_ALLOC;
|
||||
sema[semid].sem_perm.seq =
|
||||
(sema[semid].sem_perm.seq + 1) & 0x7fff;
|
||||
sema[semid].sem_nsems = nsems;
|
||||
sema[semid].sem_otime = 0;
|
||||
sema[semid].sem_ctime = time.tv_sec;
|
||||
sema[semid].sem_base = &sem[semtot];
|
||||
semtot += nsems;
|
||||
bzero(sema[semid].sem_base,
|
||||
sizeof(sema[semid].sem_base[0])*nsems);
|
||||
#ifdef SEM_DEBUG
|
||||
printf("sembase = 0x%x, next = 0x%x\n", sema[semid].sem_base,
|
||||
&sem[semtot]);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("didn't find it and wasn't asked to create it\n");
|
||||
#endif
|
||||
return(ENOENT);
|
||||
}
|
||||
|
||||
found:
|
||||
*retval = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm);
|
||||
return(0);
|
||||
}
|
||||
|
||||
struct semop_args {
|
||||
int semid;
|
||||
struct sembuf *sops;
|
||||
int nsops;
|
||||
};
|
||||
|
||||
int
|
||||
semop(p, uap, retval)
|
||||
struct proc *p;
|
||||
register struct semop_args *uap;
|
||||
int *retval;
|
||||
{
|
||||
int semid = uap->semid;
|
||||
int nsops = uap->nsops;
|
||||
struct sembuf sops[MAX_SOPS];
|
||||
register struct semid_ds *semaptr;
|
||||
register struct sembuf *sopptr;
|
||||
register struct sem *semptr;
|
||||
struct sem_undo *suptr = NULL;
|
||||
struct ucred *cred = p->p_ucred;
|
||||
int i, j, eval;
|
||||
int all_ok, do_wakeup, do_undos;
|
||||
|
||||
#ifdef SEM_DEBUG
|
||||
printf("call to semop(%d, 0x%x, %d)\n", semid, sops, nsops);
|
||||
#endif
|
||||
|
||||
semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
|
||||
|
||||
if (semid < 0 || semid >= seminfo.semmsl)
|
||||
return(EINVAL);
|
||||
|
||||
semaptr = &sema[semid];
|
||||
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0)
|
||||
return(EINVAL);
|
||||
if (semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid))
|
||||
return(EINVAL);
|
||||
|
||||
if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_W))) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("eval = %d from ipaccess\n", eval);
|
||||
#endif
|
||||
return(eval);
|
||||
}
|
||||
|
||||
if (nsops > MAX_SOPS) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("too many sops (max=%d, nsops=%d)\n", MAX_SOPS, nsops);
|
||||
#endif
|
||||
return(E2BIG);
|
||||
}
|
||||
|
||||
if ((eval = copyin(uap->sops, &sops, nsops * sizeof(sops[0]))) != 0) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("eval = %d from copyin(%08x, %08x, %d)\n", eval,
|
||||
uap->sops, &sops, nsops * sizeof(sops[0]));
|
||||
#endif
|
||||
return(eval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop trying to satisfy the vector of requests.
|
||||
* If we reach a point where we must wait, any requests already
|
||||
* performed are rolled back and we go to sleep until some other
|
||||
* process wakes us up. At this point, we start all over again.
|
||||
*
|
||||
* This ensures that from the perspective of other tasks, a set
|
||||
* of requests is atomic (never partially satisfied).
|
||||
*/
|
||||
do_undos = 0;
|
||||
|
||||
for (;;) {
|
||||
do_wakeup = 0;
|
||||
|
||||
for (i = 0; i < nsops; i++) {
|
||||
sopptr = &sops[i];
|
||||
|
||||
if (sopptr->sem_num >= semaptr->sem_nsems)
|
||||
return(EFBIG);
|
||||
|
||||
semptr = &semaptr->sem_base[sopptr->sem_num];
|
||||
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semop: semaptr=%x, sem_base=%x, semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
|
||||
semaptr, semaptr->sem_base, semptr,
|
||||
sopptr->sem_num, semptr->semval, sopptr->sem_op,
|
||||
(sopptr->sem_flg & IPC_NOWAIT) ? "nowait" : "wait");
|
||||
#endif
|
||||
|
||||
if (sopptr->sem_op < 0) {
|
||||
if (semptr->semval + sopptr->sem_op < 0) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semop: can't do it now\n");
|
||||
#endif
|
||||
break;
|
||||
} else {
|
||||
semptr->semval += sopptr->sem_op;
|
||||
if (semptr->semval == 0 &&
|
||||
semptr->semzcnt > 0)
|
||||
do_wakeup = 1;
|
||||
}
|
||||
if (sopptr->sem_flg & SEM_UNDO)
|
||||
do_undos = 1;
|
||||
} else if (sopptr->sem_op == 0) {
|
||||
if (semptr->semval > 0) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semop: not zero now\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (semptr->semncnt > 0)
|
||||
do_wakeup = 1;
|
||||
semptr->semval += sopptr->sem_op;
|
||||
if (sopptr->sem_flg & SEM_UNDO)
|
||||
do_undos = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Did we get through the entire vector?
|
||||
*/
|
||||
if (i >= nsops)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* No ... rollback anything that we've already done
|
||||
*/
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semop: rollback 0 through %d\n", i-1);
|
||||
#endif
|
||||
for (j = 0; j < i; j++)
|
||||
semaptr->sem_base[sops[j].sem_num].semval -=
|
||||
sops[j].sem_op;
|
||||
|
||||
/*
|
||||
* If the request that we couldn't satisfy has the
|
||||
* NOWAIT flag set then return with EAGAIN.
|
||||
*/
|
||||
if (sopptr->sem_flg & IPC_NOWAIT)
|
||||
return(EAGAIN);
|
||||
|
||||
if (sopptr->sem_op == 0)
|
||||
semptr->semzcnt++;
|
||||
else
|
||||
semptr->semncnt++;
|
||||
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semop: good night!\n");
|
||||
#endif
|
||||
eval = tsleep((caddr_t)semaptr, (PZERO - 4) | PCATCH,
|
||||
"semwait", 0);
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semop: good morning (eval=%d)!\n", eval);
|
||||
#endif
|
||||
|
||||
suptr = NULL; /* sem_undo may have been reallocated */
|
||||
|
||||
if (eval != 0)
|
||||
return(EINTR);
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semop: good morning!\n");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make sure that the semaphore still exists
|
||||
*/
|
||||
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
|
||||
semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
|
||||
/* The man page says to return EIDRM. */
|
||||
/* Unfortunately, BSD doesn't define that code! */
|
||||
#ifdef EIDRM
|
||||
return(EIDRM);
|
||||
#else
|
||||
return(EINVAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The semaphore is still alive. Readjust the count of
|
||||
* waiting processes.
|
||||
*/
|
||||
if (sopptr->sem_op == 0)
|
||||
semptr->semzcnt--;
|
||||
else
|
||||
semptr->semncnt--;
|
||||
}
|
||||
|
||||
done:
|
||||
/*
|
||||
* Process any SEM_UNDO requests.
|
||||
*/
|
||||
if (do_undos) {
|
||||
for (i = 0; i < nsops; i++) {
|
||||
/*
|
||||
* We only need to deal with SEM_UNDO's for non-zero
|
||||
* op's.
|
||||
*/
|
||||
int adjval;
|
||||
|
||||
if ((sops[i].sem_flg & SEM_UNDO) == 0)
|
||||
continue;
|
||||
adjval = sops[i].sem_op;
|
||||
if (adjval == 0)
|
||||
continue;
|
||||
eval = semundo_adjust(p, &suptr, semid,
|
||||
sops[i].sem_num, -adjval);
|
||||
if (eval == 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Oh-Oh! We ran out of either sem_undo's or undo's.
|
||||
* Rollback the adjustments to this point and then
|
||||
* rollback the semaphore ups and down so we can return
|
||||
* with an error with all structures restored. We
|
||||
* rollback the undo's in the exact reverse order that
|
||||
* we applied them. This guarantees that we won't run
|
||||
* out of space as we roll things back out.
|
||||
*/
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
if ((sops[j].sem_flg & SEM_UNDO) == 0)
|
||||
continue;
|
||||
adjval = sops[j].sem_op;
|
||||
if (adjval == 0)
|
||||
continue;
|
||||
if (semundo_adjust(p, &suptr, semid,
|
||||
sops[j].sem_num, adjval) != 0)
|
||||
panic("semop - can't undo undos");
|
||||
}
|
||||
|
||||
for (j = 0; j < nsops; j++)
|
||||
semaptr->sem_base[sops[j].sem_num].semval -=
|
||||
sops[j].sem_op;
|
||||
|
||||
#ifdef SEM_DEBUG
|
||||
printf("eval = %d from semundo_adjust\n", eval);
|
||||
#endif
|
||||
return(eval);
|
||||
} /* loop through the sops */
|
||||
} /* if (do_undos) */
|
||||
|
||||
/* We're definitely done - set the sempid's */
|
||||
for (i = 0; i < nsops; i++) {
|
||||
sopptr = &sops[i];
|
||||
semptr = &semaptr->sem_base[sopptr->sem_num];
|
||||
semptr->sempid = p->p_pid;
|
||||
}
|
||||
|
||||
/* Do a wakeup if any semaphore was up'd. */
|
||||
if (do_wakeup) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semop: doing wakeup\n");
|
||||
#ifdef SEM_WAKEUP
|
||||
sem_wakeup((caddr_t)semaptr);
|
||||
#else
|
||||
wakeup((caddr_t)semaptr);
|
||||
#endif
|
||||
printf("semop: back from wakeup\n");
|
||||
#else
|
||||
wakeup((caddr_t)semaptr);
|
||||
#endif
|
||||
}
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semop: done\n");
|
||||
#endif
|
||||
*retval = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through the undo structures for this process and apply the adjustments to
|
||||
* semaphores.
|
||||
*/
|
||||
semexit(p)
|
||||
struct proc *p;
|
||||
{
|
||||
register struct sem_undo *suptr;
|
||||
register struct sem_undo **supptr;
|
||||
int did_something;
|
||||
|
||||
/*
|
||||
* If somebody else is holding the global semaphore facility lock
|
||||
* then sleep until it is released.
|
||||
*/
|
||||
while (semlock_holder != NULL && semlock_holder != p) {
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semaphore facility locked - sleeping ...\n");
|
||||
#endif
|
||||
sleep((caddr_t)&semlock_holder, (PZERO - 4));
|
||||
}
|
||||
|
||||
did_something = 0;
|
||||
|
||||
/*
|
||||
* Go through the chain of undo vectors looking for one
|
||||
* associated with this process.
|
||||
*/
|
||||
|
||||
for (supptr = &semu_list; (suptr = *supptr) != NULL;
|
||||
supptr = &suptr->un_next) {
|
||||
if (suptr->un_proc == p)
|
||||
break;
|
||||
}
|
||||
|
||||
if (suptr == NULL)
|
||||
goto unlock;
|
||||
|
||||
#ifdef SEM_DEBUG
|
||||
printf("proc @%08x has undo structure with %d entries\n", p,
|
||||
suptr->un_cnt);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If there are any active undo elements then process them.
|
||||
*/
|
||||
if (suptr->un_cnt > 0) {
|
||||
int ix;
|
||||
|
||||
for (ix = 0; ix < suptr->un_cnt; ix++) {
|
||||
int semid = suptr->un_ent[ix].un_id;
|
||||
int semnum = suptr->un_ent[ix].un_num;
|
||||
int adjval = suptr->un_ent[ix].un_adjval;
|
||||
struct semid_ds *semaptr;
|
||||
|
||||
semaptr = &sema[semid];
|
||||
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0)
|
||||
panic("semexit - semid not allocated");
|
||||
if (semnum >= semaptr->sem_nsems)
|
||||
panic("semexit - semnum out of range");
|
||||
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semexit: %08x id=%d num=%d(adj=%d) ; sem=%d\n",
|
||||
suptr->un_proc, suptr->un_ent[ix].un_id,
|
||||
suptr->un_ent[ix].un_num,
|
||||
suptr->un_ent[ix].un_adjval,
|
||||
semaptr->sem_base[semnum].semval);
|
||||
#endif
|
||||
|
||||
if (adjval < 0) {
|
||||
if (semaptr->sem_base[semnum].semval < -adjval)
|
||||
semaptr->sem_base[semnum].semval = 0;
|
||||
else
|
||||
semaptr->sem_base[semnum].semval +=
|
||||
adjval;
|
||||
} else
|
||||
semaptr->sem_base[semnum].semval += adjval;
|
||||
|
||||
#ifdef SEM_WAKEUP
|
||||
sem_wakeup((caddr_t)semaptr);
|
||||
#else
|
||||
wakeup((caddr_t)semaptr);
|
||||
#endif
|
||||
#ifdef SEM_DEBUG
|
||||
printf("semexit: back from wakeup\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deallocate the undo vector.
|
||||
*/
|
||||
#ifdef SEM_DEBUG
|
||||
printf("removing vector\n");
|
||||
#endif
|
||||
suptr->un_proc = NULL;
|
||||
*supptr = suptr->un_next;
|
||||
|
||||
unlock:
|
||||
/*
|
||||
* If the exiting process is holding the global semaphore facility
|
||||
* lock then release it.
|
||||
*/
|
||||
if (semlock_holder == p) {
|
||||
semlock_holder = NULL;
|
||||
wakeup((caddr_t)&semlock_holder);
|
||||
}
|
||||
}
|
517
sys/kern/sysv_shm.c
Normal file
517
sys/kern/sysv_shm.c
Normal file
@ -0,0 +1,517 @@
|
||||
/* $Id$ */
|
||||
/* $NetBSD: sysv_shm.c,v 1.23 1994/07/04 23:25:12 glass Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Adam Glass and Charles Hannum. 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 Adam Glass and Charles
|
||||
* Hannum.
|
||||
* 4. The names of the authors may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_kern.h>
|
||||
|
||||
/*
|
||||
* Provides the following externally accessible functions:
|
||||
*
|
||||
* shminit(void); initialization
|
||||
* shmexit(struct proc *) cleanup
|
||||
* shmfork(struct proc *, struct proc *, int) fork handling
|
||||
* shmsys(arg1, arg2, arg3, arg4); shm{at,ctl,dt,get}(arg2, arg3, arg4)
|
||||
*
|
||||
* Structures:
|
||||
* shmsegs (an array of 'struct shmid_ds')
|
||||
* per proc array of 'struct shmmap_state'
|
||||
*/
|
||||
|
||||
int shmat(), shmctl(), shmdt(), shmget();
|
||||
int (*shmcalls[])() = { shmat, shmctl, shmdt, shmget };
|
||||
|
||||
#define SHMSEG_FREE 0x0200
|
||||
#define SHMSEG_REMOVED 0x0400
|
||||
#define SHMSEG_ALLOCATED 0x0800
|
||||
#define SHMSEG_WANTED 0x1000
|
||||
|
||||
vm_map_t sysvshm_map;
|
||||
int shm_last_free, shm_nused, shm_committed;
|
||||
|
||||
struct shm_handle {
|
||||
vm_offset_t kva;
|
||||
};
|
||||
|
||||
struct shmmap_state {
|
||||
vm_offset_t va;
|
||||
int shmid;
|
||||
};
|
||||
|
||||
static void shm_deallocate_segment __P((struct shmid_ds *));
|
||||
static int shm_find_segment_by_key __P((key_t));
|
||||
static struct shmid_ds *shm_find_segment_by_shmid __P((int));
|
||||
static int shm_delete_mapping __P((struct proc *, struct shmmap_state *));
|
||||
|
||||
static int
|
||||
shm_find_segment_by_key(key)
|
||||
key_t key;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < shminfo.shmmni; i++)
|
||||
if ((shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED) &&
|
||||
shmsegs[i].shm_perm.key == key)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct shmid_ds *
|
||||
shm_find_segment_by_shmid(shmid)
|
||||
int shmid;
|
||||
{
|
||||
int segnum;
|
||||
struct shmid_ds *shmseg;
|
||||
|
||||
segnum = IPCID_TO_IX(shmid);
|
||||
if (segnum < 0 || segnum >= shminfo.shmmni)
|
||||
return NULL;
|
||||
shmseg = &shmsegs[segnum];
|
||||
if ((shmseg->shm_perm.mode & (SHMSEG_ALLOCATED | SHMSEG_REMOVED))
|
||||
!= SHMSEG_ALLOCATED ||
|
||||
shmseg->shm_perm.seq != IPCID_TO_SEQ(shmid))
|
||||
return NULL;
|
||||
return shmseg;
|
||||
}
|
||||
|
||||
static void
|
||||
shm_deallocate_segment(shmseg)
|
||||
struct shmid_ds *shmseg;
|
||||
{
|
||||
struct shm_handle *shm_handle;
|
||||
size_t size;
|
||||
|
||||
shm_handle = shmseg->shm_internal;
|
||||
size = (shmseg->shm_segsz + CLOFSET) & ~CLOFSET;
|
||||
vm_deallocate(sysvshm_map, shm_handle->kva, size);
|
||||
free((caddr_t)shm_handle, M_SHM);
|
||||
shmseg->shm_internal = NULL;
|
||||
shm_committed -= btoc(size);
|
||||
shm_nused--;
|
||||
shmseg->shm_perm.mode = SHMSEG_FREE;
|
||||
}
|
||||
|
||||
static int
|
||||
shm_delete_mapping(p, shmmap_s)
|
||||
struct proc *p;
|
||||
struct shmmap_state *shmmap_s;
|
||||
{
|
||||
struct shmid_ds *shmseg;
|
||||
int segnum, result;
|
||||
size_t size;
|
||||
|
||||
segnum = IPCID_TO_IX(shmmap_s->shmid);
|
||||
shmseg = &shmsegs[segnum];
|
||||
size = (shmseg->shm_segsz + CLOFSET) & ~CLOFSET;
|
||||
result = vm_deallocate(&p->p_vmspace->vm_map, shmmap_s->va, size);
|
||||
if (result != KERN_SUCCESS)
|
||||
return EINVAL;
|
||||
shmmap_s->shmid = -1;
|
||||
shmseg->shm_dtime = time.tv_sec;
|
||||
if ((--shmseg->shm_nattch <= 0) &&
|
||||
(shmseg->shm_perm.mode & SHMSEG_REMOVED)) {
|
||||
shm_deallocate_segment(shmseg);
|
||||
shm_last_free = segnum;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct shmdt_args {
|
||||
void *shmaddr;
|
||||
};
|
||||
int
|
||||
shmdt(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct shmdt_args *uap;
|
||||
int *retval;
|
||||
{
|
||||
struct shmmap_state *shmmap_s;
|
||||
int i;
|
||||
|
||||
shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm;
|
||||
for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
|
||||
if (shmmap_s->shmid != -1 &&
|
||||
shmmap_s->va == (vm_offset_t)uap->shmaddr)
|
||||
break;
|
||||
if (i == shminfo.shmseg)
|
||||
return EINVAL;
|
||||
return shm_delete_mapping(p, shmmap_s);
|
||||
}
|
||||
|
||||
struct shmat_args {
|
||||
int shmid;
|
||||
void *shmaddr;
|
||||
int shmflg;
|
||||
};
|
||||
int
|
||||
shmat(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct shmat_args *uap;
|
||||
int *retval;
|
||||
{
|
||||
int error, i, flags;
|
||||
struct ucred *cred = p->p_ucred;
|
||||
struct shmid_ds *shmseg;
|
||||
struct shmmap_state *shmmap_s = NULL;
|
||||
vm_offset_t attach_va;
|
||||
vm_prot_t prot;
|
||||
vm_size_t size;
|
||||
|
||||
shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm;
|
||||
if (shmmap_s == NULL) {
|
||||
size = shminfo.shmseg * sizeof(struct shmmap_state);
|
||||
shmmap_s = malloc(size, M_SHM, M_WAITOK);
|
||||
for (i = 0; i < shminfo.shmseg; i++)
|
||||
shmmap_s[i].shmid = -1;
|
||||
p->p_vmspace->vm_shm = (caddr_t)shmmap_s;
|
||||
}
|
||||
shmseg = shm_find_segment_by_shmid(uap->shmid);
|
||||
if (shmseg == NULL)
|
||||
return EINVAL;
|
||||
if (error = ipcperm(cred, &shmseg->shm_perm,
|
||||
(uap->shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W))
|
||||
return error;
|
||||
for (i = 0; i < shminfo.shmseg; i++) {
|
||||
if (shmmap_s->shmid == -1)
|
||||
break;
|
||||
shmmap_s++;
|
||||
}
|
||||
if (i >= shminfo.shmseg)
|
||||
return EMFILE;
|
||||
size = (shmseg->shm_segsz + CLOFSET) & ~CLOFSET;
|
||||
prot = VM_PROT_READ;
|
||||
if ((uap->shmflg & SHM_RDONLY) == 0)
|
||||
prot |= VM_PROT_WRITE;
|
||||
flags = MAP_ANON | MAP_SHARED;
|
||||
if (uap->shmaddr) {
|
||||
flags |= MAP_FIXED;
|
||||
if (uap->shmflg & SHM_RND)
|
||||
attach_va = (vm_offset_t)uap->shmaddr & ~(SHMLBA-1);
|
||||
else if (((vm_offset_t)uap->shmaddr & (SHMLBA-1)) == 0)
|
||||
attach_va = (vm_offset_t)uap->shmaddr;
|
||||
else
|
||||
return EINVAL;
|
||||
} else {
|
||||
/* This is just a hint to vm_mmap() about where to put it. */
|
||||
attach_va = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);
|
||||
}
|
||||
error = vm_mmap(&p->p_vmspace->vm_map, &attach_va, size, prot,
|
||||
VM_PROT_DEFAULT, flags, (caddr_t) uap->shmid, 0);
|
||||
if (error)
|
||||
return error;
|
||||
shmmap_s->va = attach_va;
|
||||
shmmap_s->shmid = uap->shmid;
|
||||
shmseg->shm_lpid = p->p_pid;
|
||||
shmseg->shm_atime = time.tv_sec;
|
||||
shmseg->shm_nattch++;
|
||||
*retval = attach_va;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct shmctl_args {
|
||||
int shmid;
|
||||
int cmd;
|
||||
struct shmat_ds *ubuf;
|
||||
};
|
||||
int
|
||||
shmctl(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct shmctl_args *uap;
|
||||
int *retval;
|
||||
{
|
||||
int error, segnum;
|
||||
struct ucred *cred = p->p_ucred;
|
||||
struct shmid_ds inbuf;
|
||||
struct shmid_ds *shmseg;
|
||||
|
||||
shmseg = shm_find_segment_by_shmid(uap->shmid);
|
||||
if (shmseg == NULL)
|
||||
return EINVAL;
|
||||
switch (uap->cmd) {
|
||||
case IPC_STAT:
|
||||
if (error = ipcperm(cred, &shmseg->shm_perm, IPC_R))
|
||||
return error;
|
||||
if (error = copyout((caddr_t)shmseg, uap->ubuf, sizeof(inbuf)))
|
||||
return error;
|
||||
break;
|
||||
case IPC_SET:
|
||||
if (error = ipcperm(cred, &shmseg->shm_perm, IPC_M))
|
||||
return error;
|
||||
if (error = copyin(uap->ubuf, (caddr_t)&inbuf, sizeof(inbuf)))
|
||||
return error;
|
||||
shmseg->shm_perm.uid = inbuf.shm_perm.uid;
|
||||
shmseg->shm_perm.gid = inbuf.shm_perm.gid;
|
||||
shmseg->shm_perm.mode =
|
||||
(shmseg->shm_perm.mode & ~ACCESSPERMS) |
|
||||
(inbuf.shm_perm.mode & ACCESSPERMS);
|
||||
shmseg->shm_ctime = time.tv_sec;
|
||||
break;
|
||||
case IPC_RMID:
|
||||
if (error = ipcperm(cred, &shmseg->shm_perm, IPC_M))
|
||||
return error;
|
||||
shmseg->shm_perm.key = IPC_PRIVATE;
|
||||
shmseg->shm_perm.mode |= SHMSEG_REMOVED;
|
||||
if (shmseg->shm_nattch <= 0) {
|
||||
shm_deallocate_segment(shmseg);
|
||||
shm_last_free = IPCID_TO_IX(uap->shmid);
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
case SHM_LOCK:
|
||||
case SHM_UNLOCK:
|
||||
#endif
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct shmget_args {
|
||||
key_t key;
|
||||
size_t size;
|
||||
int shmflg;
|
||||
};
|
||||
static int
|
||||
shmget_existing(p, uap, mode, segnum, retval)
|
||||
struct proc *p;
|
||||
struct shmget_args *uap;
|
||||
int mode;
|
||||
int segnum;
|
||||
int *retval;
|
||||
{
|
||||
struct shmid_ds *shmseg;
|
||||
struct ucred *cred = p->p_ucred;
|
||||
int error;
|
||||
|
||||
shmseg = &shmsegs[segnum];
|
||||
if (shmseg->shm_perm.mode & SHMSEG_REMOVED) {
|
||||
/*
|
||||
* This segment is in the process of being allocated. Wait
|
||||
* until it's done, and look the key up again (in case the
|
||||
* allocation failed or it was freed).
|
||||
*/
|
||||
shmseg->shm_perm.mode |= SHMSEG_WANTED;
|
||||
if (error =
|
||||
tsleep((caddr_t)shmseg, PLOCK | PCATCH, "shmget", 0))
|
||||
return error;
|
||||
return EAGAIN;
|
||||
}
|
||||
if (error = ipcperm(cred, &shmseg->shm_perm, mode))
|
||||
return error;
|
||||
if (uap->size && uap->size > shmseg->shm_segsz)
|
||||
return EINVAL;
|
||||
if (uap->shmflg & (IPC_CREAT | IPC_EXCL) == (IPC_CREAT | IPC_EXCL))
|
||||
return EEXIST;
|
||||
*retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
shmget_allocate_segment(p, uap, mode, retval)
|
||||
struct proc *p;
|
||||
struct shmget_args *uap;
|
||||
int mode;
|
||||
int *retval;
|
||||
{
|
||||
int i, segnum, result, shmid, size;
|
||||
struct ucred *cred = p->p_ucred;
|
||||
struct shmid_ds *shmseg;
|
||||
struct shm_handle *shm_handle;
|
||||
|
||||
if (uap->size < shminfo.shmmin || uap->size > shminfo.shmmax)
|
||||
return EINVAL;
|
||||
if (shm_nused >= shminfo.shmmni) /* any shmids left? */
|
||||
return ENOSPC;
|
||||
size = (uap->size + CLOFSET) & ~CLOFSET;
|
||||
if (shm_committed + btoc(size) > shminfo.shmall)
|
||||
return ENOMEM;
|
||||
if (shm_last_free < 0) {
|
||||
for (i = 0; i < shminfo.shmmni; i++)
|
||||
if (shmsegs[i].shm_perm.mode & SHMSEG_FREE)
|
||||
break;
|
||||
if (i == shminfo.shmmni)
|
||||
panic("shmseg free count inconsistent");
|
||||
segnum = i;
|
||||
} else {
|
||||
segnum = shm_last_free;
|
||||
shm_last_free = -1;
|
||||
}
|
||||
shmseg = &shmsegs[segnum];
|
||||
/*
|
||||
* In case we sleep in malloc(), mark the segment present but deleted
|
||||
* so that noone else tries to create the same key.
|
||||
*/
|
||||
shmseg->shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED;
|
||||
shmseg->shm_perm.key = uap->key;
|
||||
shmseg->shm_perm.seq = (shmseg->shm_perm.seq + 1) & 0x7fff;
|
||||
shm_handle = (struct shm_handle *)
|
||||
malloc(sizeof(struct shm_handle), M_SHM, M_WAITOK);
|
||||
shmid = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm);
|
||||
result = vm_mmap(sysvshm_map, &shm_handle->kva, size, VM_PROT_ALL,
|
||||
VM_PROT_DEFAULT, MAP_ANON, (caddr_t) shmid, 0);
|
||||
if (result != KERN_SUCCESS) {
|
||||
shmseg->shm_perm.mode = SHMSEG_FREE;
|
||||
shm_last_free = segnum;
|
||||
free((caddr_t)shm_handle, M_SHM);
|
||||
/* Just in case. */
|
||||
wakeup((caddr_t)shmseg);
|
||||
return ENOMEM;
|
||||
}
|
||||
shmseg->shm_internal = shm_handle;
|
||||
shmseg->shm_perm.cuid = shmseg->shm_perm.uid = cred->cr_uid;
|
||||
shmseg->shm_perm.cgid = shmseg->shm_perm.gid = cred->cr_gid;
|
||||
shmseg->shm_perm.mode = (shmseg->shm_perm.mode & SHMSEG_WANTED) |
|
||||
(mode & ACCESSPERMS) | SHMSEG_ALLOCATED;
|
||||
shmseg->shm_segsz = uap->size;
|
||||
shmseg->shm_cpid = p->p_pid;
|
||||
shmseg->shm_lpid = shmseg->shm_nattch = 0;
|
||||
shmseg->shm_atime = shmseg->shm_dtime = 0;
|
||||
shmseg->shm_ctime = time.tv_sec;
|
||||
shm_committed += btoc(size);
|
||||
shm_nused++;
|
||||
if (shmseg->shm_perm.mode & SHMSEG_WANTED) {
|
||||
/*
|
||||
* Somebody else wanted this key while we were asleep. Wake
|
||||
* them up now.
|
||||
*/
|
||||
shmseg->shm_perm.mode &= ~SHMSEG_WANTED;
|
||||
wakeup((caddr_t)shmseg);
|
||||
}
|
||||
*retval = shmid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
shmget(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct shmget_args *uap;
|
||||
int *retval;
|
||||
{
|
||||
int segnum, mode, error;
|
||||
struct shmid_ds *shmseg;
|
||||
|
||||
mode = uap->shmflg & ACCESSPERMS;
|
||||
if (uap->key != IPC_PRIVATE) {
|
||||
again:
|
||||
segnum = shm_find_segment_by_key(uap->key);
|
||||
if (segnum >= 0) {
|
||||
error = shmget_existing(p, uap, mode, segnum, retval);
|
||||
if (error == EAGAIN)
|
||||
goto again;
|
||||
return error;
|
||||
}
|
||||
if ((uap->shmflg & IPC_CREAT) == 0)
|
||||
return ENOENT;
|
||||
}
|
||||
return shmget_allocate_segment(p, uap, mode, retval);
|
||||
}
|
||||
|
||||
struct shmsys_args {
|
||||
u_int which;
|
||||
};
|
||||
int
|
||||
shmsys(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct shmsys_args *uap;
|
||||
int *retval;
|
||||
{
|
||||
|
||||
if (uap->which >= sizeof(shmcalls)/sizeof(shmcalls[0]))
|
||||
return EINVAL;
|
||||
return ((*shmcalls[uap->which])(p, &uap[1], retval));
|
||||
}
|
||||
|
||||
void
|
||||
shmfork(p1, p2, isvfork)
|
||||
struct proc *p1, *p2;
|
||||
int isvfork;
|
||||
{
|
||||
struct shmmap_state *shmmap_s;
|
||||
size_t size;
|
||||
int i;
|
||||
|
||||
size = shminfo.shmseg * sizeof(struct shmmap_state);
|
||||
shmmap_s = malloc(size, M_SHM, M_WAITOK);
|
||||
bcopy((caddr_t)p1->p_vmspace->vm_shm, (caddr_t)shmmap_s, size);
|
||||
p2->p_vmspace->vm_shm = (caddr_t)shmmap_s;
|
||||
for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
|
||||
if (shmmap_s->shmid != -1)
|
||||
shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch++;
|
||||
}
|
||||
|
||||
void
|
||||
shmexit(p)
|
||||
struct proc *p;
|
||||
{
|
||||
struct shmmap_state *shmmap_s;
|
||||
struct shmid_ds *shmseg;
|
||||
int i;
|
||||
|
||||
shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm;
|
||||
for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
|
||||
if (shmmap_s->shmid != -1)
|
||||
shm_delete_mapping(p, shmmap_s);
|
||||
free((caddr_t)p->p_vmspace->vm_shm, M_SHM);
|
||||
p->p_vmspace->vm_shm = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
shminit()
|
||||
{
|
||||
int i;
|
||||
vm_offset_t garbage1, garbage2;
|
||||
|
||||
/* actually this *should* be pageable. SHM_{LOCK,UNLOCK} */
|
||||
sysvshm_map = kmem_suballoc(kernel_map, &garbage1, &garbage2,
|
||||
shminfo.shmall * NBPG, TRUE);
|
||||
for (i = 0; i < shminfo.shmmni; i++) {
|
||||
shmsegs[i].shm_perm.mode = SHMSEG_FREE;
|
||||
shmsegs[i].shm_perm.seq = 0;
|
||||
}
|
||||
shm_last_free = 0;
|
||||
shm_nused = 0;
|
||||
shm_committed = 0;
|
||||
}
|
@ -41,7 +41,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ipc.h 8.3 (Berkeley) 1/21/94
|
||||
* $Id$
|
||||
* $Id: ipc.h,v 1.2 1994/08/02 07:53:06 davidg Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -65,6 +65,7 @@ struct ipc_perm {
|
||||
/* common mode bits */
|
||||
#define IPC_R 00400 /* read permission */
|
||||
#define IPC_W 00200 /* write/alter permission */
|
||||
#define IPC_M 10000 /* permission to change control info */
|
||||
|
||||
/* SVID required constants (same values as system 5) */
|
||||
#define IPC_CREAT 01000 /* create entry if key does not exist */
|
||||
@ -77,4 +78,11 @@ struct ipc_perm {
|
||||
#define IPC_SET 1 /* set options */
|
||||
#define IPC_STAT 2 /* get options */
|
||||
|
||||
#ifdef KERNEL
|
||||
/* Macros to convert between ipc ids and array indices or sequence ids */
|
||||
#define IPCID_TO_IX(id) ((id) & 0xffff)
|
||||
#define IPCID_TO_SEQ(id) (((id) >> 16) & 0xffff)
|
||||
#define IXSEQ_TO_IPCID(ix,perm) (((perm.seq) << 16) | (ix & 0xffff))
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif /* !_SYS_IPC_H_ */
|
||||
|
161
sys/sys/msg.h
Normal file
161
sys/sys/msg.h
Normal file
@ -0,0 +1,161 @@
|
||||
/* $Id$ */
|
||||
/* $NetBSD: msg.h,v 1.4 1994/06/29 06:44:43 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* SVID compatible msg.h file
|
||||
*
|
||||
* Author: Daniel Boulet
|
||||
*
|
||||
* Copyright 1993 Daniel Boulet and RTMX Inc.
|
||||
*
|
||||
* This system call was implemented by Daniel Boulet under contract from RTMX.
|
||||
*
|
||||
* Redistribution and use in source forms, with and without modification,
|
||||
* are permitted provided that this entire comment appears intact.
|
||||
*
|
||||
* Redistribution in binary form may occur without any restrictions.
|
||||
* Obviously, it would be nice if you gave credit where credit is due
|
||||
* but requiring it would be too onerous.
|
||||
*
|
||||
* This software is provided ``AS IS'' without any warranties of any kind.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_MSG_H_
|
||||
#define _SYS_MSG_H_
|
||||
|
||||
#include <sys/ipc.h>
|
||||
|
||||
/*
|
||||
* The MSG_NOERROR identifier value, the msqid_ds struct and the msg struct
|
||||
* are as defined by the SV API Intel 386 Processor Supplement.
|
||||
*/
|
||||
|
||||
#define MSG_NOERROR 010000 /* don't complain about too long msgs */
|
||||
|
||||
struct msqid_ds {
|
||||
struct ipc_perm msg_perm; /* msg queue permission bits */
|
||||
struct msg *msg_first; /* first message in the queue */
|
||||
struct msg *msg_last; /* last message in the queue */
|
||||
u_long msg_cbytes; /* number of bytes in use on the queue */
|
||||
u_long msg_qnum; /* number of msgs in the queue */
|
||||
u_long msg_qbytes; /* max # of bytes on the queue */
|
||||
pid_t msg_lspid; /* pid of last msgsnd() */
|
||||
pid_t msg_lrpid; /* pid of last msgrcv() */
|
||||
time_t msg_stime; /* time of last msgsnd() */
|
||||
long msg_pad1;
|
||||
time_t msg_rtime; /* time of last msgrcv() */
|
||||
long msg_pad2;
|
||||
time_t msg_ctime; /* time of last msgctl() */
|
||||
long msg_pad3;
|
||||
long msg_pad4[4];
|
||||
};
|
||||
|
||||
struct msg {
|
||||
struct msg *msg_next; /* next msg in the chain */
|
||||
long msg_type; /* type of this message */
|
||||
/* >0 -> type of this message */
|
||||
/* 0 -> free header */
|
||||
u_short msg_ts; /* size of this message */
|
||||
short msg_spot; /* location of start of msg in buffer */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure describing a message. The SVID doesn't suggest any
|
||||
* particular name for this structure. There is a reference in the
|
||||
* msgop man page that reads "The structure mymsg is an example of what
|
||||
* this user defined buffer might look like, and includes the following
|
||||
* members:". This sentence is followed by two lines equivalent
|
||||
* to the mtype and mtext field declarations below. It isn't clear
|
||||
* if "mymsg" refers to the naem of the structure type or the name of an
|
||||
* instance of the structure...
|
||||
*/
|
||||
struct mymsg {
|
||||
long mtype; /* message type (+ve integer) */
|
||||
char mtext[1]; /* message body */
|
||||
};
|
||||
|
||||
/*
|
||||
* Based on the configuration parameters described in an SVR2 (yes, two)
|
||||
* config(1m) man page.
|
||||
*
|
||||
* Each message is broken up and stored in segments that are msgssz bytes
|
||||
* long. For efficiency reasons, this should be a power of two. Also,
|
||||
* it doesn't make sense if it is less than 8 or greater than about 256.
|
||||
* Consequently, msginit in kern/sysv_msg.c checks that msgssz is a power of
|
||||
* two between 8 and 1024 inclusive (and panic's if it isn't).
|
||||
*/
|
||||
struct msginfo {
|
||||
int msgmax, /* max chars in a message */
|
||||
msgmni, /* max message queue identifiers */
|
||||
msgmnb, /* max chars in a queue */
|
||||
msgtql, /* max messages in system */
|
||||
msgssz, /* size of a message segment (see notes above) */
|
||||
msgseg; /* number of message segments */
|
||||
};
|
||||
struct msginfo msginfo;
|
||||
|
||||
#ifdef KERNEL
|
||||
#ifndef MSGSSZ
|
||||
#define MSGSSZ 8 /* Each segment must be 2^N long */
|
||||
#endif
|
||||
#ifndef MSGSEG
|
||||
#define MSGSEG 2048 /* must be less than 32767 */
|
||||
#endif
|
||||
#undef MSGMAX /* ALWAYS compute MGSMAX! */
|
||||
#define MSGMAX (MSGSSZ*MSGSEG)
|
||||
#ifndef MSGMNB
|
||||
#define MSGMNB 2048 /* max # of bytes in a queue */
|
||||
#endif
|
||||
#ifndef MSGMNI
|
||||
#define MSGMNI 40
|
||||
#endif
|
||||
#ifndef MSGTQL
|
||||
#define MSGTQL 40
|
||||
#endif
|
||||
|
||||
/*
|
||||
* macros to convert between msqid_ds's and msqid's.
|
||||
* (specific to this implementation)
|
||||
*/
|
||||
#define MSQID(ix,ds) ((ix) & 0xffff | (((ds).msg_perm.seq << 16) & 0xffff0000))
|
||||
#define MSQID_IX(id) ((id) & 0xffff)
|
||||
#define MSQID_SEQ(id) (((id) >> 16) & 0xffff)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The rest of this file is specific to this particular implementation.
|
||||
*/
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
/*
|
||||
* Stuff allocated in machdep.h
|
||||
*/
|
||||
struct msgmap {
|
||||
short next; /* next segment in buffer */
|
||||
/* -1 -> available */
|
||||
/* 0..(MSGSEG-1) -> index of next segment */
|
||||
};
|
||||
|
||||
char *msgpool; /* MSGMAX byte long msg buffer pool */
|
||||
struct msgmap *msgmaps; /* MSGSEG msgmap structures */
|
||||
struct msg *msghdrs; /* MSGTQL msg headers */
|
||||
struct msqid_ds *msqids; /* MSGMNI msqid_ds struct's */
|
||||
|
||||
#define MSG_LOCKED 01000 /* Is this msqid_ds locked? */
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef KERNEL
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
int msgsys __P((int, ...));
|
||||
int msgctl __P((int, int, struct msqid_ds *));
|
||||
int msgget __P((key_t, int));
|
||||
int msgsnd __P((int, void *, size_t, int));
|
||||
int msgrcv __P((int, void*, size_t, long, int));
|
||||
__END_DECLS
|
||||
#endif /* !KERNEL */
|
||||
|
||||
#endif /* !_SYS_MSG_H_ */
|
179
sys/sys/sem.h
Normal file
179
sys/sys/sem.h
Normal file
@ -0,0 +1,179 @@
|
||||
/* $Id$ */
|
||||
/* $NetBSD: sem.h,v 1.5 1994/06/29 06:45:15 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* SVID compatible sem.h file
|
||||
*
|
||||
* Author: Daniel Boulet
|
||||
*/
|
||||
|
||||
#ifndef _SYS_SEM_H_
|
||||
#define _SYS_SEM_H_
|
||||
|
||||
#include <sys/ipc.h>
|
||||
|
||||
struct sem {
|
||||
u_short semval; /* semaphore value */
|
||||
pid_t sempid; /* pid of last operation */
|
||||
u_short semncnt; /* # awaiting semval > cval */
|
||||
u_short semzcnt; /* # awaiting semval = 0 */
|
||||
};
|
||||
|
||||
struct semid_ds {
|
||||
struct ipc_perm sem_perm; /* operation permission struct */
|
||||
struct sem *sem_base; /* pointer to first semaphore in set */
|
||||
u_short sem_nsems; /* number of sems in set */
|
||||
time_t sem_otime; /* last operation time */
|
||||
long sem_pad1; /* SVABI/386 says I need this here */
|
||||
time_t sem_ctime; /* last change time */
|
||||
/* Times measured in secs since */
|
||||
/* 00:00:00 GMT, Jan. 1, 1970 */
|
||||
long sem_pad2; /* SVABI/386 says I need this here */
|
||||
long sem_pad3[4]; /* SVABI/386 says I need this here */
|
||||
};
|
||||
|
||||
/*
|
||||
* semop's sops parameter structure
|
||||
*/
|
||||
struct sembuf {
|
||||
u_short sem_num; /* semaphore # */
|
||||
short sem_op; /* semaphore operation */
|
||||
short sem_flg; /* operation flags */
|
||||
};
|
||||
#define SEM_UNDO 010000
|
||||
|
||||
#define MAX_SOPS 5 /* maximum # of sembuf's per semop call */
|
||||
|
||||
/*
|
||||
* semctl's arg parameter structure
|
||||
*/
|
||||
union semun {
|
||||
int val; /* value for SETVAL */
|
||||
struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
|
||||
u_short *array; /* array for GETALL & SETALL */
|
||||
};
|
||||
|
||||
/*
|
||||
* commands for semctl
|
||||
*/
|
||||
#define GETNCNT 3 /* Return the value of semncnt {READ} */
|
||||
#define GETPID 4 /* Return the value of sempid {READ} */
|
||||
#define GETVAL 5 /* Return the value of semval {READ} */
|
||||
#define GETALL 6 /* Return semvals into arg.array {READ} */
|
||||
#define GETZCNT 7 /* Return the value of semzcnt {READ} */
|
||||
#define SETVAL 8 /* Set the value of semval to arg.val {ALTER} */
|
||||
#define SETALL 9 /* Set semvals from arg.array {ALTER} */
|
||||
|
||||
#ifdef KERNEL
|
||||
/*
|
||||
* Kernel implementation stuff
|
||||
*/
|
||||
#define SEMVMX 32767 /* semaphore maximum value */
|
||||
#define SEMAEM 16384 /* adjust on exit max value */
|
||||
|
||||
/*
|
||||
* Permissions
|
||||
*/
|
||||
#define SEM_A 0200 /* alter permission */
|
||||
#define SEM_R 0400 /* read permission */
|
||||
|
||||
/*
|
||||
* Undo structure (one per process)
|
||||
*/
|
||||
struct sem_undo {
|
||||
struct sem_undo *un_next; /* ptr to next active undo structure */
|
||||
struct proc *un_proc; /* owner of this structure */
|
||||
short un_cnt; /* # of active entries */
|
||||
struct undo {
|
||||
short un_adjval; /* adjust on exit values */
|
||||
short un_num; /* semaphore # */
|
||||
int un_id; /* semid */
|
||||
} un_ent[1]; /* undo entries */
|
||||
};
|
||||
|
||||
/*
|
||||
* semaphore info struct
|
||||
*/
|
||||
struct seminfo {
|
||||
int semmap, /* # of entries in semaphore map */
|
||||
semmni, /* # of semaphore identifiers */
|
||||
semmns, /* # of semaphores in system */
|
||||
semmnu, /* # of undo structures in system */
|
||||
semmsl, /* max # of semaphores per id */
|
||||
semopm, /* max # of operations per semop call */
|
||||
semume, /* max # of undo entries per process */
|
||||
semusz, /* size in bytes of undo structure */
|
||||
semvmx, /* semaphore maximum value */
|
||||
semaem; /* adjust on exit max value */
|
||||
};
|
||||
struct seminfo seminfo;
|
||||
|
||||
/* internal "mode" bits */
|
||||
#define SEM_ALLOC 01000 /* semaphore is allocated */
|
||||
#define SEM_DEST 02000 /* semaphore will be destroyed on last detach */
|
||||
|
||||
/*
|
||||
* Configuration parameters
|
||||
*/
|
||||
#ifndef SEMMNI
|
||||
#define SEMMNI 10 /* # of semaphore identifiers */
|
||||
#endif
|
||||
#ifndef SEMMNS
|
||||
#define SEMMNS 60 /* # of semaphores in system */
|
||||
#endif
|
||||
#ifndef SEMUME
|
||||
#define SEMUME 10 /* max # of undo entries per process */
|
||||
#endif
|
||||
#ifndef SEMMNU
|
||||
#define SEMMNU 30 /* # of undo structures in system */
|
||||
#endif
|
||||
|
||||
/* shouldn't need tuning */
|
||||
#ifndef SEMMAP
|
||||
#define SEMMAP 30 /* # of entries in semaphore map */
|
||||
#endif
|
||||
#ifndef SEMMSL
|
||||
#define SEMMSL SEMMNS /* max # of semaphores per id */
|
||||
#endif
|
||||
#ifndef SEMOPM
|
||||
#define SEMOPM 100 /* max # of operations per semop call */
|
||||
#endif
|
||||
|
||||
/* actual size of an undo structure */
|
||||
#define SEMUSZ (sizeof(struct sem_undo)+sizeof(struct undo)*SEMUME)
|
||||
|
||||
/*
|
||||
* Structures allocated in machdep.c
|
||||
*/
|
||||
struct semid_ds *sema; /* semaphore id pool */
|
||||
struct sem *sem; /* semaphore pool */
|
||||
struct map *semmap; /* semaphore allocation map */
|
||||
struct sem_undo *semu_list; /* list of active undo structures */
|
||||
int *semu; /* undo structure pool */
|
||||
|
||||
/*
|
||||
* Macro to find a particular sem_undo vector
|
||||
*/
|
||||
#define SEMU(ix) ((struct sem_undo *)(((long)semu)+ix * SEMUSZ))
|
||||
|
||||
/*
|
||||
* Parameters to the semconfig system call
|
||||
*/
|
||||
typedef enum {
|
||||
SEM_CONFIG_FREEZE, /* Freeze the semaphore facility. */
|
||||
SEM_CONFIG_THAW /* Thaw the semaphore facility. */
|
||||
} semconfig_ctl_t;
|
||||
#endif /* KERNEL */
|
||||
|
||||
#ifndef KERNEL
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
int semsys __P((int, ...));
|
||||
int semctl __P((int, int, int, union semun));
|
||||
int semget __P((key_t, int, int));
|
||||
int semop __P((int, struct sembuf *,unsigned));
|
||||
__END_DECLS
|
||||
#endif /* !KERNEL */
|
||||
|
||||
#endif /* !_SEM_H_ */
|
90
sys/sys/shm.h
Normal file
90
sys/sys/shm.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* $Id$ */
|
||||
/* $NetBSD: shm.h,v 1.15 1994/06/29 06:45:17 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Adam Glass
|
||||
* 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 Adam Glass.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* As defined+described in "X/Open System Interfaces and Headers"
|
||||
* Issue 4, p. XXX
|
||||
*/
|
||||
|
||||
#ifndef _SYS_SHM_H_
|
||||
#define _SYS_SHM_H_
|
||||
|
||||
#include <sys/ipc.h>
|
||||
|
||||
#define SHM_RDONLY 010000 /* Attach read-only (else read-write) */
|
||||
#define SHM_RND 020000 /* Round attach address to SHMLBA */
|
||||
#define SHMLBA CLBYTES /* Segment low boundry address multiple */
|
||||
|
||||
struct shmid_ds {
|
||||
struct ipc_perm shm_perm; /* operation permission structure */
|
||||
int shm_segsz; /* size of segment in bytes */
|
||||
pid_t shm_lpid; /* process ID of last shared memory op */
|
||||
pid_t shm_cpid; /* process ID of creator */
|
||||
short shm_nattch; /* number of current attaches */
|
||||
time_t shm_atime; /* time of last shmat() */
|
||||
time_t shm_dtime; /* time of last shmdt() */
|
||||
time_t shm_ctime; /* time of last change by shmctl() */
|
||||
void *shm_internal; /* sysv stupidity */
|
||||
};
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
/*
|
||||
* System 5 style catch-all structure for shared memory constants that
|
||||
* might be of interest to user programs. Do we really want/need this?
|
||||
*/
|
||||
struct shminfo {
|
||||
int shmmax, /* max shared memory segment size (bytes) */
|
||||
shmmin, /* min shared memory segment size (bytes) */
|
||||
shmmni, /* max number of shared memory identifiers */
|
||||
shmseg, /* max shared memory segments per process */
|
||||
shmall; /* max amount of shared memory (pages) */
|
||||
};
|
||||
struct shminfo shminfo;
|
||||
struct shmid_ds *shmsegs;
|
||||
|
||||
#else /* !KERNEL */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
int shmsys __P((int, ...));
|
||||
void *shmat __P((int, void *, int));
|
||||
int shmget __P((key_t, int, int));
|
||||
int shmctl __P((int, int, struct shmid_ds *));
|
||||
int shmdt __P((void *));
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !KERNEL */
|
||||
|
||||
#endif /* !_SYS_SHM_H_ */
|
@ -2,7 +2,7 @@
|
||||
* System call hiders.
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* created from $Id: syscalls.master,v 1.6 1994/09/01 05:12:42 davidg Exp $
|
||||
* created from $Id: syscalls.master,v 1.7 1994/09/13 00:48:19 wollman Exp $
|
||||
*/
|
||||
|
||||
HIDE_POSIX(fork)
|
||||
@ -175,6 +175,14 @@ HIDE_BSD(setdomainname)
|
||||
HIDE_BSD(uname)
|
||||
HIDE_BSD(sysarch)
|
||||
HIDE_BSD(rtprio)
|
||||
#ifdef SYSVSEM
|
||||
HIDE_BSD(semsys)
|
||||
#else
|
||||
#endif
|
||||
#ifdef SYSVMSG
|
||||
HIDE_BSD(msgsys)
|
||||
#else
|
||||
#endif
|
||||
#ifdef SYSVSHM
|
||||
HIDE_BSD(shmsys)
|
||||
#else
|
||||
|
@ -2,7 +2,7 @@
|
||||
* System call numbers.
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* created from $Id: syscalls.master,v 1.6 1994/09/01 05:12:42 davidg Exp $
|
||||
* created from $Id: syscalls.master,v 1.7 1994/09/13 00:48:19 wollman Exp $
|
||||
*/
|
||||
|
||||
#define SYS_syscall 0
|
||||
@ -165,6 +165,8 @@
|
||||
#define SYS_uname 164
|
||||
#define SYS_sysarch 165
|
||||
#define SYS_rtprio 166
|
||||
#define SYS_semsys 169
|
||||
#define SYS_msgsys 170
|
||||
#define SYS_shmsys 171
|
||||
#define SYS_ntp_gettime 175
|
||||
#define SYS_ntp_adjtime 176
|
||||
|
Loading…
x
Reference in New Issue
Block a user