#include "inc.h"
-endpoint_t who_e;
-static unsigned int call_type;
-
+/*
+ * The call table for this service.
+ */
#define CALL(n) [((n) - IPC_BASE)]
static int (* const call_vec[])(message *) = {
CALL(IPC_SHMGET) = do_shmget,
static int verbose = 0;
-/* SEF functions and variables. */
-static void sef_local_startup(void);
-static int sef_cb_init_fresh(int type, sef_init_info_t *info);
-static void sef_cb_signal_handler(int signo);
+/*
+ * Initialize the IPC server.
+ */
+static int
+sef_cb_init_fresh(int type __unused, sef_init_info_t * info __unused)
+{
+
+ return OK;
+}
+
+static void
+sef_cb_signal_handler(int signo)
+{
+
+ /* Only check for termination signal, ignore anything else. */
+ if (signo != SIGTERM) return;
+
+ /*
+ * Check if there are still IPC keys around. If not, we can safely
+ * exit immediately. Otherwise, warn the system administrator.
+ */
+ if (is_sem_nil() && is_shm_nil())
+ sef_exit(0);
+
+ printf("IPC: exit with unclean state\n");
+}
-int main(int argc, char *argv[])
+static void
+sef_local_startup(void)
+{
+
+ /* Register init callbacks. */
+ sef_setcb_init_fresh(sef_cb_init_fresh);
+ sef_setcb_init_restart(sef_cb_init_fresh);
+
+ /* Register signal callbacks. */
+ sef_setcb_signal_handler(sef_cb_signal_handler);
+
+ /* Let SEF perform startup. */
+ sef_startup();
+}
+
+int
+main(int argc, char ** argv)
{
message m;
- unsigned int ipc_number;
- int r;
+ unsigned int call_index;
+ int r, ipc_status;
/* SEF local startup. */
env_setargs(argc, argv);
sef_local_startup();
- while (TRUE) {
- if ((r = sef_receive(ANY, &m)) != OK)
- printf("sef_receive failed %d.\n", r);
- who_e = m.m_source;
- call_type = m.m_type;
+ /* The main message loop. */
+ for (;;) {
+ if ((r = sef_receive_status(ANY, &m, &ipc_status)) != OK)
+ panic("IPC: sef_receive_status failed: %d", r);
- if(verbose)
- printf("IPC: get %d from %d\n", call_type, who_e);
+ if (verbose)
+ printf("IPC: got %d from %d\n", m.m_type, m.m_source);
- if (call_type & NOTIFY_MESSAGE) {
- switch (who_e) {
+ if (is_ipc_notify(ipc_status)) {
+ switch (m.m_source) {
case VM_PROC_NR:
- /* currently, only semaphore needs such information. */
+ /*
+ * Currently, only semaphore handling needs
+ * to know about processes exiting.
+ */
sem_process_vm_notify();
break;
default:
- printf("IPC: ignoring notify() from %d\n",
- who_e);
+ printf("IPC: ignoring notification from %d\n",
+ m.m_source);
break;
}
continue;
}
- ipc_number = (unsigned int)(call_type - IPC_BASE);
+ /* Dispatch the request. */
+ call_index = (unsigned int)(m.m_type - IPC_BASE);
- /* dispatch message */
- if (ipc_number < __arraycount(call_vec) &&
- call_vec[ipc_number] != NULL) {
- /* If any process does an IPC call,
- * we have to know about it exiting.
- * Tell VM to watch it for us.
+ if (call_index < __arraycount(call_vec) &&
+ call_vec[call_index] != NULL) {
+ /*
+ * If any process does an IPC call, we have to know
+ * about it exiting. Tell VM to watch it for us.
+ * TODO: this is not true; limit to affected processes.
*/
- if(vm_watch_exit(m.m_source) != OK) {
- printf("IPC: watch failed on %d\n", m.m_source);
+ if (vm_watch_exit(m.m_source) != OK) {
+ printf("IPC: watch failed on %d\n",
+ m.m_source);
}
- r = call_vec[ipc_number](&m);
+ r = call_vec[call_index](&m);
+ } else
+ r = ENOSYS;
+
+ /* Send a reply, if needed. */
+ if (r != SUSPEND) {
+ if (verbose)
+ printf("IPC: call result %d\n", r);
+ m.m_type = r;
/*
- * The handler of the IPC call did not
- * post a reply.
+ * Other fields may have been set by the handler
+ * function already.
*/
- if (r != SUSPEND) {
- m.m_type = r;
- if(verbose && r != OK)
- printf("IPC: error for %d: %d\n",
- call_type, r);
-
- if ((r = ipc_sendnb(who_e, &m)) != OK)
- printf("IPC send error %d.\n", r);
- }
- } else {
- /* warn and then ignore */
- printf("IPC unknown call type: %d from %d.\n",
- call_type, who_e);
+ if ((r = ipc_sendnb(m.m_source, &m)) != OK)
+ printf("IPC: send error %d\n", r);
}
+
+ /* XXX there must be a better way to do this! */
update_refcount_and_destroy();
}
- /* no way to get here */
- return -1;
-}
-
-/*===========================================================================*
- * sef_local_startup *
- *===========================================================================*/
-static void sef_local_startup(void)
-{
- /* Register init callbacks. */
- sef_setcb_init_fresh(sef_cb_init_fresh);
- sef_setcb_init_restart(sef_cb_init_fresh);
-
- /* Register signal callbacks. */
- sef_setcb_signal_handler(sef_cb_signal_handler);
-
- /* Let SEF perform startup. */
- sef_startup();
-}
-
-/*===========================================================================*
- * sef_cb_init_fresh *
- *===========================================================================*/
-static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
-{
-/* Initialize the ipc server. */
-
- if(verbose)
- printf("IPC: self: %d\n", sef_self());
-
- return(OK);
-}
-
-/*===========================================================================*
- * sef_cb_signal_handler *
- *===========================================================================*/
-static void sef_cb_signal_handler(int signo)
-{
- /* Only check for termination signal, ignore anything else. */
- if (signo != SIGTERM) return;
-
- /* Checkout if there are still IPC keys. Inform the user in that case. */
- if (is_sem_nil() && is_shm_nil())
- sef_exit(0);
-
- printf("IPC: exit with un-clean states.\n");
+ /* NOTREACHED */
+ return 0;
}
static struct sem_struct sem_list[SEMMNI];
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)
{
unsigned int i;
if (key == IPC_PRIVATE)
return NULL;
+
for (i = 0; i < sem_list_nr; i++) {
if (!(sem_list[i].semid_ds.sem_perm.mode & SEM_ALLOC))
continue;
if (sem_list[i].semid_ds.sem_perm._key == key)
return &sem_list[i];
}
+
return NULL;
}
-static struct sem_struct *sem_find_id(int id)
+static struct sem_struct *
+sem_find_id(int id)
{
struct sem_struct *sem;
unsigned int i;
return sem;
}
-/*===========================================================================*
- * do_semget *
- *===========================================================================*/
-int do_semget(message *m)
+int
+do_semget(message * m)
{
struct sem_struct *sem;
unsigned int i, seq;
nsems = m->m_lc_ipc_semget.nr;
flag = m->m_lc_ipc_semget.flag;
- if ((sem = sem_find_key(key))) {
+ if ((sem = sem_find_key(key)) != NULL) {
if ((flag & IPC_CREAT) && (flag & IPC_EXCL))
return EEXIST;
- if (!check_perm(&sem->semid_ds.sem_perm, who_e, flag))
+ if (!check_perm(&sem->semid_ds.sem_perm, m->m_source, flag))
return EACCES;
if (nsems > sem->semid_ds.sem_nsems)
return EINVAL;
/* Initialize the entry. */
sem = &sem_list[i];
seq = sem->semid_ds.sem_perm._seq;
- memset(sem, 0, sizeof(struct sem_struct));
+ memset(sem, 0, sizeof(*sem));
sem->semid_ds.sem_perm._key = key;
sem->semid_ds.sem_perm.cuid =
- sem->semid_ds.sem_perm.uid = getnuid(who_e);
+ sem->semid_ds.sem_perm.uid = getnuid(m->m_source);
sem->semid_ds.sem_perm.cgid =
- sem->semid_ds.sem_perm.gid = getngid(who_e);
+ sem->semid_ds.sem_perm.gid = getngid(m->m_source);
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;
return OK;
}
-static void send_message_to_process(endpoint_t who, int ret, int ignore)
+static void
+send_reply(endpoint_t who, int ret)
{
message m;
+ memset(&m, 0, sizeof(m));
m.m_type = ret;
+
ipc_sendnb(who, &m);
}
-static void remove_semaphore(struct sem_struct *sem)
+static void
+remove_semaphore(struct sem_struct * sem)
{
- int i, nr;
+ int i, j, nr;
+ struct semaphore *semaphore;
nr = sem->semid_ds.sem_nsems;
+ /* Deal with processes waiting for this semaphore set. */
for (i = 0; i < nr; i++) {
- if (sem->sems[i].zlist)
- free(sem->sems[i].zlist);
- if (sem->sems[i].nlist)
- free(sem->sems[i].nlist);
+ semaphore = &sem->sems[i];
+
+ for (j = 0; j < semaphore->semzcnt; j++)
+ send_reply(semaphore->zlist[j].who, EIDRM);
+ for (j = 0; j < semaphore->semncnt; j++)
+ send_reply(semaphore->nlist[j].who, EIDRM);
+
+ if (semaphore->zlist != NULL) {
+ free(semaphore->zlist);
+ semaphore->zlist = NULL;
+ }
+ if (semaphore->nlist != NULL) {
+ free(semaphore->nlist);
+ semaphore->nlist = NULL;
+ }
}
/* Mark the entry as free. */
}
#if 0
-static void show_semaphore(void)
+static void
+show_semaphore(void)
{
unsigned int i;
int j, k, nr;
printf("incr(");
for (k = 0; k < semaphore->semncnt; k++)
printf("%d-%d,",
- semaphore->nlist[k].who, semaphore->nlist[k].val);
+ semaphore->nlist[k].who,
+ semaphore->nlist[k].val);
printf(")");
}
printf("\n");
}
#endif
-static void remove_process(endpoint_t pt)
+static void
+remove_process(endpoint_t endpt)
{
struct sem_struct *sem;
+ struct semaphore *semaphore;
+ endpoint_t who_waiting;
unsigned int i;
- int j, nr;
+ int j, k, nr;
for (i = 0; i < sem_list_nr; i++) {
sem = &sem_list[i];
nr = sem->semid_ds.sem_nsems;
for (j = 0; j < nr; j++) {
- struct semaphore *semaphore = &sem->sems[j];
- int k;
+ semaphore = &sem->sems[j];
for (k = 0; k < semaphore->semzcnt; k++) {
- endpoint_t who_waiting = semaphore->zlist[k].who;
+ who_waiting = semaphore->zlist[k].who;
+
+ if (who_waiting == endpt) {
+ /* Remove this slot first. */
+ memmove(semaphore->zlist + k,
+ semaphore->zlist + k + 1,
+ sizeof(struct waiting) *
+ (semaphore->semzcnt - k - 1));
+ semaphore->semzcnt--;
- if (who_waiting == pt) {
- /* remove this slot first */
- memmove(semaphore->zlist+k, semaphore->zlist+k+1,
- sizeof(struct waiting) * (semaphore->semzcnt-k-1));
- --semaphore->semzcnt;
- /* then send message to the process */
- send_message_to_process(who_waiting, EINTR, 1);
+ /* Then send message to the process. */
+ send_reply(who_waiting, EINTR);
break;
}
}
for (k = 0; k < semaphore->semncnt; k++) {
- endpoint_t who_waiting = semaphore->nlist[k].who;
+ who_waiting = semaphore->nlist[k].who;
+
+ if (who_waiting == endpt) {
+ /* Remove it first. */
+ memmove(semaphore->nlist + k,
+ semaphore->nlist + k + 1,
+ sizeof(struct waiting) *
+ (semaphore->semncnt-k-1));
+ semaphore->semncnt--;
- if (who_waiting == pt) {
- /* remove it first */
- memmove(semaphore->nlist+k, semaphore->nlist+k+1,
- sizeof(struct waiting) * (semaphore->semncnt-k-1));
- --semaphore->semncnt;
- /* send the message to the process */
- send_message_to_process(who_waiting, EINTR, 1);
+ /* Send the message to the process. */
+ send_reply(who_waiting, EINTR);
break;
}
}
}
-static void update_one_semaphore(struct sem_struct *sem, int is_remove)
+static void
+check_semaphore(struct sem_struct * sem)
{
int i, j, nr;
struct semaphore *semaphore;
nr = sem->semid_ds.sem_nsems;
- if (is_remove) {
- for (i = 0; i < nr; i++) {
- semaphore = &sem->sems[i];
-
- for (j = 0; j < semaphore->semzcnt; j++)
- send_message_to_process(semaphore->zlist[j].who, EIDRM, 0);
- for (j = 0; j < semaphore->semncnt; j++)
- send_message_to_process(semaphore->nlist[j].who, EIDRM, 0);
- }
-
- remove_semaphore(sem);
- return;
- }
-
for (i = 0; i < nr; i++) {
semaphore = &sem->sems[i];
if (semaphore->zlist && !semaphore->semval) {
- /* choose one process, policy: FIFO. */
+ /* Choose one process, policy: FIFO. */
who = semaphore->zlist[0].who;
- memmove(semaphore->zlist, semaphore->zlist+1,
- sizeof(struct waiting) * (semaphore->semzcnt-1));
- --semaphore->semzcnt;
+ memmove(semaphore->zlist, semaphore->zlist + 1,
+ sizeof(struct waiting) * (semaphore->semzcnt - 1));
+ semaphore->semzcnt--;
- send_message_to_process(who, OK, 0);
+ send_reply(who, OK);
}
if (semaphore->nlist) {
for (j = 0; j < semaphore->semncnt; j++) {
- if (semaphore->nlist[j].val <= semaphore->semval) {
- semaphore->semval -= semaphore->nlist[j].val;
+ if (semaphore->nlist[j].val <=
+ semaphore->semval) {
+ semaphore->semval -=
+ semaphore->nlist[j].val;
who = semaphore->nlist[j].who;
- memmove(semaphore->nlist+j, semaphore->nlist+j+1,
- sizeof(struct waiting) * (semaphore->semncnt-j-1));
- --semaphore->semncnt;
-
- send_message_to_process(who, OK, 0);
+ memmove(semaphore->nlist + j,
+ semaphore->nlist + j + 1,
+ sizeof(struct waiting) *
+ (semaphore->semncnt-j-1));
+ semaphore->semncnt--;
- /* choose only one process */
+ send_reply(who, OK);
break;
}
}
}
}
-static void update_semaphores(void)
-{
- unsigned int i;
-
- for (i = 0; i < sem_list_nr; i++) {
- if (!(sem_list[i].semid_ds.sem_perm.mode & SEM_ALLOC))
- continue;
- update_one_semaphore(&sem_list[i], FALSE /*is_remove*/);
- }
-}
-
-/*===========================================================================*
- * do_semctl *
- *===========================================================================*/
-int do_semctl(message *m)
+int
+do_semctl(message * m)
{
unsigned int i;
vir_bytes opt;
uid_t uid;
int r, id, num, cmd, val;
unsigned short *buf;
- struct semid_ds *ds, tmp_ds;
+ struct semid_ds tmp_ds;
struct sem_struct *sem;
struct seminfo sinfo;
return EINVAL;
break;
default:
- if (!(sem = sem_find_id(id)))
+ if ((sem = sem_find_id(id)) == NULL)
return EINVAL;
break;
}
- /* IPC_SET and IPC_RMID as its own permission check */
+ /*
+ * IPC_SET and IPC_RMID have their own permission checks. IPC_INFO and
+ * SEM_INFO are free for general use.
+ */
if (sem != NULL && cmd != IPC_SET && cmd != IPC_RMID) {
- /* check read permission */
- if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0444))
+ /* Check read permission. */
+ if (!check_perm(&sem->semid_ds.sem_perm, m->m_source, 0444))
return EACCES;
}
switch (cmd) {
case IPC_STAT:
case SEM_STAT:
- if ((r = sys_datacopy(SELF, (vir_bytes)&sem->semid_ds, who_e,
- (vir_bytes)opt, sizeof(sem->semid_ds))) != OK)
+ if ((r = sys_datacopy(SELF, (vir_bytes)&sem->semid_ds,
+ m->m_source, opt, sizeof(sem->semid_ds))) != OK)
return r;
if (cmd == SEM_STAT)
m->m_lc_ipc_semctl.ret =
IXSEQ_TO_IPCID(id, sem->semid_ds.sem_perm);
break;
case IPC_SET:
- uid = getnuid(who_e);
+ uid = getnuid(m->m_source);
if (uid != sem->semid_ds.sem_perm.cuid &&
- uid != sem->semid_ds.sem_perm.uid &&
- uid != 0)
+ uid != sem->semid_ds.sem_perm.uid && uid != 0)
return EPERM;
- ds = (struct semid_ds *) opt;
- if ((r = sys_datacopy(who_e, (vir_bytes)ds, SELF,
- (vir_bytes)&tmp_ds, sizeof(struct semid_ds))) != OK)
+ if ((r = sys_datacopy(m->m_source, opt, SELF,
+ (vir_bytes)&tmp_ds, sizeof(tmp_ds))) != OK)
return r;
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_ctime = clock_time(NULL);
break;
case IPC_RMID:
- uid = getnuid(who_e);
+ uid = getnuid(m->m_source);
if (uid != sem->semid_ds.sem_perm.cuid &&
- uid != sem->semid_ds.sem_perm.uid &&
- uid != 0)
+ uid != sem->semid_ds.sem_perm.uid && uid != 0)
return EPERM;
- /* awaken all processes block in semop
- * and remove the semaphore set.
+ /*
+ * Awaken all processes blocked in semop(2) on any semaphore in
+ * this set, and remove the semaphore set itself.
*/
- update_one_semaphore(sem, TRUE /*is_remove*/);
+ remove_semaphore(sem);
break;
case IPC_INFO:
case SEM_INFO:
} 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)
+ if ((r = sys_datacopy(SELF, (vir_bytes)&sinfo, m->m_source,
+ opt, sizeof(sinfo))) != OK)
return r;
/* Return the highest in-use slot number if any, or zero. */
if (sem_list_nr > 0)
return ENOMEM;
for (i = 0; i < sem->semid_ds.sem_nsems; i++)
buf[i] = sem->sems[i].semval;
- r = sys_datacopy(SELF, (vir_bytes)buf, who_e, (vir_bytes)opt,
- sizeof(unsigned short) * sem->semid_ds.sem_nsems);
+ r = sys_datacopy(SELF, (vir_bytes)buf, m->m_source,
+ opt, sizeof(unsigned short) * sem->semid_ds.sem_nsems);
free(buf);
if (r != OK)
return EINVAL;
buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems);
if (buf == NULL)
return ENOMEM;
- r = sys_datacopy(who_e, (vir_bytes)opt, SELF, (vir_bytes)buf,
+ r = sys_datacopy(m->m_source, opt, SELF, (vir_bytes)buf,
sizeof(unsigned short) * sem->semid_ds.sem_nsems);
if (r != OK) {
free(buf);
return EINVAL;
}
-#ifdef DEBUG_SEM
- printf("SEMCTL: SETALL: opt: %lu\n", (vir_bytes) opt);
- for (i = 0; i < sem->semid_ds.sem_nsems; i++)
- printf("SEMCTL: SETALL val: [%d] %d\n", i, buf[i]);
-#endif
for (i = 0; i < sem->semid_ds.sem_nsems; i++) {
if (buf[i] > SEMVMX) {
free(buf);
- update_semaphores();
return ERANGE;
}
- sem->sems[i].semval = buf[i];
}
+#ifdef DEBUG_SEM
+ for (i = 0; i < sem->semid_ds.sem_nsems; i++)
+ printf("SEMCTL: SETALL val: [%d] %d\n", i, buf[i]);
+#endif
+ for (i = 0; i < sem->semid_ds.sem_nsems; i++)
+ sem->sems[i].semval = buf[i];
free(buf);
- /* awaken if possible */
- update_semaphores();
+ /* Awaken any waiting parties if now possible. */
+ check_semaphore(sem);
break;
case SETVAL:
- val = (int) opt;
- /* check write permission */
- if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0222))
+ val = (int)opt;
+ /* Check write permission. */
+ if (!check_perm(&sem->semid_ds.sem_perm, m->m_source, 0222))
return EACCES;
if (num < 0 || num >= sem->semid_ds.sem_nsems)
return EINVAL;
printf("SEMCTL: SETVAL: %d %d\n", num, val);
#endif
sem->semid_ds.sem_ctime = clock_time(NULL);
- /* awaken if possible */
- update_semaphores();
+ /* Awaken any waiting parties if now possible. */
+ check_semaphore(sem);
break;
default:
return EINVAL;
return OK;
}
-/*===========================================================================*
- * do_semop *
- *===========================================================================*/
-int do_semop(message *m)
+int
+do_semop(message * m)
{
- unsigned int i, j, mask;
+ unsigned int i, mask;
int id, r;
struct sembuf *sops;
unsigned int nsops;
struct sem_struct *sem;
- int no_reply = 0;
+ struct semaphore *s;
+ int op_n, val, no_reply;
id = m->m_lc_ipc_semop.id;
nsops = m->m_lc_ipc_semop.size;
- if (!(sem = sem_find_id(id)))
+ if ((sem = sem_find_id(id)) == NULL)
return EINVAL;
if (nsops <= 0)
if (nsops > SEMOPM)
return E2BIG;
- /* get the array from user application */
- sops = malloc(sizeof(struct sembuf) * nsops);
+ /* Get the array from the user process. */
+ sops = malloc(sizeof(sops[0]) * nsops);
if (!sops)
return ENOMEM;
- r = sys_datacopy(who_e, (vir_bytes) m->m_lc_ipc_semop.ops,
- SELF, (vir_bytes) sops,
- sizeof(struct sembuf) * nsops);
+ r = sys_datacopy(m->m_source, (vir_bytes)m->m_lc_ipc_semop.ops, SELF,
+ (vir_bytes)sops, sizeof(sops[0]) * nsops);
if (r != OK)
goto out_free;
printf("SEMOP: num:%d op:%d flg:%d\n",
sops[i].sem_num, sops[i].sem_op, sops[i].sem_flg);
#endif
- /* check for value range */
+ /* Check that all given semaphore numbers are within range. */
r = EFBIG;
for (i = 0; i < nsops; i++)
if (sops[i].sem_num >= sem->semid_ds.sem_nsems)
goto out_free;
- /* check for permissions */
+ /* Check for permissions. */
r = EACCES;
mask = 0;
for (i = 0; i < nsops; i++) {
else
mask |= 0444; /* check for read permission */
}
- if (mask && !check_perm(&sem->semid_ds.sem_perm, who_e, mask))
+ if (mask && !check_perm(&sem->semid_ds.sem_perm, m->m_source, mask))
goto out_free;
- /* check for duplicate number */
- r = EINVAL;
- for (i = 0; i < nsops; i++)
- for (j = i + 1; j < nsops; j++)
- if (sops[i].sem_num == sops[j].sem_num)
- goto out_free;
-
- /* check for nonblocking operations */
+ /* Check for nonblocking operations. */
r = EAGAIN;
for (i = 0; i < nsops; i++) {
- int op_n, val;
-
op_n = sops[i].sem_op;
val = sem->sems[sops[i].sem_num].semval;
if ((sops[i].sem_flg & IPC_NOWAIT) &&
- ((!op_n && val) ||
- (op_n < 0 &&
- -op_n > val)))
+ ((op_n == 0 && val != 0) || (op_n < 0 && -op_n > val)))
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. */
+ no_reply = 0;
for (i = 0; i < nsops; i++) {
- struct semaphore *s;
- int op_n;
-
s = &sem->sems[sops[i].sem_num];
op_n = sops[i].sem_op;
- s->sempid = getnpid(who_e);
+ s->sempid = getnpid(m->m_source);
if (op_n > 0) {
+ /* XXX missing ERANGE check */
s->semval += sops[i].sem_op;
- } else if (!op_n) {
+ } else if (op_n == 0) {
if (s->semval) {
- /* put the process asleep */
+ /* Put the process to sleep. */
s->semzcnt++;
s->zlist = realloc(s->zlist,
sizeof(struct waiting) * s->semzcnt);
/* continuing if NULL would lead to disaster */
if (s->zlist == NULL)
panic("out of memory");
- s->zlist[s->semzcnt-1].who = who_e;
- s->zlist[s->semzcnt-1].val = op_n;
+ s->zlist[s->semzcnt - 1].who = m->m_source;
+ s->zlist[s->semzcnt - 1].val = op_n;
-#ifdef DEBUG_SEM
- printf("SEMOP: Put into sleep... %d\n", who_e);
-#endif
no_reply++;
}
- } else {
+ } else /* (op_n < 0) */ {
if (s->semval >= -op_n)
s->semval += op_n;
else {
- /* put the process asleep */
+ /* Put the process to sleep. */
s->semncnt++;
s->nlist = realloc(s->nlist,
sizeof(struct waiting) * s->semncnt);
/* continuing if NULL would lead to disaster */
if (s->nlist == NULL)
panic("out of memory");
- s->nlist[s->semncnt-1].who = who_e;
- s->nlist[s->semncnt-1].val = -op_n;
+ s->nlist[s->semncnt - 1].who = m->m_source;
+ s->nlist[s->semncnt - 1].val = -op_n;
no_reply++;
}
}
r = no_reply ? SUSPEND : OK;
+
+ /* Awaken any other waiting parties if now possible. */
+ check_semaphore(sem);
+
out_free:
free(sops);
- /* awaken process if possible */
- update_semaphores();
-
return r;
}
-/*===========================================================================*
- * is_sem_nil *
- *===========================================================================*/
-int is_sem_nil(void)
+int
+is_sem_nil(void)
{
+
return (sem_list_nr == 0);
}
-/*===========================================================================*
- * sem_process_vm_notify *
- *===========================================================================*/
-void sem_process_vm_notify(void)
+void
+sem_process_vm_notify(void)
{
- endpoint_t pt;
+ endpoint_t endpt;
int r;
- while ((r = vm_query_exit(&pt)) >= 0) {
- /* for each enpoint 'pt', check whether it's waiting... */
- remove_process(pt);
+ /* For each endpoint, check whether it is waiting. */
+ while ((r = vm_query_exit(&endpt)) >= 0) {
+ remove_process(endpt);
if (r == 0)
break;
}
if (r < 0)
- printf("IPC: query exit error!\n");
+ printf("IPC: query exit error (%d)\n", r);
}
-
static struct shm_struct shm_list[SHMMNI];
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)
{
unsigned int i;
if (key == IPC_PRIVATE)
return NULL;
+
for (i = 0; i < shm_list_nr; i++) {
if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
continue;
if (shm_list[i].shmid_ds.shm_perm._key == key)
return &shm_list[i];
}
+
return NULL;
}
-static struct shm_struct *shm_find_id(int id)
+static struct shm_struct *
+shm_find_id(int id)
{
struct shm_struct *shm;
unsigned int i;
return shm;
}
-/*===========================================================================*
- * do_shmget *
- *===========================================================================*/
-int do_shmget(message *m)
+int
+do_shmget(message * m)
{
struct shm_struct *shm;
unsigned int i, seq;
old_size = size = m->m_lc_ipc_shmget.size;
flag = m->m_lc_ipc_shmget.flag;
- if ((shm = shm_find_key(key))) {
- if (!check_perm(&shm->shmid_ds.shm_perm, who_e, flag))
+ if ((shm = shm_find_key(key)) != NULL) {
+ if (!check_perm(&shm->shmid_ds.shm_perm, m->m_source, flag))
return EACCES;
if ((flag & IPC_CREAT) && (flag & IPC_EXCL))
return EEXIST;
return ENOENT;
if (size <= 0)
return EINVAL;
- /* round up to a multiple of PAGE_SIZE */
- if (size % PAGE_SIZE)
- size += PAGE_SIZE - size % PAGE_SIZE;
+ size = roundup(size, PAGE_SIZE);
if (size <= 0)
return EINVAL;
/* Initialize the entry. */
shm = &shm_list[i];
seq = shm->shmid_ds.shm_perm._seq;
- memset(shm, 0, sizeof(struct shm_struct));
+ memset(shm, 0, sizeof(*shm));
shm->shmid_ds.shm_perm._key = key;
shm->shmid_ds.shm_perm.cuid =
- shm->shmid_ds.shm_perm.uid = getnuid(who_e);
+ shm->shmid_ds.shm_perm.uid = getnuid(m->m_source);
shm->shmid_ds.shm_perm.cgid =
- shm->shmid_ds.shm_perm.gid = getngid(who_e);
+ shm->shmid_ds.shm_perm.gid = getngid(m->m_source);
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_atime = 0;
shm->shmid_ds.shm_dtime = 0;
shm->shmid_ds.shm_ctime = clock_time(NULL);
- shm->shmid_ds.shm_cpid = getnpid(who_e);
+ shm->shmid_ds.shm_cpid = getnpid(m->m_source);
shm->shmid_ds.shm_lpid = 0;
shm->shmid_ds.shm_nattch = 0;
shm->page = (vir_bytes)page;
return OK;
}
-/*===========================================================================*
- * do_shmat *
- *===========================================================================*/
-int do_shmat(message *m)
+int
+do_shmat(message * m)
{
int id, flag;
vir_bytes addr;
struct shm_struct *shm;
id = m->m_lc_ipc_shmat.id;
- addr = (vir_bytes) m->m_lc_ipc_shmat.addr;
+ addr = (vir_bytes)m->m_lc_ipc_shmat.addr;
flag = m->m_lc_ipc_shmat.flag;
- if (addr && (addr % PAGE_SIZE)) {
+ if (addr % PAGE_SIZE) {
if (flag & SHM_RND)
- addr -= (addr % PAGE_SIZE);
+ addr -= addr % PAGE_SIZE;
else
return EINVAL;
}
- if (!(shm = shm_find_id(id)))
+ if ((shm = shm_find_id(id)) == NULL)
return EINVAL;
if (flag & SHM_RDONLY)
flag = 0444;
else
flag = 0666;
- if (!check_perm(&shm->shmid_ds.shm_perm, who_e, flag))
+ if (!check_perm(&shm->shmid_ds.shm_perm, m->m_source, flag))
return EACCES;
- ret = vm_remap(who_e, sef_self(), (void *)addr, (void *)shm->page,
- shm->shmid_ds.shm_segsz);
+ ret = vm_remap(m->m_source, sef_self(), (void *)addr,
+ (void *)shm->page, shm->shmid_ds.shm_segsz);
if (ret == MAP_FAILED)
return ENOMEM;
shm->shmid_ds.shm_atime = clock_time(NULL);
- shm->shmid_ds.shm_lpid = getnpid(who_e);
- /* nattach is updated lazily */
+ shm->shmid_ds.shm_lpid = getnpid(m->m_source);
+ /* nattch is updated lazily */
m->m_lc_ipc_shmat.retaddr = ret;
return OK;
}
-/*===========================================================================*
- * update_refcount_and_destroy *
- *===========================================================================*/
-void update_refcount_and_destroy(void)
+void
+update_refcount_and_destroy(void)
{
- size_t size;
u8_t rc;
unsigned int i;
if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
continue;
- rc = vm_getrefcount(sef_self(), (void *) shm_list[i].page);
- if (rc == (u8_t) -1) {
+ rc = vm_getrefcount(sef_self(), (void *)shm_list[i].page);
+ if (rc == (u8_t)-1) {
printf("IPC: can't find physical region.\n");
continue;
}
if (shm_list[i].shmid_ds.shm_nattch == 0 &&
(shm_list[i].shmid_ds.shm_perm.mode & SHM_DEST)) {
- size = shm_list[i].shmid_ds.shm_segsz;
- if (size % PAGE_SIZE)
- size += PAGE_SIZE - size % PAGE_SIZE;
- munmap((void *)shm_list[i].page, size);
+ munmap((void *)shm_list[i].page,
+ roundup(shm_list[i].shmid_ds.shm_segsz,
+ PAGE_SIZE));
/* Mark the entry as free. */
shm_list[i].shmid_ds.shm_perm.mode &= ~SHM_ALLOC;
}
shm_list_nr--;
}
-/*===========================================================================*
- * do_shmdt *
- *===========================================================================*/
-int do_shmdt(message *m)
+int
+do_shmdt(message * m)
{
struct shm_struct *shm;
vir_bytes addr;
phys_bytes vm_id;
unsigned int i;
- addr = (vir_bytes) m->m_lc_ipc_shmdt.addr;
+ addr = (vir_bytes)m->m_lc_ipc_shmdt.addr;
- if ((vm_id = vm_getphys(who_e, (void *) addr)) == 0)
+ if ((vm_id = vm_getphys(m->m_source, (void *)addr)) == 0)
return EINVAL;
for (i = 0; i < shm_list_nr; i++) {
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(m->m_source);
/* nattch is updated lazily */
- vm_unmap(who_e, (void *) addr);
+ vm_unmap(m->m_source, (void *)addr);
break;
}
}
if (i == shm_list_nr)
- printf("IPC: do_shmdt impossible error! could not find id %lu to unmap\n",
- vm_id);
+ printf("IPC: do_shmdt: ID %lu not found\n", vm_id);
update_refcount_and_destroy();
return OK;
}
-/*===========================================================================*
- * do_shmctl *
- *===========================================================================*/
-int do_shmctl(message *m)
+int
+do_shmctl(message * m)
{
- struct shmid_ds *ds;
struct shmid_ds tmp_ds;
struct shm_struct *shm;
struct shminfo sinfo;
struct shm_info s_info;
+ vir_bytes buf;
unsigned int i;
uid_t uid;
int r, id, cmd;
id = m->m_lc_ipc_shmctl.id;
cmd = m->m_lc_ipc_shmctl.cmd;
- ds = (struct shmid_ds *)m->m_lc_ipc_shmctl.buf;
+ buf = (vir_bytes)m->m_lc_ipc_shmctl.buf;
/*
* For stat calls, sure that all information is up-to-date. Since this
return EINVAL;
break;
default:
- if (!(shm = shm_find_id(id)))
+ if ((shm = shm_find_id(id)) == NULL)
return EINVAL;
break;
}
case IPC_STAT:
case SHM_STAT:
/* Check whether the caller has read permission. */
- if (!check_perm(&shm->shmid_ds.shm_perm, who_e, 0444))
+ if (!check_perm(&shm->shmid_ds.shm_perm, m->m_source, 0444))
return EACCES;
- if ((r = sys_datacopy(SELF, (vir_bytes)&shm->shmid_ds, who_e,
- (vir_bytes)ds, sizeof(struct shmid_ds))) != OK)
+ if ((r = sys_datacopy(SELF, (vir_bytes)&shm->shmid_ds,
+ m->m_source, buf, sizeof(shm->shmid_ds))) != OK)
return r;
if (cmd == SHM_STAT)
m->m_lc_ipc_shmctl.ret =
IXSEQ_TO_IPCID(id, shm->shmid_ds.shm_perm);
break;
case IPC_SET:
- uid = getnuid(who_e);
+ uid = getnuid(m->m_source);
if (uid != shm->shmid_ds.shm_perm.cuid &&
- uid != shm->shmid_ds.shm_perm.uid &&
- uid != 0)
+ uid != shm->shmid_ds.shm_perm.uid && uid != 0)
return EPERM;
- if ((r = sys_datacopy(who_e, (vir_bytes)ds, SELF,
- (vir_bytes)&tmp_ds, sizeof(struct shmid_ds))) != OK)
+ if ((r = sys_datacopy(m->m_source, buf, SELF,
+ (vir_bytes)&tmp_ds, sizeof(tmp_ds))) != OK)
return r;
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_ctime = clock_time(NULL);
break;
case IPC_RMID:
- uid = getnuid(who_e);
+ uid = getnuid(m->m_source);
if (uid != shm->shmid_ds.shm_perm.cuid &&
- uid != shm->shmid_ds.shm_perm.uid &&
- uid != 0)
+ uid != shm->shmid_ds.shm_perm.uid && uid != 0)
return EPERM;
shm->shmid_ds.shm_perm.mode |= SHM_DEST;
- /* destroy if possible */
+ /* Destroy if possible. */
update_refcount_and_destroy();
break;
case IPC_INFO:
sinfo.shmmni = __arraycount(shm_list);
sinfo.shmseg = (unsigned long) -1;
sinfo.shmall = (unsigned long) -1;
- if ((r = sys_datacopy(SELF, (vir_bytes)&sinfo, who_e,
- (vir_bytes)ds, sizeof(sinfo))) != OK)
+ if ((r = sys_datacopy(SELF, (vir_bytes)&sinfo, m->m_source,
+ buf, sizeof(sinfo))) != OK)
return r;
if (shm_list_nr > 0)
m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
s_info.shm_tot = 0;
for (i = 0; i < shm_list_nr; i++)
s_info.shm_tot +=
- shm_list[i].shmid_ds.shm_segsz/PAGE_SIZE;
+ shm_list[i].shmid_ds.shm_segsz / PAGE_SIZE;
s_info.shm_rss = s_info.shm_tot;
s_info.shm_swp = 0;
s_info.swap_attempts = 0;
s_info.swap_successes = 0;
- if ((r = sys_datacopy(SELF, (vir_bytes)&s_info, who_e,
- (vir_bytes)ds, sizeof(s_info))) != OK)
+ if ((r = sys_datacopy(SELF, (vir_bytes)&s_info, m->m_source,
+ buf, sizeof(s_info))) != OK)
return r;
if (shm_list_nr > 0)
m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
}
#if 0
-static void list_shm_ds(void)
+static void
+list_shm_ds(void)
{
unsigned int i;
+
printf("key\tid\tpage\n");
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",
- shm_list[i].shmid_ds.shm_perm._key,
- IXSEQ_TO_IPCID(i, shm_list[i].shmid_ds.shm_perm),
- shm_list[i].page);
+ shm_list[i].shmid_ds.shm_perm._key,
+ IXSEQ_TO_IPCID(i, shm_list[i].shmid_ds.shm_perm),
+ shm_list[i].page);
}
}
#endif
-/*===========================================================================*
- * is_shm_nil *
- *===========================================================================*/
-int is_shm_nil(void)
+int
+is_shm_nil(void)
{
+
return (shm_list_nr == 0);
}