From: David van Moolenbroek Date: Wed, 25 Nov 2015 22:37:19 +0000 (+0000) Subject: IPC server: restyle X-Git-Url: http://zhaoyanbai.com/repos/dig.html?a=commitdiff_plain;h=0baafa0ef4760fc6c0d2e86ae5f07c8acb9cd272;p=minix.git IPC server: restyle Closer to KNF, better coding practices, more similar to other services, no more global variables, a few more comments, that kind of stuff. No major functional changes. Change-Id: I6e8f53bfafd6f41e92031fba76c40a31d2107a8e --- diff --git a/minix/servers/ipc/inc.h b/minix/servers/ipc/inc.h index 1a41048c0..d9728467f 100644 --- a/minix/servers/ipc/inc.h +++ b/minix/servers/ipc/inc.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -38,17 +39,20 @@ #define IPCID_TO_IX(id) ((id) & 0xffff) #define IPCID_TO_SEQ(id) (((id) >> 16) & 0xffff) +/* shm.c */ int do_shmget(message *); int do_shmat(message *); int do_shmdt(message *); int do_shmctl(message *); -int check_perm(struct ipc_perm *, endpoint_t, int); +int is_shm_nil(void); void update_refcount_and_destroy(void); + +/* sem.c */ int do_semget(message *); int do_semctl(message *); int do_semop(message *); int is_sem_nil(void); -int is_shm_nil(void); void sem_process_vm_notify(void); -EXTERN endpoint_t who_e; +/* utility.c */ +int check_perm(struct ipc_perm *, endpoint_t, int); diff --git a/minix/servers/ipc/main.c b/minix/servers/ipc/main.c index 46d902ab7..948b72b27 100644 --- a/minix/servers/ipc/main.c +++ b/minix/servers/ipc/main.c @@ -1,8 +1,8 @@ #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, @@ -16,125 +16,122 @@ static int (* const call_vec[])(message *) = { 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; } diff --git a/minix/servers/ipc/sem.c b/minix/servers/ipc/sem.c index cabf50726..88bea83a7 100644 --- a/minix/servers/ipc/sem.c +++ b/minix/servers/ipc/sem.c @@ -22,22 +22,26 @@ struct sem_struct { 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; @@ -54,10 +58,8 @@ static struct sem_struct *sem_find_id(int id) return sem; } -/*===========================================================================* - * do_semget * - *===========================================================================*/ -int do_semget(message *m) +int +do_semget(message * m) { struct sem_struct *sem; unsigned int i, seq; @@ -68,10 +70,10 @@ int do_semget(message *m) 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; @@ -92,12 +94,12 @@ int do_semget(message *m) /* 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; @@ -113,25 +115,42 @@ int do_semget(message *m) 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. */ @@ -147,7 +166,8 @@ static void remove_semaphore(struct sem_struct *sem) } #if 0 -static void show_semaphore(void) +static void +show_semaphore(void) { unsigned int i; int j, k, nr; @@ -176,7 +196,8 @@ static void show_semaphore(void) 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"); @@ -186,11 +207,14 @@ static void show_semaphore(void) } #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]; @@ -199,34 +223,39 @@ static void remove_process(endpoint_t pt) 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; } @@ -235,7 +264,8 @@ static void remove_process(endpoint_t pt) } } -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; @@ -243,47 +273,35 @@ static void update_one_semaphore(struct sem_struct *sem, int is_remove) 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; } } @@ -291,28 +309,15 @@ static void update_one_semaphore(struct sem_struct *sem, int is_remove) } } -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; @@ -334,37 +339,38 @@ int do_semctl(message *m) 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; @@ -374,15 +380,15 @@ int do_semctl(message *m) 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: @@ -413,8 +419,8 @@ int do_semctl(message *m) } 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) @@ -428,8 +434,8 @@ int do_semctl(message *m) 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; @@ -458,33 +464,32 @@ int do_semctl(message *m) 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; @@ -495,8 +500,8 @@ int do_semctl(message *m) 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; @@ -505,22 +510,21 @@ int do_semctl(message *m) 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) @@ -528,13 +532,12 @@ int do_semop(message *m) 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; @@ -543,13 +546,13 @@ int do_semop(message *m) 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++) { @@ -558,73 +561,58 @@ int do_semop(message *m) 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++; } @@ -632,39 +620,36 @@ int do_semop(message *m) } 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); } - diff --git a/minix/servers/ipc/shm.c b/minix/servers/ipc/shm.c index edd351938..43aa6a8d8 100644 --- a/minix/servers/ipc/shm.c +++ b/minix/servers/ipc/shm.c @@ -11,22 +11,26 @@ struct shm_struct { 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; @@ -43,10 +47,8 @@ static struct shm_struct *shm_find_id(int id) return shm; } -/*===========================================================================* - * do_shmget * - *===========================================================================*/ -int do_shmget(message *m) +int +do_shmget(message * m) { struct shm_struct *shm; unsigned int i, seq; @@ -59,8 +61,8 @@ int do_shmget(message *m) 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; @@ -72,9 +74,7 @@ int do_shmget(message *m) 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; @@ -98,20 +98,20 @@ int do_shmget(message *m) /* 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; @@ -126,10 +126,8 @@ int do_shmget(message *m) return OK; } -/*===========================================================================* - * do_shmat * - *===========================================================================*/ -int do_shmat(message *m) +int +do_shmat(message * m) { int id, flag; vir_bytes addr; @@ -137,45 +135,42 @@ int do_shmat(message *m) 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; @@ -183,8 +178,8 @@ void update_refcount_and_destroy(void) 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; } @@ -192,10 +187,9 @@ void update_refcount_and_destroy(void) 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; } @@ -210,19 +204,17 @@ void update_refcount_and_destroy(void) 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++) { @@ -233,39 +225,36 @@ int do_shmdt(message *m) 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 @@ -287,7 +276,7 @@ int do_shmctl(message *m) return EINVAL; break; default: - if (!(shm = shm_find_id(id))) + if ((shm = shm_find_id(id)) == NULL) return EINVAL; break; } @@ -296,23 +285,22 @@ int do_shmctl(message *m) 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; @@ -322,13 +310,12 @@ int do_shmctl(message *m) 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: @@ -338,8 +325,8 @@ int do_shmctl(message *m) 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; @@ -352,13 +339,13 @@ int do_shmctl(message *m) 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; @@ -372,25 +359,26 @@ int do_shmctl(message *m) } #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); } diff --git a/minix/servers/ipc/utility.c b/minix/servers/ipc/utility.c index 46a84f85b..aebf4f081 100644 --- a/minix/servers/ipc/utility.c +++ b/minix/servers/ipc/utility.c @@ -1,35 +1,34 @@ #include "inc.h" -int check_perm(struct ipc_perm *req, endpoint_t who, int mode) +int +check_perm(struct ipc_perm * req, endpoint_t who, int mode) { int req_mode; int cur_mode; - uid_t uid = getnuid(who); - gid_t gid = getngid(who); + uid_t uid; + gid_t gid; + uid = getnuid(who); + gid = getngid(who); mode &= 0666; - /* is root? */ + /* Root is allowed to do anything. */ if (uid == 0) return 1; if (uid == req->uid || uid == req->cuid) { - /* same user */ + /* Same user. */ req_mode = (req->mode >> 6) & 0x7; cur_mode = (mode >> 6) & 0x7; } else if (gid == req->gid || gid == req->cgid) { - /* same group */ + /* Same group. */ req_mode = (req->mode >> 3) & 0x7; cur_mode = (mode >> 3) & 0x7; } else { - /* other group */ + /* Other user and group. */ req_mode = req->mode & 0x7; cur_mode = mode & 0x7; } - if (cur_mode && ((cur_mode & req_mode) == cur_mode)) - return 1; - else - return 0; + return (cur_mode && ((cur_mode & req_mode) == cur_mode)); } -