/*===========================================================================* * 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; }
/*===========================================================================* * 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_shmget * *===========================================================================*/ PUBLIC int do_shmget(message *m) { struct shm_struct *shm; long key, size, old_size; int flag; int id; key = m->SHMGET_KEY; old_size = size = m->SHMGET_SIZE; flag = m->SHMGET_FLAG; if ((shm = shm_find_key(key))) { if (!check_perm(&shm->shmid_ds.shm_perm, who_e, flag)) return EACCES; if ((flag & IPC_CREAT) && (flag & IPC_EXCL)) return EEXIST; if (size && shm->shmid_ds.shm_segsz < size) return EINVAL; id = shm->id; } else { /* no key found */ if (!(flag & IPC_CREAT)) return ENOENT; if (size <= 0) return EINVAL; /* round up to a multiple of PAGE_SIZE */ if (size % I386_PAGE_SIZE) size += I386_PAGE_SIZE - size % I386_PAGE_SIZE; if (size <= 0) return EINVAL; if (shm_list_nr == MAX_SHM_NR) return ENOMEM; /* TODO: shmmni should be changed... */ if (identifier == SHMMNI) 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_CONTIG|MAP_PREALLOC|MAP_ANON|MAP_SHARED, -1, 0); if (shm->page == (vir_bytes) MAP_FAILED) return ENOMEM; shm->phys = vm_getphys(SELF_E, (void *) shm->page); memset((void *)shm->page, 0, size); shm->shmid_ds.shm_perm.cuid = shm->shmid_ds.shm_perm.uid = getnuid(who_e); shm->shmid_ds.shm_perm.cgid = shm->shmid_ds.shm_perm.gid = getngid(who_e); shm->shmid_ds.shm_perm.mode = flag & 0777; shm->shmid_ds.shm_segsz = old_size; shm->shmid_ds.shm_atime = 0; shm->shmid_ds.shm_dtime = 0; shm->shmid_ds.shm_ctime = time(NULL); shm->shmid_ds.shm_cpid = getnpid(who_e); shm->shmid_ds.shm_lpid = 0; shm->shmid_ds.shm_nattch = 0; shm->id = id = identifier++; shm->key = key; shm_list_nr++; } m->SHMGET_RETID = id; return OK; }