xref: /minix3/minix/servers/ipc/shm.c (revision 0baafa0ef4760fc6c0d2e86ae5f07c8acb9cd272)
1433d6423SLionel Sambuc #include "inc.h"
2433d6423SLionel Sambuc 
34d272e5aSDavid van Moolenbroek /* Private shm_perm.mode flags, synchronized with NetBSD kernel values */
44d272e5aSDavid van Moolenbroek #define SHM_ALLOC	0x0800	/* slot is in use (SHMSEG_ALLOCATED) */
5433d6423SLionel Sambuc 
6433d6423SLionel Sambuc struct shm_struct {
7433d6423SLionel Sambuc 	struct shmid_ds shmid_ds;
8433d6423SLionel Sambuc 	vir_bytes page;
94d272e5aSDavid van Moolenbroek 	phys_bytes vm_id;
10433d6423SLionel Sambuc };
114d272e5aSDavid van Moolenbroek static struct shm_struct shm_list[SHMMNI];
124d272e5aSDavid van Moolenbroek static unsigned int shm_list_nr = 0; /* highest in-use slot number plus one */
13433d6423SLionel Sambuc 
14*0baafa0eSDavid van Moolenbroek static struct shm_struct *
15*0baafa0eSDavid van Moolenbroek shm_find_key(key_t key)
16433d6423SLionel Sambuc {
174d272e5aSDavid van Moolenbroek 	unsigned int i;
184d272e5aSDavid van Moolenbroek 
19433d6423SLionel Sambuc 	if (key == IPC_PRIVATE)
20433d6423SLionel Sambuc 		return NULL;
21*0baafa0eSDavid van Moolenbroek 
224d272e5aSDavid van Moolenbroek 	for (i = 0; i < shm_list_nr; i++) {
234d272e5aSDavid van Moolenbroek 		if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
244d272e5aSDavid van Moolenbroek 			continue;
254d272e5aSDavid van Moolenbroek 		if (shm_list[i].shmid_ds.shm_perm._key == key)
264d272e5aSDavid van Moolenbroek 			return &shm_list[i];
274d272e5aSDavid van Moolenbroek 	}
28*0baafa0eSDavid van Moolenbroek 
29433d6423SLionel Sambuc 	return NULL;
30433d6423SLionel Sambuc }
31433d6423SLionel Sambuc 
32*0baafa0eSDavid van Moolenbroek static struct shm_struct *
33*0baafa0eSDavid van Moolenbroek shm_find_id(int id)
34433d6423SLionel Sambuc {
354d272e5aSDavid van Moolenbroek 	struct shm_struct *shm;
364d272e5aSDavid van Moolenbroek 	unsigned int i;
374d272e5aSDavid van Moolenbroek 
384d272e5aSDavid van Moolenbroek 	i = IPCID_TO_IX(id);
394d272e5aSDavid van Moolenbroek 	if (i >= shm_list_nr)
40433d6423SLionel Sambuc 		return NULL;
414d272e5aSDavid van Moolenbroek 
424d272e5aSDavid van Moolenbroek 	shm = &shm_list[i];
434d272e5aSDavid van Moolenbroek 	if (!(shm->shmid_ds.shm_perm.mode & SHM_ALLOC))
444d272e5aSDavid van Moolenbroek 		return NULL;
454d272e5aSDavid van Moolenbroek 	if (shm->shmid_ds.shm_perm._seq != IPCID_TO_SEQ(id))
464d272e5aSDavid van Moolenbroek 		return NULL;
474d272e5aSDavid van Moolenbroek 	return shm;
48433d6423SLionel Sambuc }
49433d6423SLionel Sambuc 
50*0baafa0eSDavid van Moolenbroek int
51*0baafa0eSDavid van Moolenbroek do_shmget(message * m)
52433d6423SLionel Sambuc {
53433d6423SLionel Sambuc 	struct shm_struct *shm;
544d272e5aSDavid van Moolenbroek 	unsigned int i, seq;
554d272e5aSDavid van Moolenbroek 	key_t key;
564d272e5aSDavid van Moolenbroek 	size_t size, old_size;
57433d6423SLionel Sambuc 	int flag;
584d272e5aSDavid van Moolenbroek 	void *page;
59433d6423SLionel Sambuc 
60433d6423SLionel Sambuc 	key = m->m_lc_ipc_shmget.key;
61433d6423SLionel Sambuc 	old_size = size = m->m_lc_ipc_shmget.size;
62433d6423SLionel Sambuc 	flag = m->m_lc_ipc_shmget.flag;
63433d6423SLionel Sambuc 
64*0baafa0eSDavid van Moolenbroek 	if ((shm = shm_find_key(key)) != NULL) {
65*0baafa0eSDavid van Moolenbroek 		if (!check_perm(&shm->shmid_ds.shm_perm, m->m_source, flag))
66433d6423SLionel Sambuc 			return EACCES;
67433d6423SLionel Sambuc 		if ((flag & IPC_CREAT) && (flag & IPC_EXCL))
68433d6423SLionel Sambuc 			return EEXIST;
69433d6423SLionel Sambuc 		if (size && shm->shmid_ds.shm_segsz < size)
70433d6423SLionel Sambuc 			return EINVAL;
714d272e5aSDavid van Moolenbroek 		i = shm - shm_list;
72433d6423SLionel Sambuc 	} else { /* no key found */
73433d6423SLionel Sambuc 		if (!(flag & IPC_CREAT))
74433d6423SLionel Sambuc 			return ENOENT;
75433d6423SLionel Sambuc 		if (size <= 0)
76433d6423SLionel Sambuc 			return EINVAL;
77*0baafa0eSDavid van Moolenbroek 		size = roundup(size, PAGE_SIZE);
78433d6423SLionel Sambuc 		if (size <= 0)
79433d6423SLionel Sambuc 			return EINVAL;
80433d6423SLionel Sambuc 
814d272e5aSDavid van Moolenbroek 		/* Find a free entry. */
824d272e5aSDavid van Moolenbroek 		for (i = 0; i < __arraycount(shm_list); i++)
834d272e5aSDavid van Moolenbroek 			if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
844d272e5aSDavid van Moolenbroek 				break;
854d272e5aSDavid van Moolenbroek 		if (i == __arraycount(shm_list))
86433d6423SLionel Sambuc 			return ENOSPC;
87433d6423SLionel Sambuc 
884d272e5aSDavid van Moolenbroek 		/*
894d272e5aSDavid van Moolenbroek 		 * Allocate memory to share.  For now, we store the page
904d272e5aSDavid van Moolenbroek 		 * reference as a numerical value so as to avoid issues with
914d272e5aSDavid van Moolenbroek 		 * live update.  TODO: a proper solution.
924d272e5aSDavid van Moolenbroek 		 */
934d272e5aSDavid van Moolenbroek 		page = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
944d272e5aSDavid van Moolenbroek 		if (page == MAP_FAILED)
954d272e5aSDavid van Moolenbroek 			return ENOMEM;
964d272e5aSDavid van Moolenbroek 		memset(page, 0, size);
974d272e5aSDavid van Moolenbroek 
984d272e5aSDavid van Moolenbroek 		/* Initialize the entry. */
994d272e5aSDavid van Moolenbroek 		shm = &shm_list[i];
1004d272e5aSDavid van Moolenbroek 		seq = shm->shmid_ds.shm_perm._seq;
101*0baafa0eSDavid van Moolenbroek 		memset(shm, 0, sizeof(*shm));
1024d272e5aSDavid van Moolenbroek 
1034d272e5aSDavid van Moolenbroek 		shm->shmid_ds.shm_perm._key = key;
104433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.cuid =
105*0baafa0eSDavid van Moolenbroek 			shm->shmid_ds.shm_perm.uid = getnuid(m->m_source);
106433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.cgid =
107*0baafa0eSDavid van Moolenbroek 			shm->shmid_ds.shm_perm.gid = getngid(m->m_source);
1084d272e5aSDavid van Moolenbroek 		shm->shmid_ds.shm_perm.mode = SHM_ALLOC | (flag & ACCESSPERMS);
1094d272e5aSDavid van Moolenbroek 		shm->shmid_ds.shm_perm._seq = (seq + 1) & 0x7fff;
110433d6423SLionel Sambuc 		shm->shmid_ds.shm_segsz = old_size;
111433d6423SLionel Sambuc 		shm->shmid_ds.shm_atime = 0;
112433d6423SLionel Sambuc 		shm->shmid_ds.shm_dtime = 0;
1134d272e5aSDavid van Moolenbroek 		shm->shmid_ds.shm_ctime = clock_time(NULL);
114*0baafa0eSDavid van Moolenbroek 		shm->shmid_ds.shm_cpid = getnpid(m->m_source);
115433d6423SLionel Sambuc 		shm->shmid_ds.shm_lpid = 0;
116433d6423SLionel Sambuc 		shm->shmid_ds.shm_nattch = 0;
1174d272e5aSDavid van Moolenbroek 		shm->page = (vir_bytes)page;
1184d272e5aSDavid van Moolenbroek 		shm->vm_id = vm_getphys(sef_self(), page);
119433d6423SLionel Sambuc 
1204d272e5aSDavid van Moolenbroek 		assert(i <= shm_list_nr);
1214d272e5aSDavid van Moolenbroek 		if (i == shm_list_nr)
122433d6423SLionel Sambuc 			shm_list_nr++;
123433d6423SLionel Sambuc 	}
124433d6423SLionel Sambuc 
1254d272e5aSDavid van Moolenbroek 	m->m_lc_ipc_shmget.retid = IXSEQ_TO_IPCID(i, shm->shmid_ds.shm_perm);
126433d6423SLionel Sambuc 	return OK;
127433d6423SLionel Sambuc }
128433d6423SLionel Sambuc 
129*0baafa0eSDavid van Moolenbroek int
130*0baafa0eSDavid van Moolenbroek do_shmat(message * m)
131433d6423SLionel Sambuc {
132433d6423SLionel Sambuc 	int id, flag;
133433d6423SLionel Sambuc 	vir_bytes addr;
134433d6423SLionel Sambuc 	void *ret;
135433d6423SLionel Sambuc 	struct shm_struct *shm;
136433d6423SLionel Sambuc 
137433d6423SLionel Sambuc 	id = m->m_lc_ipc_shmat.id;
138433d6423SLionel Sambuc 	addr = (vir_bytes)m->m_lc_ipc_shmat.addr;
139433d6423SLionel Sambuc 	flag = m->m_lc_ipc_shmat.flag;
140433d6423SLionel Sambuc 
141*0baafa0eSDavid van Moolenbroek 	if (addr % PAGE_SIZE) {
142433d6423SLionel Sambuc 		if (flag & SHM_RND)
143*0baafa0eSDavid van Moolenbroek 			addr -= addr % PAGE_SIZE;
144433d6423SLionel Sambuc 		else
145433d6423SLionel Sambuc 			return EINVAL;
146433d6423SLionel Sambuc 	}
147433d6423SLionel Sambuc 
148*0baafa0eSDavid van Moolenbroek 	if ((shm = shm_find_id(id)) == NULL)
149433d6423SLionel Sambuc 		return EINVAL;
150433d6423SLionel Sambuc 
151433d6423SLionel Sambuc 	if (flag & SHM_RDONLY)
152433d6423SLionel Sambuc 		flag = 0444;
153433d6423SLionel Sambuc 	else
154433d6423SLionel Sambuc 		flag = 0666;
155*0baafa0eSDavid van Moolenbroek 	if (!check_perm(&shm->shmid_ds.shm_perm, m->m_source, flag))
156433d6423SLionel Sambuc 		return EACCES;
157433d6423SLionel Sambuc 
158*0baafa0eSDavid van Moolenbroek 	ret = vm_remap(m->m_source, sef_self(), (void *)addr,
159*0baafa0eSDavid van Moolenbroek 	    (void *)shm->page, shm->shmid_ds.shm_segsz);
160433d6423SLionel Sambuc 	if (ret == MAP_FAILED)
161433d6423SLionel Sambuc 		return ENOMEM;
162433d6423SLionel Sambuc 
1634d272e5aSDavid van Moolenbroek 	shm->shmid_ds.shm_atime = clock_time(NULL);
164*0baafa0eSDavid van Moolenbroek 	shm->shmid_ds.shm_lpid = getnpid(m->m_source);
165*0baafa0eSDavid van Moolenbroek 	/* nattch is updated lazily */
166433d6423SLionel Sambuc 
167433d6423SLionel Sambuc 	m->m_lc_ipc_shmat.retaddr = ret;
168433d6423SLionel Sambuc 	return OK;
169433d6423SLionel Sambuc }
170433d6423SLionel Sambuc 
171*0baafa0eSDavid van Moolenbroek void
172*0baafa0eSDavid van Moolenbroek update_refcount_and_destroy(void)
173433d6423SLionel Sambuc {
174433d6423SLionel Sambuc 	u8_t rc;
1754d272e5aSDavid van Moolenbroek 	unsigned int i;
1764d272e5aSDavid van Moolenbroek 
1774d272e5aSDavid van Moolenbroek 	for (i = 0; i < shm_list_nr; i++) {
1784d272e5aSDavid van Moolenbroek 		if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
1794d272e5aSDavid van Moolenbroek 			continue;
180433d6423SLionel Sambuc 
181433d6423SLionel Sambuc 		rc = vm_getrefcount(sef_self(), (void *)shm_list[i].page);
182433d6423SLionel Sambuc 		if (rc == (u8_t)-1) {
183433d6423SLionel Sambuc 			printf("IPC: can't find physical region.\n");
184433d6423SLionel Sambuc 			continue;
185433d6423SLionel Sambuc 		}
186433d6423SLionel Sambuc 		shm_list[i].shmid_ds.shm_nattch = rc - 1;
187433d6423SLionel Sambuc 
1884d272e5aSDavid van Moolenbroek 		if (shm_list[i].shmid_ds.shm_nattch == 0 &&
1894d272e5aSDavid van Moolenbroek 		    (shm_list[i].shmid_ds.shm_perm.mode & SHM_DEST)) {
190*0baafa0eSDavid van Moolenbroek 			munmap((void *)shm_list[i].page,
191*0baafa0eSDavid van Moolenbroek 			    roundup(shm_list[i].shmid_ds.shm_segsz,
192*0baafa0eSDavid van Moolenbroek 			    PAGE_SIZE));
1934d272e5aSDavid van Moolenbroek 			/* Mark the entry as free. */
1944d272e5aSDavid van Moolenbroek 			shm_list[i].shmid_ds.shm_perm.mode &= ~SHM_ALLOC;
195433d6423SLionel Sambuc 		}
196433d6423SLionel Sambuc 	}
1974d272e5aSDavid van Moolenbroek 
1984d272e5aSDavid van Moolenbroek 	/*
1994d272e5aSDavid van Moolenbroek 	 * Now that we may have removed an arbitrary set of slots, ensure that
2004d272e5aSDavid van Moolenbroek 	 * shm_list_nr again equals the highest in-use slot number plus one.
2014d272e5aSDavid van Moolenbroek 	 */
2024d272e5aSDavid van Moolenbroek 	while (shm_list_nr > 0 &&
2034d272e5aSDavid van Moolenbroek 	    !(shm_list[shm_list_nr - 1].shmid_ds.shm_perm.mode & SHM_ALLOC))
2044d272e5aSDavid van Moolenbroek 		shm_list_nr--;
205433d6423SLionel Sambuc }
206433d6423SLionel Sambuc 
207*0baafa0eSDavid van Moolenbroek int
208*0baafa0eSDavid van Moolenbroek do_shmdt(message * m)
209433d6423SLionel Sambuc {
2104d272e5aSDavid van Moolenbroek 	struct shm_struct *shm;
211433d6423SLionel Sambuc 	vir_bytes addr;
212433d6423SLionel Sambuc 	phys_bytes vm_id;
2134d272e5aSDavid van Moolenbroek 	unsigned int i;
214433d6423SLionel Sambuc 
215433d6423SLionel Sambuc 	addr = (vir_bytes)m->m_lc_ipc_shmdt.addr;
216433d6423SLionel Sambuc 
217*0baafa0eSDavid van Moolenbroek 	if ((vm_id = vm_getphys(m->m_source, (void *)addr)) == 0)
218433d6423SLionel Sambuc 		return EINVAL;
219433d6423SLionel Sambuc 
220433d6423SLionel Sambuc 	for (i = 0; i < shm_list_nr; i++) {
2214d272e5aSDavid van Moolenbroek 		shm = &shm_list[i];
222433d6423SLionel Sambuc 
2234d272e5aSDavid van Moolenbroek 		if (!(shm->shmid_ds.shm_perm.mode & SHM_ALLOC))
2244d272e5aSDavid van Moolenbroek 			continue;
2254d272e5aSDavid van Moolenbroek 
2264d272e5aSDavid van Moolenbroek 		if (shm->vm_id == vm_id) {
2274d272e5aSDavid van Moolenbroek 			shm->shmid_ds.shm_atime = clock_time(NULL);
228*0baafa0eSDavid van Moolenbroek 			shm->shmid_ds.shm_lpid = getnpid(m->m_source);
229433d6423SLionel Sambuc 			/* nattch is updated lazily */
230433d6423SLionel Sambuc 
231*0baafa0eSDavid van Moolenbroek 			vm_unmap(m->m_source, (void *)addr);
232433d6423SLionel Sambuc 			break;
233433d6423SLionel Sambuc 		}
234433d6423SLionel Sambuc 	}
235433d6423SLionel Sambuc 	if (i == shm_list_nr)
236*0baafa0eSDavid van Moolenbroek 		printf("IPC: do_shmdt: ID %lu not found\n", vm_id);
237433d6423SLionel Sambuc 
238433d6423SLionel Sambuc 	update_refcount_and_destroy();
239433d6423SLionel Sambuc 
240433d6423SLionel Sambuc 	return OK;
241433d6423SLionel Sambuc }
242433d6423SLionel Sambuc 
243*0baafa0eSDavid van Moolenbroek int
244*0baafa0eSDavid van Moolenbroek do_shmctl(message * m)
245433d6423SLionel Sambuc {
246433d6423SLionel Sambuc 	struct shmid_ds tmp_ds;
2474d272e5aSDavid van Moolenbroek 	struct shm_struct *shm;
248433d6423SLionel Sambuc 	struct shminfo sinfo;
249433d6423SLionel Sambuc 	struct shm_info s_info;
250*0baafa0eSDavid van Moolenbroek 	vir_bytes buf;
2514d272e5aSDavid van Moolenbroek 	unsigned int i;
252433d6423SLionel Sambuc 	uid_t uid;
2534d272e5aSDavid van Moolenbroek 	int r, id, cmd;
254433d6423SLionel Sambuc 
2554d272e5aSDavid van Moolenbroek 	id = m->m_lc_ipc_shmctl.id;
2564d272e5aSDavid van Moolenbroek 	cmd = m->m_lc_ipc_shmctl.cmd;
257*0baafa0eSDavid van Moolenbroek 	buf = (vir_bytes)m->m_lc_ipc_shmctl.buf;
2584d272e5aSDavid van Moolenbroek 
2594d272e5aSDavid van Moolenbroek 	/*
2604d272e5aSDavid van Moolenbroek 	 * For stat calls, sure that all information is up-to-date.  Since this
2614d272e5aSDavid van Moolenbroek 	 * may free the slot, do this before mapping from ID to slot below.
2624d272e5aSDavid van Moolenbroek 	 */
2634d272e5aSDavid van Moolenbroek 	if (cmd == IPC_STAT || cmd == SHM_STAT)
264433d6423SLionel Sambuc 		update_refcount_and_destroy();
265433d6423SLionel Sambuc 
2664d272e5aSDavid van Moolenbroek 	switch (cmd) {
2674d272e5aSDavid van Moolenbroek 	case IPC_INFO:
2684d272e5aSDavid van Moolenbroek 	case SHM_INFO:
2694d272e5aSDavid van Moolenbroek 		shm = NULL;
2704d272e5aSDavid van Moolenbroek 		break;
2714d272e5aSDavid van Moolenbroek 	case SHM_STAT:
2724d272e5aSDavid van Moolenbroek 		if (id < 0 || (unsigned int)id >= shm_list_nr)
273433d6423SLionel Sambuc 			return EINVAL;
2744d272e5aSDavid van Moolenbroek 		shm = &shm_list[id];
2754d272e5aSDavid van Moolenbroek 		if (!(shm->shmid_ds.shm_perm.mode & SHM_ALLOC))
2764d272e5aSDavid van Moolenbroek 			return EINVAL;
2774d272e5aSDavid van Moolenbroek 		break;
2784d272e5aSDavid van Moolenbroek 	default:
279*0baafa0eSDavid van Moolenbroek 		if ((shm = shm_find_id(id)) == NULL)
2804d272e5aSDavid van Moolenbroek 			return EINVAL;
2814d272e5aSDavid van Moolenbroek 		break;
2824d272e5aSDavid van Moolenbroek 	}
283433d6423SLionel Sambuc 
284433d6423SLionel Sambuc 	switch (cmd) {
285433d6423SLionel Sambuc 	case IPC_STAT:
2864d272e5aSDavid van Moolenbroek 	case SHM_STAT:
2874d272e5aSDavid van Moolenbroek 		/* Check whether the caller has read permission. */
288*0baafa0eSDavid van Moolenbroek 		if (!check_perm(&shm->shmid_ds.shm_perm, m->m_source, 0444))
289433d6423SLionel Sambuc 			return EACCES;
290*0baafa0eSDavid van Moolenbroek 		if ((r = sys_datacopy(SELF, (vir_bytes)&shm->shmid_ds,
291*0baafa0eSDavid van Moolenbroek 		    m->m_source, buf, sizeof(shm->shmid_ds))) != OK)
2924d272e5aSDavid van Moolenbroek 			return r;
2934d272e5aSDavid van Moolenbroek 		if (cmd == SHM_STAT)
2944d272e5aSDavid van Moolenbroek 			m->m_lc_ipc_shmctl.ret =
2954d272e5aSDavid van Moolenbroek 			    IXSEQ_TO_IPCID(id, shm->shmid_ds.shm_perm);
296433d6423SLionel Sambuc 		break;
297433d6423SLionel Sambuc 	case IPC_SET:
298*0baafa0eSDavid van Moolenbroek 		uid = getnuid(m->m_source);
299433d6423SLionel Sambuc 		if (uid != shm->shmid_ds.shm_perm.cuid &&
300*0baafa0eSDavid van Moolenbroek 		    uid != shm->shmid_ds.shm_perm.uid && uid != 0)
301433d6423SLionel Sambuc 			return EPERM;
302*0baafa0eSDavid van Moolenbroek 		if ((r = sys_datacopy(m->m_source, buf, SELF,
303*0baafa0eSDavid van Moolenbroek 		    (vir_bytes)&tmp_ds, sizeof(tmp_ds))) != OK)
3044d272e5aSDavid van Moolenbroek 			return r;
305433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.uid = tmp_ds.shm_perm.uid;
306433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.gid = tmp_ds.shm_perm.gid;
3074d272e5aSDavid van Moolenbroek 		shm->shmid_ds.shm_perm.mode &= ~ACCESSPERMS;
3084d272e5aSDavid van Moolenbroek 		shm->shmid_ds.shm_perm.mode |=
3094d272e5aSDavid van Moolenbroek 		    tmp_ds.shm_perm.mode & ACCESSPERMS;
3104d272e5aSDavid van Moolenbroek 		shm->shmid_ds.shm_ctime = clock_time(NULL);
311433d6423SLionel Sambuc 		break;
312433d6423SLionel Sambuc 	case IPC_RMID:
313*0baafa0eSDavid van Moolenbroek 		uid = getnuid(m->m_source);
314433d6423SLionel Sambuc 		if (uid != shm->shmid_ds.shm_perm.cuid &&
315*0baafa0eSDavid van Moolenbroek 		    uid != shm->shmid_ds.shm_perm.uid && uid != 0)
316433d6423SLionel Sambuc 			return EPERM;
317433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.mode |= SHM_DEST;
318*0baafa0eSDavid van Moolenbroek 		/* Destroy if possible. */
319433d6423SLionel Sambuc 		update_refcount_and_destroy();
320433d6423SLionel Sambuc 		break;
321433d6423SLionel Sambuc 	case IPC_INFO:
3224d272e5aSDavid van Moolenbroek 		memset(&sinfo, 0, sizeof(sinfo));
323433d6423SLionel Sambuc 		sinfo.shmmax = (unsigned long) -1;
324433d6423SLionel Sambuc 		sinfo.shmmin = 1;
3254d272e5aSDavid van Moolenbroek 		sinfo.shmmni = __arraycount(shm_list);
326433d6423SLionel Sambuc 		sinfo.shmseg = (unsigned long) -1;
327433d6423SLionel Sambuc 		sinfo.shmall = (unsigned long) -1;
328*0baafa0eSDavid van Moolenbroek 		if ((r = sys_datacopy(SELF, (vir_bytes)&sinfo, m->m_source,
329*0baafa0eSDavid van Moolenbroek 		    buf, sizeof(sinfo))) != OK)
3304d272e5aSDavid van Moolenbroek 			return r;
3314d272e5aSDavid van Moolenbroek 		if (shm_list_nr > 0)
3324d272e5aSDavid van Moolenbroek 			m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
3334d272e5aSDavid van Moolenbroek 		else
334433d6423SLionel Sambuc 			m->m_lc_ipc_shmctl.ret = 0;
335433d6423SLionel Sambuc 		break;
336433d6423SLionel Sambuc 	case SHM_INFO:
3374d272e5aSDavid van Moolenbroek 		memset(&s_info, 0, sizeof(s_info));
338433d6423SLionel Sambuc 		s_info.used_ids = shm_list_nr;
339433d6423SLionel Sambuc 		s_info.shm_tot = 0;
340433d6423SLionel Sambuc 		for (i = 0; i < shm_list_nr; i++)
341433d6423SLionel Sambuc 			s_info.shm_tot +=
342433d6423SLionel Sambuc 			    shm_list[i].shmid_ds.shm_segsz / PAGE_SIZE;
343433d6423SLionel Sambuc 		s_info.shm_rss = s_info.shm_tot;
344433d6423SLionel Sambuc 		s_info.shm_swp = 0;
345433d6423SLionel Sambuc 		s_info.swap_attempts = 0;
346433d6423SLionel Sambuc 		s_info.swap_successes = 0;
347*0baafa0eSDavid van Moolenbroek 		if ((r = sys_datacopy(SELF, (vir_bytes)&s_info, m->m_source,
348*0baafa0eSDavid van Moolenbroek 		    buf, sizeof(s_info))) != OK)
3494d272e5aSDavid van Moolenbroek 			return r;
3504d272e5aSDavid van Moolenbroek 		if (shm_list_nr > 0)
351433d6423SLionel Sambuc 			m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
3524d272e5aSDavid van Moolenbroek 		else
353433d6423SLionel Sambuc 			m->m_lc_ipc_shmctl.ret = 0;
354433d6423SLionel Sambuc 		break;
355433d6423SLionel Sambuc 	default:
356433d6423SLionel Sambuc 		return EINVAL;
357433d6423SLionel Sambuc 	}
358433d6423SLionel Sambuc 	return OK;
359433d6423SLionel Sambuc }
360433d6423SLionel Sambuc 
361433d6423SLionel Sambuc #if 0
362*0baafa0eSDavid van Moolenbroek static void
363*0baafa0eSDavid van Moolenbroek list_shm_ds(void)
364433d6423SLionel Sambuc {
3654d272e5aSDavid van Moolenbroek 	unsigned int i;
366*0baafa0eSDavid van Moolenbroek 
367433d6423SLionel Sambuc 	printf("key\tid\tpage\n");
3684d272e5aSDavid van Moolenbroek 	for (i = 0; i < shm_list_nr; i++) {
3694d272e5aSDavid van Moolenbroek 		if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
3704d272e5aSDavid van Moolenbroek 			continue;
371433d6423SLionel Sambuc 		printf("%ld\t%d\t%lx\n",
3724d272e5aSDavid van Moolenbroek 		    shm_list[i].shmid_ds.shm_perm._key,
3734d272e5aSDavid van Moolenbroek 		    IXSEQ_TO_IPCID(i, shm_list[i].shmid_ds.shm_perm),
374433d6423SLionel Sambuc 		    shm_list[i].page);
375433d6423SLionel Sambuc 	}
3764d272e5aSDavid van Moolenbroek }
377433d6423SLionel Sambuc #endif
378433d6423SLionel Sambuc 
379*0baafa0eSDavid van Moolenbroek int
380*0baafa0eSDavid van Moolenbroek is_shm_nil(void)
381433d6423SLionel Sambuc {
382*0baafa0eSDavid van Moolenbroek 
383433d6423SLionel Sambuc 	return (shm_list_nr == 0);
384433d6423SLionel Sambuc }
385