IPC server: NetBSD sync, general improvements

- switch to the NetBSD identifier system; it is not only better, but
  also required for porting NetBSD ipcs(1) and ipcrm(1); however, it
  requires that slots not be moved, and that results in some changes;
- synchronize some other things with NetBSD: where keys are kept, as
  well as various non-permission mode flags;
- fix semctl(2) vararg retrieval and message field type;
- use SUSPEND instead of weird reply exceptions in the call table;
- fix several memory leaks and at least one missing permission check;
- improve the atomicity of semop(2) by a small amount, even though
  its atomicity is still broken at a fundamental level;
- use the new cheaper way to retrieve the current time;
- resolve all level-5 LLVM warnings.

Change-Id: I0c47aacde478b23bb77d628384aeab855a22fdbf
This commit is contained in:
David van Moolenbroek 2015-11-24 23:01:22 +00:00 committed by Lionel Sambuc
parent 58c1923c9f
commit 4d272e5a97
10 changed files with 353 additions and 285 deletions

View File

@ -365,7 +365,7 @@ typedef struct {
int id; int id;
int num; int num;
int cmd; int cmd;
int opt; vir_bytes opt;
int ret; int ret;
uint8_t padding[36]; uint8_t padding[36];
} mess_lc_ipc_semctl; } mess_lc_ipc_semctl;

View File

@ -1,4 +1,3 @@
#define __USE_MISC
#define _SYSTEM 1 #define _SYSTEM 1
#define _MINIX_SYSTEM 1 #define _MINIX_SYSTEM 1
@ -64,10 +63,23 @@ int semctl(int semid, int semnum, int cmd, ...)
m.m_lc_ipc_semctl.num = semnum; m.m_lc_ipc_semctl.num = semnum;
m.m_lc_ipc_semctl.cmd = cmd; m.m_lc_ipc_semctl.cmd = cmd;
va_start(ap, cmd); va_start(ap, cmd);
if (cmd == IPC_STAT || cmd == IPC_SET || cmd == IPC_INFO || switch (cmd) {
cmd == SEM_INFO || cmd == SEM_STAT || cmd == GETALL || case SETVAL:
cmd == SETALL || cmd == SETVAL) m.m_lc_ipc_semctl.opt = (vir_bytes)va_arg(ap, int);
m.m_lc_ipc_semctl.opt = (long) va_arg(ap, long); break;
case IPC_STAT:
case IPC_SET:
case IPC_INFO:
case SEM_INFO:
case SEM_STAT:
case GETALL:
case SETALL:
m.m_lc_ipc_semctl.opt = (vir_bytes)va_arg(ap, void *);
break;
default:
m.m_lc_ipc_semctl.opt = 0;
break;
}
va_end(ap); va_end(ap);
r = _syscall(ipc_pt, IPC_SEMCTL, &m); r = _syscall(ipc_pt, IPC_SEMCTL, &m);

View File

@ -9,4 +9,6 @@ FILES=ipc.conf
FILESNAME=ipc FILESNAME=ipc
FILESDIR= /etc/system.conf.d FILESDIR= /etc/system.conf.d
WARNS?= 5
.include <minix.service.mk> .include <minix.service.mk>

View File

@ -14,6 +14,7 @@
#include <sys/ipc.h> #include <sys/ipc.h>
#include <sys/shm.h> #include <sys/shm.h>
#include <sys/sem.h> #include <sys/sem.h>
#include <sys/stat.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <machine/param.h> #include <machine/param.h>
#include <machine/vm.h> #include <machine/vm.h>
@ -27,6 +28,15 @@
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <assert.h>
/*
* On NetBSD, these macros are only defined when _KERNEL is set. However,
* since ipcs(1) uses IXSEQ_TO_IPCID, NetBSD cannot change these macros without
* breaking the userland API. Thus, having a copy of them here is not risky.
*/
#define IPCID_TO_IX(id) ((id) & 0xffff)
#define IPCID_TO_SEQ(id) (((id) >> 16) & 0xffff)
int do_shmget(message *); int do_shmget(message *);
int do_shmat(message *); int do_shmat(message *);
@ -41,6 +51,4 @@ int is_sem_nil(void);
int is_shm_nil(void); int is_shm_nil(void);
void sem_process_vm_notify(void); void sem_process_vm_notify(void);
EXTERN int identifier;
EXTERN endpoint_t who_e; EXTERN endpoint_t who_e;
EXTERN int call_type;

View File

@ -1,25 +1,19 @@
#include "inc.h" #include "inc.h"
int identifier = 0x1234;
endpoint_t who_e; endpoint_t who_e;
int call_type; static unsigned int call_type;
static struct { #define CALL(n) [((n) - IPC_BASE)]
int type; static int (* const call_vec[])(message *) = {
int (*func)(message *); CALL(IPC_SHMGET) = do_shmget,
int reply; /* whether the reply action is passed through */ CALL(IPC_SHMAT) = do_shmat,
} ipc_calls[] = { CALL(IPC_SHMDT) = do_shmdt,
{ IPC_SHMGET, do_shmget, 0 }, CALL(IPC_SHMCTL) = do_shmctl,
{ IPC_SHMAT, do_shmat, 0 }, CALL(IPC_SEMGET) = do_semget,
{ IPC_SHMDT, do_shmdt, 0 }, CALL(IPC_SEMCTL) = do_semctl,
{ IPC_SHMCTL, do_shmctl, 0 }, CALL(IPC_SEMOP) = do_semop,
{ IPC_SEMGET, do_semget, 0 },
{ IPC_SEMCTL, do_semctl, 0 },
{ IPC_SEMOP, do_semop, 1 },
}; };
#define SIZE(a) (sizeof(a)/sizeof(a[0]))
static int verbose = 0; static int verbose = 0;
/* SEF functions and variables. */ /* SEF functions and variables. */
@ -30,15 +24,14 @@ static void sef_cb_signal_handler(int signo);
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
message m; message m;
unsigned int ipc_number;
int r;
/* SEF local startup. */ /* SEF local startup. */
env_setargs(argc, argv); env_setargs(argc, argv);
sef_local_startup(); sef_local_startup();
while (TRUE) { while (TRUE) {
int r;
int ipc_number;
if ((r = sef_receive(ANY, &m)) != OK) if ((r = sef_receive(ANY, &m)) != OK)
printf("sef_receive failed %d.\n", r); printf("sef_receive failed %d.\n", r);
who_e = m.m_source; who_e = m.m_source;
@ -61,22 +54,11 @@ int main(int argc, char *argv[])
continue; continue;
} }
/* ipc_number = (unsigned int)(call_type - IPC_BASE);
* The ipc number in the table can be obtained
* with a simple equation because the values of
* IPC system calls are consecutive and begin
* at ( IPC_BASE + 1 )
*/
ipc_number = call_type - (IPC_BASE + 1);
/* dispatch message */ /* dispatch message */
if (ipc_number >= 0 && ipc_number < SIZE(ipc_calls)) { if (ipc_number < __arraycount(call_vec) &&
int result; call_vec[ipc_number] != NULL) {
if (ipc_calls[ipc_number].type != call_type)
panic("IPC: call table order mismatch");
/* If any process does an IPC call, /* If any process does an IPC call,
* we have to know about it exiting. * we have to know about it exiting.
* Tell VM to watch it for us. * Tell VM to watch it for us.
@ -85,19 +67,18 @@ int main(int argc, char *argv[])
printf("IPC: watch failed on %d\n", m.m_source); printf("IPC: watch failed on %d\n", m.m_source);
} }
result = ipc_calls[ipc_number].func(&m); r = call_vec[ipc_number](&m);
/* /*
* The handler of the IPC call did not * The handler of the IPC call did not
* post a reply. * post a reply.
*/ */
if (!ipc_calls[ipc_number].reply) { if (r != SUSPEND) {
m.m_type = r;
m.m_type = result; if(verbose && r != OK)
if(verbose && result != OK)
printf("IPC: error for %d: %d\n", printf("IPC: error for %d: %d\n",
call_type, result); call_type, r);
if ((r = ipc_sendnb(who_e, &m)) != OK) if ((r = ipc_sendnb(who_e, &m)) != OK)
printf("IPC send error %d.\n", r); printf("IPC send error %d.\n", r);
@ -117,7 +98,7 @@ int main(int argc, char *argv[])
/*===========================================================================* /*===========================================================================*
* sef_local_startup * * sef_local_startup *
*===========================================================================*/ *===========================================================================*/
static void sef_local_startup() static void sef_local_startup(void)
{ {
/* Register init callbacks. */ /* Register init callbacks. */
sef_setcb_init_fresh(sef_cb_init_fresh); sef_setcb_init_fresh(sef_cb_init_fresh);
@ -152,7 +133,8 @@ static void sef_cb_signal_handler(int signo)
if (signo != SIGTERM) return; if (signo != SIGTERM) return;
/* Checkout if there are still IPC keys. Inform the user in that case. */ /* Checkout if there are still IPC keys. Inform the user in that case. */
if (!is_sem_nil() || !is_shm_nil()) if (is_sem_nil() && is_shm_nil())
sef_exit(0);
printf("IPC: exit with un-clean states.\n"); printf("IPC: exit with un-clean states.\n");
} }

View File

@ -1,7 +1,3 @@
#define __USE_MISC
#include <minix/vm.h>
#include "inc.h" #include "inc.h"
struct waiting { struct waiting {
@ -19,33 +15,43 @@ struct semaphore {
}; };
struct sem_struct { struct sem_struct {
key_t key;
int id;
struct semid_ds semid_ds; struct semid_ds semid_ds;
struct semaphore sems[SEMMSL]; struct semaphore sems[SEMMSL];
}; };
static struct sem_struct sem_list[SEMMNI]; static struct sem_struct sem_list[SEMMNI];
static int sem_list_nr = 0; static unsigned int sem_list_nr = 0; /* highest in-use slot number plus one */
static struct sem_struct *sem_find_key(key_t key) static struct sem_struct *sem_find_key(key_t key)
{ {
int i; unsigned int i;
if (key == IPC_PRIVATE) if (key == IPC_PRIVATE)
return NULL; return NULL;
for (i = 0; i < sem_list_nr; i++) for (i = 0; i < sem_list_nr; i++) {
if (sem_list[i].key == key) if (!(sem_list[i].semid_ds.sem_perm.mode & SEM_ALLOC))
return sem_list+i; continue;
if (sem_list[i].semid_ds.sem_perm._key == key)
return &sem_list[i];
}
return NULL; return NULL;
} }
static struct sem_struct *sem_find_id(int id) static struct sem_struct *sem_find_id(int id)
{ {
int i; struct sem_struct *sem;
for (i = 0; i < sem_list_nr; i++) unsigned int i;
if (sem_list[i].id == id)
return sem_list+i; i = IPCID_TO_IX(id);
if (i >= sem_list_nr)
return NULL; return NULL;
sem = &sem_list[i];
if (!(sem->semid_ds.sem_perm.mode & SEM_ALLOC))
return NULL;
if (sem->semid_ds.sem_perm._seq != IPCID_TO_SEQ(id))
return NULL;
return sem;
} }
/*===========================================================================* /*===========================================================================*
@ -53,9 +59,10 @@ static struct sem_struct *sem_find_id(int id)
*===========================================================================*/ *===========================================================================*/
int do_semget(message *m) int do_semget(message *m)
{ {
key_t key;
int nsems, flag, id;
struct sem_struct *sem; struct sem_struct *sem;
unsigned int i, seq;
key_t key;
int nsems, flag;
key = m->m_lc_ipc_semget.key; key = m->m_lc_ipc_semget.key;
nsems = m->m_lc_ipc_semget.nr; nsems = m->m_lc_ipc_semget.nr;
@ -68,33 +75,41 @@ int do_semget(message *m)
return EACCES; return EACCES;
if (nsems > sem->semid_ds.sem_nsems) if (nsems > sem->semid_ds.sem_nsems)
return EINVAL; return EINVAL;
id = sem->id; i = sem - sem_list;
} else { } else {
if (!(flag & IPC_CREAT)) if (!(flag & IPC_CREAT))
return ENOENT; return ENOENT;
if (nsems < 0 || nsems >= SEMMSL) if (nsems < 0 || nsems >= SEMMSL)
return EINVAL; return EINVAL;
if (sem_list_nr == SEMMNI)
/* Find a free entry. */
for (i = 0; i < __arraycount(sem_list); i++)
if (!(sem_list[i].semid_ds.sem_perm.mode & SEM_ALLOC))
break;
if (i == __arraycount(sem_list))
return ENOSPC; return ENOSPC;
/* create a new semaphore set */ /* Initialize the entry. */
sem = &sem_list[sem_list_nr]; sem = &sem_list[i];
seq = sem->semid_ds.sem_perm._seq;
memset(sem, 0, sizeof(struct sem_struct)); memset(sem, 0, sizeof(struct sem_struct));
sem->semid_ds.sem_perm._key = key;
sem->semid_ds.sem_perm.cuid = sem->semid_ds.sem_perm.cuid =
sem->semid_ds.sem_perm.uid = getnuid(who_e); sem->semid_ds.sem_perm.uid = getnuid(who_e);
sem->semid_ds.sem_perm.cgid = sem->semid_ds.sem_perm.cgid =
sem->semid_ds.sem_perm.gid = getngid(who_e); sem->semid_ds.sem_perm.gid = getngid(who_e);
sem->semid_ds.sem_perm.mode = flag & 0777; sem->semid_ds.sem_perm.mode = SEM_ALLOC | (flag & ACCESSPERMS);
sem->semid_ds.sem_perm._seq = (seq + 1) & 0x7fff;
sem->semid_ds.sem_nsems = nsems; sem->semid_ds.sem_nsems = nsems;
sem->semid_ds.sem_otime = 0; sem->semid_ds.sem_otime = 0;
sem->semid_ds.sem_ctime = time(NULL); sem->semid_ds.sem_ctime = clock_time(NULL);
sem->id = id = identifier++;
sem->key = key;
assert(i <= sem_list_nr);
if (i == sem_list_nr)
sem_list_nr++; sem_list_nr++;
} }
m->m_lc_ipc_semget.retid = id; m->m_lc_ipc_semget.retid = IXSEQ_TO_IPCID(i, sem->semid_ds.sem_perm);
return OK; return OK;
} }
@ -119,22 +134,29 @@ static void remove_semaphore(struct sem_struct *sem)
free(sem->sems[i].nlist); free(sem->sems[i].nlist);
} }
for (i = 0; i < sem_list_nr; i++) { /* Mark the entry as free. */
if (&sem_list[i] == sem) sem->semid_ds.sem_perm.mode &= ~SEM_ALLOC;
break;
}
if (i < sem_list_nr && --sem_list_nr != i) /*
sem_list[i] = sem_list[sem_list_nr]; * This may have been the last in-use slot in the list. Ensure that
* sem_list_nr again equals the highest in-use slot number plus one.
*/
while (sem_list_nr > 0 &&
!(sem_list[sem_list_nr - 1].semid_ds.sem_perm.mode & SEM_ALLOC))
sem_list_nr--;
} }
#if 0 #if 0
static void show_semaphore(void) static void show_semaphore(void)
{ {
int i, j, k; unsigned int i;
int j, k, nr;
for (i = 0; i < sem_list_nr; i++) { for (i = 0; i < sem_list_nr; i++) {
int nr = sem_list[i].semid_ds.sem_nsems; if (!(sem_list[i].semid_ds.sem_perm.mode & SEM_ALLOC))
continue;
nr = sem_list[i].semid_ds.sem_nsems;
printf("===== [%d] =====\n", i); printf("===== [%d] =====\n", i);
for (j = 0; j < nr; j++) { for (j = 0; j < nr; j++) {
@ -166,13 +188,16 @@ static void show_semaphore(void)
static void remove_process(endpoint_t pt) static void remove_process(endpoint_t pt)
{ {
int i; struct sem_struct *sem;
unsigned int i;
int j, nr;
for (i = 0; i < sem_list_nr; i++) { for (i = 0; i < sem_list_nr; i++) {
struct sem_struct *sem = &sem_list[i]; sem = &sem_list[i];
int nr = sem->semid_ds.sem_nsems; if (!(sem->semid_ds.sem_perm.mode & SEM_ALLOC))
int j; continue;
nr = sem->semid_ds.sem_nsems;
for (j = 0; j < nr; j++) { for (j = 0; j < nr; j++) {
struct semaphore *semaphore = &sem->sems[j]; struct semaphore *semaphore = &sem->sems[j];
int k; int k;
@ -268,10 +293,13 @@ static void update_one_semaphore(struct sem_struct *sem, int is_remove)
static void update_semaphores(void) static void update_semaphores(void)
{ {
int i; unsigned int i;
for (i = 0; i < sem_list_nr; i++) for (i = 0; i < sem_list_nr; i++) {
update_one_semaphore(sem_list+i, 0 /* not remove */); if (!(sem_list[i].semid_ds.sem_perm.mode & SEM_ALLOC))
continue;
update_one_semaphore(&sem_list[i], FALSE /*is_remove*/);
}
} }
/*===========================================================================* /*===========================================================================*
@ -279,10 +307,10 @@ static void update_semaphores(void)
*===========================================================================*/ *===========================================================================*/
int do_semctl(message *m) int do_semctl(message *m)
{ {
int r, i; unsigned int i;
long opt = 0; vir_bytes opt;
uid_t uid; uid_t uid;
int id, num, cmd, val; int r, id, num, cmd, val;
unsigned short *buf; unsigned short *buf;
struct semid_ds *ds, tmp_ds; struct semid_ds *ds, tmp_ds;
struct sem_struct *sem; struct sem_struct *sem;
@ -291,10 +319,6 @@ int do_semctl(message *m)
id = m->m_lc_ipc_semctl.id; id = m->m_lc_ipc_semctl.id;
num = m->m_lc_ipc_semctl.num; num = m->m_lc_ipc_semctl.num;
cmd = m->m_lc_ipc_semctl.cmd; cmd = m->m_lc_ipc_semctl.cmd;
if (cmd == IPC_STAT || cmd == IPC_SET || cmd == IPC_INFO ||
cmd == SEM_INFO || cmd == SEM_STAT || cmd == GETALL ||
cmd == SETALL || cmd == SETVAL)
opt = m->m_lc_ipc_semctl.opt; opt = m->m_lc_ipc_semctl.opt;
switch (cmd) { switch (cmd) {
@ -303,13 +327,16 @@ int do_semctl(message *m)
sem = NULL; sem = NULL;
break; break;
case SEM_STAT: case SEM_STAT:
if (id < 0 || id >= sem_list_nr) if (id < 0 || (unsigned int)id >= sem_list_nr)
return EINVAL; return EINVAL;
sem = &sem_list[id]; sem = &sem_list[id];
if (!(sem->semid_ds.sem_perm.mode & SEM_ALLOC))
return EINVAL;
break; break;
default: default:
if (!(sem = sem_find_id(id))) if (!(sem = sem_find_id(id)))
return EINVAL; return EINVAL;
break;
} }
/* IPC_SET and IPC_RMID as its own permission check */ /* IPC_SET and IPC_RMID as its own permission check */
@ -325,7 +352,9 @@ int do_semctl(message *m)
if ((r = sys_datacopy(SELF, (vir_bytes)&sem->semid_ds, who_e, if ((r = sys_datacopy(SELF, (vir_bytes)&sem->semid_ds, who_e,
(vir_bytes)opt, sizeof(sem->semid_ds))) != OK) (vir_bytes)opt, sizeof(sem->semid_ds))) != OK)
return r; return r;
m->m_lc_ipc_semctl.ret = sem->id; if (cmd == SEM_STAT)
m->m_lc_ipc_semctl.ret =
IXSEQ_TO_IPCID(id, sem->semid_ds.sem_perm);
break; break;
case IPC_SET: case IPC_SET:
uid = getnuid(who_e); uid = getnuid(who_e);
@ -334,15 +363,15 @@ int do_semctl(message *m)
uid != 0) uid != 0)
return EPERM; return EPERM;
ds = (struct semid_ds *) opt; ds = (struct semid_ds *) opt;
r = sys_datacopy(who_e, (vir_bytes) ds, if ((r = sys_datacopy(who_e, (vir_bytes)ds, SELF,
SELF, (vir_bytes) &tmp_ds, sizeof(struct semid_ds)); (vir_bytes)&tmp_ds, sizeof(struct semid_ds))) != OK)
if (r != OK) return r;
return EINVAL;
sem->semid_ds.sem_perm.uid = tmp_ds.sem_perm.uid; sem->semid_ds.sem_perm.uid = tmp_ds.sem_perm.uid;
sem->semid_ds.sem_perm.gid = tmp_ds.sem_perm.gid; sem->semid_ds.sem_perm.gid = tmp_ds.sem_perm.gid;
sem->semid_ds.sem_perm.mode &= ~0777; sem->semid_ds.sem_perm.mode &= ~ACCESSPERMS;
sem->semid_ds.sem_perm.mode |= tmp_ds.sem_perm.mode & 0666; sem->semid_ds.sem_perm.mode |=
sem->semid_ds.sem_ctime = time(NULL); tmp_ds.sem_perm.mode & ACCESSPERMS;
sem->semid_ds.sem_ctime = clock_time(NULL);
break; break;
case IPC_RMID: case IPC_RMID:
uid = getnuid(who_e); uid = getnuid(who_e);
@ -353,7 +382,7 @@ int do_semctl(message *m)
/* awaken all processes block in semop /* awaken all processes block in semop
* and remove the semaphore set. * and remove the semaphore set.
*/ */
update_one_semaphore(sem, 1); update_one_semaphore(sem, TRUE /*is_remove*/);
break; break;
case IPC_INFO: case IPC_INFO:
case SEM_INFO: case SEM_INFO:
@ -395,16 +424,15 @@ int do_semctl(message *m)
break; break;
case GETALL: case GETALL:
buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems); buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems);
if (!buf) if (buf == NULL)
return ENOMEM; return ENOMEM;
for (i = 0; i < sem->semid_ds.sem_nsems; i++) for (i = 0; i < sem->semid_ds.sem_nsems; i++)
buf[i] = sem->sems[i].semval; buf[i] = sem->sems[i].semval;
r = sys_datacopy(SELF, (vir_bytes) buf, r = sys_datacopy(SELF, (vir_bytes)buf, who_e, (vir_bytes)opt,
who_e, (vir_bytes) opt,
sizeof(unsigned short) * sem->semid_ds.sem_nsems); sizeof(unsigned short) * sem->semid_ds.sem_nsems);
free(buf);
if (r != OK) if (r != OK)
return EINVAL; return EINVAL;
free(buf);
break; break;
case GETNCNT: case GETNCNT:
if (num < 0 || num >= sem->semid_ds.sem_nsems) if (num < 0 || num >= sem->semid_ds.sem_nsems)
@ -428,13 +456,14 @@ int do_semctl(message *m)
break; break;
case SETALL: case SETALL:
buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems); buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems);
if (!buf) if (buf == NULL)
return ENOMEM; return ENOMEM;
r = sys_datacopy(who_e, (vir_bytes) opt, r = sys_datacopy(who_e, (vir_bytes)opt, SELF, (vir_bytes)buf,
SELF, (vir_bytes) buf,
sizeof(unsigned short) * sem->semid_ds.sem_nsems); sizeof(unsigned short) * sem->semid_ds.sem_nsems);
if (r != OK) if (r != OK) {
free(buf);
return EINVAL; return EINVAL;
}
#ifdef DEBUG_SEM #ifdef DEBUG_SEM
printf("SEMCTL: SETALL: opt: %lu\n", (vir_bytes) opt); printf("SEMCTL: SETALL: opt: %lu\n", (vir_bytes) opt);
for (i = 0; i < sem->semid_ds.sem_nsems; i++) for (i = 0; i < sem->semid_ds.sem_nsems; i++)
@ -465,7 +494,7 @@ int do_semctl(message *m)
#ifdef DEBUG_SEM #ifdef DEBUG_SEM
printf("SEMCTL: SETVAL: %d %d\n", num, val); printf("SEMCTL: SETVAL: %d %d\n", num, val);
#endif #endif
sem->semid_ds.sem_ctime = time(NULL); sem->semid_ds.sem_ctime = clock_time(NULL);
/* awaken if possible */ /* awaken if possible */
update_semaphores(); update_semaphores();
break; break;
@ -481,7 +510,8 @@ int do_semctl(message *m)
*===========================================================================*/ *===========================================================================*/
int do_semop(message *m) int do_semop(message *m)
{ {
int id, i, j, r; unsigned int i, j, mask;
int id, r;
struct sembuf *sops; struct sembuf *sops;
unsigned int nsops; unsigned int nsops;
struct sem_struct *sem; struct sem_struct *sem;
@ -490,34 +520,23 @@ int do_semop(message *m)
id = m->m_lc_ipc_semop.id; id = m->m_lc_ipc_semop.id;
nsops = m->m_lc_ipc_semop.size; nsops = m->m_lc_ipc_semop.size;
r = EINVAL;
if (!(sem = sem_find_id(id))) if (!(sem = sem_find_id(id)))
goto out; return EINVAL;
if (nsops <= 0) if (nsops <= 0)
goto out; return EINVAL;
r = E2BIG;
if (nsops > SEMOPM) if (nsops > SEMOPM)
goto out; return E2BIG;
/* check for read permission */
r = EACCES;
if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0444))
goto out;
/* get the array from user application */ /* get the array from user application */
r = ENOMEM;
sops = malloc(sizeof(struct sembuf) * nsops); sops = malloc(sizeof(struct sembuf) * nsops);
if (!sops) if (!sops)
goto out_free; return ENOMEM;
r = sys_datacopy(who_e, (vir_bytes) m->m_lc_ipc_semop.ops, r = sys_datacopy(who_e, (vir_bytes) m->m_lc_ipc_semop.ops,
SELF, (vir_bytes) sops, SELF, (vir_bytes) sops,
sizeof(struct sembuf) * nsops); sizeof(struct sembuf) * nsops);
if (r != OK) { if (r != OK)
r = EINVAL;
goto out_free; goto out_free;
}
#ifdef DEBUG_SEM #ifdef DEBUG_SEM
for (i = 0; i < nsops; i++) for (i = 0; i < nsops; i++)
@ -530,6 +549,18 @@ int do_semop(message *m)
if (sops[i].sem_num >= sem->semid_ds.sem_nsems) if (sops[i].sem_num >= sem->semid_ds.sem_nsems)
goto out_free; goto out_free;
/* check for permissions */
r = EACCES;
mask = 0;
for (i = 0; i < nsops; i++) {
if (sops[i].sem_op != 0)
mask |= 0222; /* check for write permission */
else
mask |= 0444; /* check for read permission */
}
if (mask && !check_perm(&sem->semid_ds.sem_perm, who_e, mask))
goto out_free;
/* check for duplicate number */ /* check for duplicate number */
r = EINVAL; r = EINVAL;
for (i = 0; i < nsops; i++) for (i = 0; i < nsops; i++)
@ -537,7 +568,7 @@ int do_semop(message *m)
if (sops[i].sem_num == sops[j].sem_num) if (sops[i].sem_num == sops[j].sem_num)
goto out_free; goto out_free;
/* check for EAGAIN error */ /* check for nonblocking operations */
r = EAGAIN; r = EAGAIN;
for (i = 0; i < nsops; i++) { for (i = 0; i < nsops; i++) {
int op_n, val; int op_n, val;
@ -550,8 +581,8 @@ int do_semop(message *m)
(op_n < 0 && (op_n < 0 &&
-op_n > val))) -op_n > val)))
goto out_free; goto out_free;
} }
/* there will be no errors left, so we can go ahead */ /* there will be no errors left, so we can go ahead */
for (i = 0; i < nsops; i++) { for (i = 0; i < nsops; i++) {
struct semaphore *s; struct semaphore *s;
@ -563,20 +594,16 @@ int do_semop(message *m)
s->sempid = getnpid(who_e); s->sempid = getnpid(who_e);
if (op_n > 0) { if (op_n > 0) {
/* check for alter permission */
r = EACCES;
if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0222))
goto out_free;
s->semval += sops[i].sem_op; s->semval += sops[i].sem_op;
} else if (!op_n) { } else if (!op_n) {
if (s->semval) { if (s->semval) {
/* put the process asleep */ /* put the process asleep */
s->semzcnt++; s->semzcnt++;
s->zlist = realloc(s->zlist, sizeof(struct waiting) * s->semzcnt); s->zlist = realloc(s->zlist,
if (!s->zlist) { sizeof(struct waiting) * s->semzcnt);
printf("IPC: zero waiting list lost...\n"); /* continuing if NULL would lead to disaster */
break; if (s->zlist == NULL)
} panic("out of memory");
s->zlist[s->semzcnt-1].who = who_e; s->zlist[s->semzcnt-1].who = who_e;
s->zlist[s->semzcnt-1].val = op_n; s->zlist[s->semzcnt-1].val = op_n;
@ -586,20 +613,16 @@ int do_semop(message *m)
no_reply++; no_reply++;
} }
} else { } else {
/* check for alter permission */
r = EACCES;
if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0222))
goto out_free;
if (s->semval >= -op_n) if (s->semval >= -op_n)
s->semval += op_n; s->semval += op_n;
else { else {
/* put the process asleep */ /* put the process asleep */
s->semncnt++; s->semncnt++;
s->nlist = realloc(s->nlist, sizeof(struct waiting) * s->semncnt); s->nlist = realloc(s->nlist,
if (!s->nlist) { sizeof(struct waiting) * s->semncnt);
printf("IPC: increase waiting list lost...\n"); /* continuing if NULL would lead to disaster */
break; if (s->nlist == NULL)
} panic("out of memory");
s->nlist[s->semncnt-1].who = who_e; s->nlist[s->semncnt-1].who = who_e;
s->nlist[s->semncnt-1].val = -op_n; s->nlist[s->semncnt-1].val = -op_n;
@ -608,23 +631,14 @@ int do_semop(message *m)
} }
} }
r = OK; r = no_reply ? SUSPEND : OK;
out_free: out_free:
free(sops); free(sops);
out:
/* if we reach here by errors
* or with no errors but we should reply back.
*/
if (r != OK || !no_reply) {
m->m_type = r;
ipc_sendnb(who_e, m);
}
/* awaken process if possible */ /* awaken process if possible */
update_semaphores(); update_semaphores();
return 0; return r;
} }
/*===========================================================================* /*===========================================================================*

View File

@ -1,35 +1,46 @@
#include "inc.h" #include "inc.h"
#define MAX_SHM_NR 1024 /* Private shm_perm.mode flags, synchronized with NetBSD kernel values */
#define SHM_ALLOC 0x0800 /* slot is in use (SHMSEG_ALLOCATED) */
struct shm_struct { struct shm_struct {
key_t key;
int id;
struct shmid_ds shmid_ds; struct shmid_ds shmid_ds;
vir_bytes page; vir_bytes page;
int vm_id; phys_bytes vm_id;
}; };
static struct shm_struct shm_list[MAX_SHM_NR]; static struct shm_struct shm_list[SHMMNI];
static int shm_list_nr = 0; static unsigned int shm_list_nr = 0; /* highest in-use slot number plus one */
static struct shm_struct *shm_find_key(key_t key) static struct shm_struct *shm_find_key(key_t key)
{ {
int i; unsigned int i;
if (key == IPC_PRIVATE) if (key == IPC_PRIVATE)
return NULL; return NULL;
for (i = 0; i < shm_list_nr; i++) for (i = 0; i < shm_list_nr; i++) {
if (shm_list[i].key == key) if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
return shm_list+i; continue;
if (shm_list[i].shmid_ds.shm_perm._key == key)
return &shm_list[i];
}
return NULL; return NULL;
} }
static struct shm_struct *shm_find_id(int id) static struct shm_struct *shm_find_id(int id)
{ {
int i; struct shm_struct *shm;
for (i = 0; i < shm_list_nr; i++) unsigned int i;
if (shm_list[i].id == id)
return shm_list+i; i = IPCID_TO_IX(id);
if (i >= shm_list_nr)
return NULL; return NULL;
shm = &shm_list[i];
if (!(shm->shmid_ds.shm_perm.mode & SHM_ALLOC))
return NULL;
if (shm->shmid_ds.shm_perm._seq != IPCID_TO_SEQ(id))
return NULL;
return shm;
} }
/*===========================================================================* /*===========================================================================*
@ -38,9 +49,11 @@ static struct shm_struct *shm_find_id(int id)
int do_shmget(message *m) int do_shmget(message *m)
{ {
struct shm_struct *shm; struct shm_struct *shm;
long key, size, old_size; unsigned int i, seq;
key_t key;
size_t size, old_size;
int flag; int flag;
int id; void *page;
key = m->m_lc_ipc_shmget.key; key = m->m_lc_ipc_shmget.key;
old_size = size = m->m_lc_ipc_shmget.size; old_size = size = m->m_lc_ipc_shmget.size;
@ -53,7 +66,7 @@ int do_shmget(message *m)
return EEXIST; return EEXIST;
if (size && shm->shmid_ds.shm_segsz < size) if (size && shm->shmid_ds.shm_segsz < size)
return EINVAL; return EINVAL;
id = shm->id; i = shm - shm_list;
} else { /* no key found */ } else { /* no key found */
if (!(flag & IPC_CREAT)) if (!(flag & IPC_CREAT))
return ENOENT; return ENOENT;
@ -65,39 +78,51 @@ int do_shmget(message *m)
if (size <= 0) if (size <= 0)
return EINVAL; return EINVAL;
if (shm_list_nr == MAX_SHM_NR) /* Find a free entry. */
return ENOMEM; for (i = 0; i < __arraycount(shm_list); i++)
/* TODO: shmmni should be changed... */ if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
if (identifier == SHMMNI) break;
if (i == __arraycount(shm_list))
return ENOSPC; return ENOSPC;
shm = &shm_list[shm_list_nr];
memset(shm, 0, sizeof(struct shm_struct));
shm->page = (vir_bytes) mmap(0, size,
PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
if (shm->page == (vir_bytes) MAP_FAILED)
return ENOMEM;
shm->vm_id = vm_getphys(sef_self(), (void *) shm->page);
memset((void *)shm->page, 0, size);
/*
* Allocate memory to share. For now, we store the page
* reference as a numerical value so as to avoid issues with
* live update. TODO: a proper solution.
*/
page = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
if (page == MAP_FAILED)
return ENOMEM;
memset(page, 0, size);
/* Initialize the entry. */
shm = &shm_list[i];
seq = shm->shmid_ds.shm_perm._seq;
memset(shm, 0, sizeof(struct shm_struct));
shm->shmid_ds.shm_perm._key = key;
shm->shmid_ds.shm_perm.cuid = shm->shmid_ds.shm_perm.cuid =
shm->shmid_ds.shm_perm.uid = getnuid(who_e); shm->shmid_ds.shm_perm.uid = getnuid(who_e);
shm->shmid_ds.shm_perm.cgid = shm->shmid_ds.shm_perm.cgid =
shm->shmid_ds.shm_perm.gid = getngid(who_e); shm->shmid_ds.shm_perm.gid = getngid(who_e);
shm->shmid_ds.shm_perm.mode = flag & 0777; shm->shmid_ds.shm_perm.mode = SHM_ALLOC | (flag & ACCESSPERMS);
shm->shmid_ds.shm_perm._seq = (seq + 1) & 0x7fff;
shm->shmid_ds.shm_segsz = old_size; shm->shmid_ds.shm_segsz = old_size;
shm->shmid_ds.shm_atime = 0; shm->shmid_ds.shm_atime = 0;
shm->shmid_ds.shm_dtime = 0; shm->shmid_ds.shm_dtime = 0;
shm->shmid_ds.shm_ctime = time(NULL); shm->shmid_ds.shm_ctime = clock_time(NULL);
shm->shmid_ds.shm_cpid = getnpid(who_e); shm->shmid_ds.shm_cpid = getnpid(who_e);
shm->shmid_ds.shm_lpid = 0; shm->shmid_ds.shm_lpid = 0;
shm->shmid_ds.shm_nattch = 0; shm->shmid_ds.shm_nattch = 0;
shm->id = id = identifier++; shm->page = (vir_bytes)page;
shm->key = key; shm->vm_id = vm_getphys(sef_self(), page);
assert(i <= shm_list_nr);
if (i == shm_list_nr)
shm_list_nr++; shm_list_nr++;
} }
m->m_lc_ipc_shmget.retid = id; m->m_lc_ipc_shmget.retid = IXSEQ_TO_IPCID(i, shm->shmid_ds.shm_perm);
return OK; return OK;
} }
@ -137,7 +162,7 @@ int do_shmat(message *m)
if (ret == MAP_FAILED) if (ret == MAP_FAILED)
return ENOMEM; return ENOMEM;
shm->shmid_ds.shm_atime = time(NULL); shm->shmid_ds.shm_atime = clock_time(NULL);
shm->shmid_ds.shm_lpid = getnpid(who_e); shm->shmid_ds.shm_lpid = getnpid(who_e);
/* nattach is updated lazily */ /* nattach is updated lazily */
@ -150,10 +175,13 @@ int do_shmat(message *m)
*===========================================================================*/ *===========================================================================*/
void update_refcount_and_destroy(void) void update_refcount_and_destroy(void)
{ {
int i, j; size_t size;
for (i = 0, j = 0; i < shm_list_nr; i++) {
u8_t rc; u8_t rc;
unsigned int i;
for (i = 0; i < shm_list_nr; i++) {
if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
continue;
rc = vm_getrefcount(sef_self(), (void *) shm_list[i].page); rc = vm_getrefcount(sef_self(), (void *) shm_list[i].page);
if (rc == (u8_t) -1) { if (rc == (u8_t) -1) {
@ -162,19 +190,24 @@ void update_refcount_and_destroy(void)
} }
shm_list[i].shmid_ds.shm_nattch = rc - 1; shm_list[i].shmid_ds.shm_nattch = rc - 1;
if (shm_list[i].shmid_ds.shm_nattch || if (shm_list[i].shmid_ds.shm_nattch == 0 &&
!(shm_list[i].shmid_ds.shm_perm.mode & SHM_DEST)) { (shm_list[i].shmid_ds.shm_perm.mode & SHM_DEST)) {
if (i != j) size = shm_list[i].shmid_ds.shm_segsz;
shm_list[j] = shm_list[i];
j++;
} else {
int size = shm_list[i].shmid_ds.shm_segsz;
if (size % PAGE_SIZE) if (size % PAGE_SIZE)
size += PAGE_SIZE - size % PAGE_SIZE; size += PAGE_SIZE - size % PAGE_SIZE;
munmap((void *)shm_list[i].page, size); munmap((void *)shm_list[i].page, size);
/* Mark the entry as free. */
shm_list[i].shmid_ds.shm_perm.mode &= ~SHM_ALLOC;
} }
} }
shm_list_nr = j;
/*
* Now that we may have removed an arbitrary set of slots, ensure that
* shm_list_nr again equals the highest in-use slot number plus one.
*/
while (shm_list_nr > 0 &&
!(shm_list[shm_list_nr - 1].shmid_ds.shm_perm.mode & SHM_ALLOC))
shm_list_nr--;
} }
/*===========================================================================* /*===========================================================================*
@ -182,9 +215,10 @@ void update_refcount_and_destroy(void)
*===========================================================================*/ *===========================================================================*/
int do_shmdt(message *m) int do_shmdt(message *m)
{ {
struct shm_struct *shm;
vir_bytes addr; vir_bytes addr;
phys_bytes vm_id; phys_bytes vm_id;
int i; unsigned int i;
addr = (vir_bytes) m->m_lc_ipc_shmdt.addr; addr = (vir_bytes) m->m_lc_ipc_shmdt.addr;
@ -192,10 +226,13 @@ int do_shmdt(message *m)
return EINVAL; return EINVAL;
for (i = 0; i < shm_list_nr; i++) { for (i = 0; i < shm_list_nr; i++) {
if (shm_list[i].vm_id == vm_id) { shm = &shm_list[i];
struct shm_struct *shm = &shm_list[i];
shm->shmid_ds.shm_atime = time(NULL); if (!(shm->shmid_ds.shm_perm.mode & SHM_ALLOC))
continue;
if (shm->vm_id == vm_id) {
shm->shmid_ds.shm_atime = clock_time(NULL);
shm->shmid_ds.shm_lpid = getnpid(who_e); shm->shmid_ds.shm_lpid = getnpid(who_e);
/* nattch is updated lazily */ /* nattch is updated lazily */
@ -217,36 +254,56 @@ int do_shmdt(message *m)
*===========================================================================*/ *===========================================================================*/
int do_shmctl(message *m) int do_shmctl(message *m)
{ {
int id = m->m_lc_ipc_shmctl.id; struct shmid_ds *ds;
int cmd = m->m_lc_ipc_shmctl.cmd;
struct shmid_ds *ds = (struct shmid_ds *)m->m_lc_ipc_shmctl.buf;
struct shmid_ds tmp_ds; struct shmid_ds tmp_ds;
struct shm_struct *shm = NULL; struct shm_struct *shm;
struct shminfo sinfo; struct shminfo sinfo;
struct shm_info s_info; struct shm_info s_info;
unsigned int i;
uid_t uid; uid_t uid;
int r, i; int r, id, cmd;
if (cmd == IPC_STAT) id = m->m_lc_ipc_shmctl.id;
cmd = m->m_lc_ipc_shmctl.cmd;
ds = (struct shmid_ds *)m->m_lc_ipc_shmctl.buf;
/*
* For stat calls, sure that all information is up-to-date. Since this
* may free the slot, do this before mapping from ID to slot below.
*/
if (cmd == IPC_STAT || cmd == SHM_STAT)
update_refcount_and_destroy(); update_refcount_and_destroy();
if ((cmd == IPC_STAT || switch (cmd) {
cmd == IPC_SET || case IPC_INFO:
cmd == IPC_RMID) && case SHM_INFO:
!(shm = shm_find_id(id))) shm = NULL;
break;
case SHM_STAT:
if (id < 0 || (unsigned int)id >= shm_list_nr)
return EINVAL; return EINVAL;
shm = &shm_list[id];
if (!(shm->shmid_ds.shm_perm.mode & SHM_ALLOC))
return EINVAL;
break;
default:
if (!(shm = shm_find_id(id)))
return EINVAL;
break;
}
switch (cmd) { switch (cmd) {
case IPC_STAT: case IPC_STAT:
if (!ds) case SHM_STAT:
return EFAULT; /* Check whether the caller has read permission. */
/* check whether it has read permission */
if (!check_perm(&shm->shmid_ds.shm_perm, who_e, 0444)) if (!check_perm(&shm->shmid_ds.shm_perm, who_e, 0444))
return EACCES; return EACCES;
r = sys_datacopy(SELF, (vir_bytes)&shm->shmid_ds, if ((r = sys_datacopy(SELF, (vir_bytes)&shm->shmid_ds, who_e,
who_e, (vir_bytes)ds, sizeof(struct shmid_ds)); (vir_bytes)ds, sizeof(struct shmid_ds))) != OK)
if (r != OK) return r;
return EFAULT; if (cmd == SHM_STAT)
m->m_lc_ipc_shmctl.ret =
IXSEQ_TO_IPCID(id, shm->shmid_ds.shm_perm);
break; break;
case IPC_SET: case IPC_SET:
uid = getnuid(who_e); uid = getnuid(who_e);
@ -254,15 +311,15 @@ int do_shmctl(message *m)
uid != shm->shmid_ds.shm_perm.uid && uid != shm->shmid_ds.shm_perm.uid &&
uid != 0) uid != 0)
return EPERM; return EPERM;
r = sys_datacopy(who_e, (vir_bytes)ds, if ((r = sys_datacopy(who_e, (vir_bytes)ds, SELF,
SELF, (vir_bytes)&tmp_ds, sizeof(struct shmid_ds)); (vir_bytes)&tmp_ds, sizeof(struct shmid_ds))) != OK)
if (r != OK) return r;
return EFAULT;
shm->shmid_ds.shm_perm.uid = tmp_ds.shm_perm.uid; shm->shmid_ds.shm_perm.uid = tmp_ds.shm_perm.uid;
shm->shmid_ds.shm_perm.gid = tmp_ds.shm_perm.gid; shm->shmid_ds.shm_perm.gid = tmp_ds.shm_perm.gid;
shm->shmid_ds.shm_perm.mode &= ~0777; shm->shmid_ds.shm_perm.mode &= ~ACCESSPERMS;
shm->shmid_ds.shm_perm.mode |= tmp_ds.shm_perm.mode & 0666; shm->shmid_ds.shm_perm.mode |=
shm->shmid_ds.shm_ctime = time(NULL); tmp_ds.shm_perm.mode & ACCESSPERMS;
shm->shmid_ds.shm_ctime = clock_time(NULL);
break; break;
case IPC_RMID: case IPC_RMID:
uid = getnuid(who_e); uid = getnuid(who_e);
@ -275,24 +332,22 @@ int do_shmctl(message *m)
update_refcount_and_destroy(); update_refcount_and_destroy();
break; break;
case IPC_INFO: case IPC_INFO:
if (!ds) memset(&sinfo, 0, sizeof(sinfo));
return EFAULT;
sinfo.shmmax = (unsigned long) -1; sinfo.shmmax = (unsigned long) -1;
sinfo.shmmin = 1; sinfo.shmmin = 1;
sinfo.shmmni = MAX_SHM_NR; sinfo.shmmni = __arraycount(shm_list);
sinfo.shmseg = (unsigned long) -1; sinfo.shmseg = (unsigned long) -1;
sinfo.shmall = (unsigned long) -1; sinfo.shmall = (unsigned long) -1;
r = sys_datacopy(SELF, (vir_bytes)&sinfo, if ((r = sys_datacopy(SELF, (vir_bytes)&sinfo, who_e,
who_e, (vir_bytes)ds, sizeof(struct shminfo)); (vir_bytes)ds, sizeof(sinfo))) != OK)
if (r != OK) return r;
return EFAULT; if (shm_list_nr > 0)
m->m_lc_ipc_shmctl.ret = (shm_list_nr - 1); m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
if (m->m_lc_ipc_shmctl.ret < 0) else
m->m_lc_ipc_shmctl.ret = 0; m->m_lc_ipc_shmctl.ret = 0;
break; break;
case SHM_INFO: case SHM_INFO:
if (!ds) memset(&s_info, 0, sizeof(s_info));
return EFAULT;
s_info.used_ids = shm_list_nr; s_info.used_ids = shm_list_nr;
s_info.shm_tot = 0; s_info.shm_tot = 0;
for (i = 0; i < shm_list_nr; i++) for (i = 0; i < shm_list_nr; i++)
@ -302,24 +357,14 @@ int do_shmctl(message *m)
s_info.shm_swp = 0; s_info.shm_swp = 0;
s_info.swap_attempts = 0; s_info.swap_attempts = 0;
s_info.swap_successes = 0; s_info.swap_successes = 0;
r = sys_datacopy(SELF, (vir_bytes)&s_info, if ((r = sys_datacopy(SELF, (vir_bytes)&s_info, who_e,
who_e, (vir_bytes)ds, sizeof(struct shm_info)); (vir_bytes)ds, sizeof(s_info))) != OK)
if (r != OK) return r;
return EFAULT; if (shm_list_nr > 0)
m->m_lc_ipc_shmctl.ret = shm_list_nr - 1; m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
if (m->m_lc_ipc_shmctl.ret < 0) else
m->m_lc_ipc_shmctl.ret = 0; m->m_lc_ipc_shmctl.ret = 0;
break; break;
case SHM_STAT:
if (id < 0 || id >= shm_list_nr)
return EINVAL;
shm = &shm_list[id];
r = sys_datacopy(SELF, (vir_bytes)&shm->shmid_ds,
who_e, (vir_bytes)ds, sizeof(struct shmid_ds));
if (r != OK)
return EFAULT;
m->m_lc_ipc_shmctl.ret = shm->id;
break;
default: default:
return EINVAL; return EINVAL;
} }
@ -329,13 +374,16 @@ int do_shmctl(message *m)
#if 0 #if 0
static void list_shm_ds(void) static void list_shm_ds(void)
{ {
int i; unsigned int i;
printf("key\tid\tpage\n"); printf("key\tid\tpage\n");
for (i = 0; i < shm_list_nr; i++) for (i = 0; i < shm_list_nr; i++) {
if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
continue;
printf("%ld\t%d\t%lx\n", printf("%ld\t%d\t%lx\n",
shm_list[i].key, shm_list[i].shmid_ds.shm_perm._key,
shm_list[i].id, IXSEQ_TO_IPCID(i, shm_list[i].shmid_ds.shm_perm),
shm_list[i].page); shm_list[i].page);
}
} }
#endif #endif

View File

@ -326,7 +326,7 @@ ipc_semctl_out(struct trace_proc * proc, const message * m_out)
return CT_DONE; return CT_DONE;
case SETVAL: case SETVAL:
put_value(proc, "val", "%d", m_out->m_lc_ipc_semctl.opt); put_value(proc, "val", "%lu", m_out->m_lc_ipc_semctl.opt);
return CT_DONE; return CT_DONE;

View File

@ -187,11 +187,13 @@ struct sem_sysctl_info {
/* actual size of an undo structure */ /* actual size of an undo structure */
#define SEMUSZ (sizeof(struct sem_undo)+sizeof(struct sem_undo_entry)*SEMUME) #define SEMUSZ (sizeof(struct sem_undo)+sizeof(struct sem_undo_entry)*SEMUME)
#ifndef __minix
/* /*
* Structures allocated in machdep.c * Structures allocated in machdep.c
*/ */
extern struct seminfo seminfo; extern struct seminfo seminfo;
extern struct semid_ds *sema; /* semaphore id pool */ extern struct semid_ds *sema; /* semaphore id pool */
#endif /* !__minix */
/* /*
* Parameters to the semconfig system call * Parameters to the semconfig system call

View File

@ -215,12 +215,12 @@ struct shm_info
unsigned long int swap_successes; unsigned long int swap_successes;
}; };
#define SHMMNI 4096 #define SHMMNI 1024
#define SHMSEG 32 /* max shared segs per process */ #define SHMSEG 32 /* max shared segs per process */
/* shm_mode upper byte flags */ /* Public shm_perm.mode flags, synchronized with NetBSD kernel values above */
#define SHM_DEST 01000 /* segment will be destroyed on last detach */ #define SHM_DEST 0x0400 /* destroy on last detach (SHMSEG_REMOVED) */
#define SHM_LOCKED 02000 /* segment will not be swapped */ #define SHM_LOCKED 0x4000 /* pages will not be swapped (SHMSEG_WIRED) */
#endif /* defined(__minix) */ #endif /* defined(__minix) */