IPC server: expose semaphore information

Specifically, add support for the IPC_INFO, SEM_INFO, and SEM_STAT
semctl(2) operations, similar to how information about shared memory
is already exposed as well.  The MINIX3 ipcs(1) utility already had
support for these operations, and can now actually use them, too.

Change-Id: Ice5a02e729bf6df6aa8fab76e854808adc04dae3
This commit is contained in:
David van Moolenbroek 2015-11-23 23:25:27 +00:00 committed by Lionel Sambuc
parent 9d796422b1
commit 58c1923c9f

View File

@ -286,6 +286,7 @@ int do_semctl(message *m)
unsigned short *buf;
struct semid_ds *ds, tmp_ds;
struct sem_struct *sem;
struct seminfo sinfo;
id = m->m_lc_ipc_semctl.id;
num = m->m_lc_ipc_semctl.num;
@ -296,12 +297,23 @@ int do_semctl(message *m)
cmd == SETALL || cmd == SETVAL)
opt = m->m_lc_ipc_semctl.opt;
if (!(sem = sem_find_id(id))) {
return EINVAL;
switch (cmd) {
case IPC_INFO:
case SEM_INFO:
sem = NULL;
break;
case SEM_STAT:
if (id < 0 || id >= sem_list_nr)
return EINVAL;
sem = &sem_list[id];
break;
default:
if (!(sem = sem_find_id(id)))
return EINVAL;
}
/* IPC_SET and IPC_RMID as its own permission check */
if (cmd != IPC_SET && cmd != IPC_RMID) {
if (sem != NULL && cmd != IPC_SET && cmd != IPC_RMID) {
/* check read permission */
if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0444))
return EACCES;
@ -309,13 +321,11 @@ int do_semctl(message *m)
switch (cmd) {
case IPC_STAT:
ds = (struct semid_ds *) opt;
if (!ds)
return EFAULT;
r = sys_datacopy(SELF, (vir_bytes) &sem->semid_ds,
who_e, (vir_bytes) ds, sizeof(struct semid_ds));
if (r != OK)
return EINVAL;
case SEM_STAT:
if ((r = sys_datacopy(SELF, (vir_bytes)&sem->semid_ds, who_e,
(vir_bytes)opt, sizeof(sem->semid_ds))) != OK)
return r;
m->m_lc_ipc_semctl.ret = sem->id;
break;
case IPC_SET:
uid = getnuid(who_e);
@ -346,10 +356,42 @@ int do_semctl(message *m)
update_one_semaphore(sem, 1);
break;
case IPC_INFO:
break;
case SEM_INFO:
break;
case SEM_STAT:
memset(&sinfo, 0, sizeof(sinfo));
sinfo.semmap = SEMMNI;
sinfo.semmni = SEMMNI;
sinfo.semmns = SEMMNI * SEMMSL;
sinfo.semmnu = 0; /* TODO: support for SEM_UNDO */
sinfo.semmsl = SEMMSL;
sinfo.semopm = SEMOPM;
sinfo.semume = 0; /* TODO: support for SEM_UNDO */
if (cmd == SEM_INFO) {
/*
* For SEM_INFO the semusz field is expected to contain
* the number of semaphore sets currently in use.
*/
sinfo.semusz = sem_list_nr;
} else
sinfo.semusz = 0; /* TODO: support for SEM_UNDO */
sinfo.semvmx = SEMVMX;
if (cmd == SEM_INFO) {
/*
* For SEM_INFO the semaem field is expected to contain
* the total number of allocated semaphores.
*/
for (i = 0; i < sem_list_nr; i++)
sinfo.semaem += sem_list[i].semid_ds.sem_nsems;
} else
sinfo.semaem = 0; /* TODO: support for SEM_UNDO */
if ((r = sys_datacopy(SELF, (vir_bytes)&sinfo, who_e,
(vir_bytes)opt, sizeof(sinfo))) != OK)
return r;
/* Return the highest in-use slot number if any, or zero. */
if (sem_list_nr > 0)
m->m_lc_ipc_semctl.ret = sem_list_nr - 1;
else
m->m_lc_ipc_semctl.ret = 0;
break;
case GETALL:
buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems);