/*===========================================================================* * do_shmdt * *===========================================================================*/ int do_shmdt(message *m) { vir_bytes addr; phys_bytes vm_id; int i; addr = (vir_bytes) m->m_lc_ipc_shmdt.addr; if ((vm_id = vm_getphys(who_e, (void *) addr)) == 0) return EINVAL; for (i = 0; i < shm_list_nr; i++) { if (shm_list[i].vm_id == vm_id) { struct shm_struct *shm = &shm_list[i]; shm->shmid_ds.shm_atime = time(NULL); shm->shmid_ds.shm_lpid = getnpid(who_e); /* nattch is updated lazily */ vm_unmap(who_e, (void *) addr); break; } } if (i == shm_list_nr) printf("IPC: do_shmdt impossible error! could not find id %lu to unmap\n", vm_id); update_refcount_and_destroy(); return OK; }
/*===========================================================================* * do_shmdt * *===========================================================================*/ PUBLIC int do_shmdt(message *m) { vir_bytes addr; phys_bytes paddr; int i; addr = m->SHMDT_ADDR; if ((paddr = vm_getphys(who_e, (void *) addr)) == 0) return EINVAL; for (i = 0; i < shm_list_nr; i++) { if (shm_list[i].phys == paddr) { struct shm_struct *shm = &shm_list[i]; shm->shmid_ds.shm_atime = time(NULL); shm->shmid_ds.shm_lpid = getnpid(who_e); /* nattch is updated lazily */ vm_unmap(who_e, (void *) addr); break; } } if (i == shm_list_nr) fprintf(stderr, "IPC: do_shmdt impossible error!\n"); update_refcount_and_destroy(); return OK; }
PUBLIC int main(int argc, char *argv[]) { message m; /* SEF local startup. */ env_setargs(argc, argv); sef_local_startup(); while (TRUE) { int r; int i; if ((r = sef_receive(ANY, &m)) != OK) printf("sef_receive failed %d.\n", r); who_e = m.m_source; call_type = m.m_type; if(verbose) printf("IPC: get %d from %d\n", call_type, who_e); if (call_type & NOTIFY_MESSAGE) { switch (who_e) { case PM_PROC_NR: /* PM sends a notify() on shutdown, * checkout if there are still IPC keys, * give warning messages. */ if (!is_sem_nil() || !is_shm_nil()) printf("IPC: exit with un-clean states.\n"); break; case VM_PROC_NR: /* currently, only semaphore needs such information. */ sem_process_vm_notify(); break; default: printf("IPC: ignoring notify() from %d\n", who_e); break; } continue; } /* dispatch messages */ for (i = 0; i < SIZE(ipc_calls); i++) { if (ipc_calls[i].type == call_type) { int result; result = ipc_calls[i].func(&m); if (ipc_calls[i].reply) break; m.m_type = result; if(verbose && result != OK) printf("IPC: error for %d: %d\n", call_type, result); if ((r = sendnb(who_e, &m)) != OK) printf("IPC send error %d.\n", r); break; } } if (i == SIZE(ipc_calls)) { /* warn and then ignore */ printf("IPC unknown call type: %d from %d.\n", call_type, who_e); } update_refcount_and_destroy(); } /* no way to get here */ return -1; }
/*===========================================================================* * do_shmctl * *===========================================================================*/ PUBLIC int do_shmctl(message *m) { int id = m->SHMCTL_ID; int cmd = m->SHMCTL_CMD; struct shmid_ds *ds = (struct shmid_ds *)m->SHMCTL_BUF; struct shmid_ds tmp_ds; struct shm_struct *shm; struct shminfo sinfo; struct shm_info s_info; uid_t uid; int r, i; if (cmd == IPC_STAT) update_refcount_and_destroy(); if ((cmd == IPC_STAT || cmd == IPC_SET || cmd == IPC_RMID) && !(shm = shm_find_id(id))) return EINVAL; switch (cmd) { case IPC_STAT: if (!ds) return EFAULT; /* check whether it has read permission */ if (!check_perm(&shm->shmid_ds.shm_perm, who_e, 0444)) return EACCES; r = sys_datacopy(SELF_E, (vir_bytes)&shm->shmid_ds, who_e, (vir_bytes)ds, sizeof(struct shmid_ds)); if (r != OK) return EFAULT; break; case IPC_SET: uid = getnuid(who_e); if (uid != shm->shmid_ds.shm_perm.cuid && uid != shm->shmid_ds.shm_perm.uid && uid != 0) return EPERM; r = sys_datacopy(who_e, (vir_bytes)ds, SELF_E, (vir_bytes)&tmp_ds, sizeof(struct shmid_ds)); if (r != OK) return EFAULT; 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.mode &= ~0777; shm->shmid_ds.shm_perm.mode |= tmp_ds.shm_perm.mode & 0666; shm->shmid_ds.shm_ctime = time(NULL); break; case IPC_RMID: uid = getnuid(who_e); if (uid != shm->shmid_ds.shm_perm.cuid && uid != shm->shmid_ds.shm_perm.uid && uid != 0) return EPERM; shm->shmid_ds.shm_perm.mode |= SHM_DEST; /* destroy if possible */ update_refcount_and_destroy(); break; case IPC_INFO: if (!ds) return EFAULT; sinfo.shmmax = (unsigned long) -1; sinfo.shmmin = 1; sinfo.shmmni = MAX_SHM_NR; sinfo.shmseg = (unsigned long) -1; sinfo.shmall = (unsigned long) -1; r = sys_datacopy(SELF_E, (vir_bytes)&sinfo, who_e, (vir_bytes)ds, sizeof(struct shminfo)); if (r != OK) return EFAULT; m->SHMCTL_RET = shm_list_nr - 1; if (m->SHMCTL_RET < 0) m->SHMCTL_RET = 0; break; case SHM_INFO: if (!ds) return EFAULT; s_info.used_ids = shm_list_nr; s_info.shm_tot = 0; for (i = 0; i < shm_list_nr; i++) s_info.shm_tot += shm_list[i].shmid_ds.shm_segsz/I386_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; r = sys_datacopy(SELF_E, (vir_bytes)&s_info, who_e, (vir_bytes)ds, sizeof(struct shm_info)); if (r != OK) return EFAULT; m->SHMCTL_RET = shm_list_nr - 1; if (m->SHMCTL_RET < 0) m->SHMCTL_RET = 0; break; case SHM_STAT: if (id < 0 || id >= shm_list_nr) return EINVAL; shm = &shm_list[id]; r = sys_datacopy(SELF_E, (vir_bytes)&shm->shmid_ds, who_e, (vir_bytes)ds, sizeof(struct shmid_ds)); if (r != OK) return EFAULT; m->SHMCTL_RET = shm->id; break; default: return EINVAL; } return OK; }
PUBLIC int main(int argc, char *argv[]) { message m; /* SEF local startup. */ env_setargs(argc, argv); sef_local_startup(); while (TRUE) { int r; int i; if ((r = sef_receive(ANY, &m)) != OK) printf("sef_receive failed %d.\n", r); who_e = m.m_source; call_type = m.m_type; if(verbose) printf("IPC: get %d from %d\n", call_type, who_e); if (call_type & NOTIFY_MESSAGE) { switch (who_e) { case VM_PROC_NR: /* currently, only semaphore needs such information. */ sem_process_vm_notify(); break; default: printf("IPC: ignoring notify() from %d\n", who_e); break; } continue; } /* dispatch messages */ for (i = 0; i < SIZE(ipc_calls); i++) { /* If any process does an IPC call, * we have to know about it exiting. * Tell VM to watch it for us. */ if(vm_watch_exit(m.m_source) != OK) { printf("IPC: watch failed on %d\n", m.m_source); } if (ipc_calls[i].type == call_type) { int result; result = ipc_calls[i].func(&m); if (ipc_calls[i].reply) break; m.m_type = result; if(verbose && result != OK) printf("IPC: error for %d: %d\n", call_type, result); if ((r = sendnb(who_e, &m)) != OK) printf("IPC send error %d.\n", r); break; } } if (i == SIZE(ipc_calls)) { /* warn and then ignore */ printf("IPC unknown call type: %d from %d.\n", call_type, who_e); } update_refcount_and_destroy(); } /* no way to get here */ return -1; }