xref: /minix3/minix/servers/ipc/shm.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc #include "inc.h"
2*433d6423SLionel Sambuc 
3*433d6423SLionel Sambuc #define MAX_SHM_NR 1024
4*433d6423SLionel Sambuc 
5*433d6423SLionel Sambuc struct shm_struct {
6*433d6423SLionel Sambuc 	key_t key;
7*433d6423SLionel Sambuc 	int id;
8*433d6423SLionel Sambuc 	struct shmid_ds shmid_ds;
9*433d6423SLionel Sambuc 	vir_bytes page;
10*433d6423SLionel Sambuc 	int vm_id;
11*433d6423SLionel Sambuc };
12*433d6423SLionel Sambuc static struct shm_struct shm_list[MAX_SHM_NR];
13*433d6423SLionel Sambuc static int shm_list_nr = 0;
14*433d6423SLionel Sambuc 
15*433d6423SLionel Sambuc static struct shm_struct *shm_find_key(key_t key)
16*433d6423SLionel Sambuc {
17*433d6423SLionel Sambuc 	int i;
18*433d6423SLionel Sambuc 	if (key == IPC_PRIVATE)
19*433d6423SLionel Sambuc 		return NULL;
20*433d6423SLionel Sambuc 	for (i = 0; i < shm_list_nr; i++)
21*433d6423SLionel Sambuc 		if (shm_list[i].key == key)
22*433d6423SLionel Sambuc 			return shm_list+i;
23*433d6423SLionel Sambuc 	return NULL;
24*433d6423SLionel Sambuc }
25*433d6423SLionel Sambuc 
26*433d6423SLionel Sambuc static struct shm_struct *shm_find_id(int id)
27*433d6423SLionel Sambuc {
28*433d6423SLionel Sambuc 	int i;
29*433d6423SLionel Sambuc 	for (i = 0; i < shm_list_nr; i++)
30*433d6423SLionel Sambuc 		if (shm_list[i].id == id)
31*433d6423SLionel Sambuc 			return shm_list+i;
32*433d6423SLionel Sambuc 	return NULL;
33*433d6423SLionel Sambuc }
34*433d6423SLionel Sambuc 
35*433d6423SLionel Sambuc /*===========================================================================*
36*433d6423SLionel Sambuc  *				do_shmget		     		     *
37*433d6423SLionel Sambuc  *===========================================================================*/
38*433d6423SLionel Sambuc int do_shmget(message *m)
39*433d6423SLionel Sambuc {
40*433d6423SLionel Sambuc 	struct shm_struct *shm;
41*433d6423SLionel Sambuc 	long key, size, old_size;
42*433d6423SLionel Sambuc 	int flag;
43*433d6423SLionel Sambuc 	int id;
44*433d6423SLionel Sambuc 
45*433d6423SLionel Sambuc 	key = m->m_lc_ipc_shmget.key;
46*433d6423SLionel Sambuc 	old_size = size = m->m_lc_ipc_shmget.size;
47*433d6423SLionel Sambuc 	flag = m->m_lc_ipc_shmget.flag;
48*433d6423SLionel Sambuc 
49*433d6423SLionel Sambuc 	if ((shm = shm_find_key(key))) {
50*433d6423SLionel Sambuc 		if (!check_perm(&shm->shmid_ds.shm_perm, who_e, flag))
51*433d6423SLionel Sambuc 			return EACCES;
52*433d6423SLionel Sambuc 		if ((flag & IPC_CREAT) && (flag & IPC_EXCL))
53*433d6423SLionel Sambuc 			return EEXIST;
54*433d6423SLionel Sambuc 		if (size && shm->shmid_ds.shm_segsz < size)
55*433d6423SLionel Sambuc 			return EINVAL;
56*433d6423SLionel Sambuc 		id = shm->id;
57*433d6423SLionel Sambuc 	} else { /* no key found */
58*433d6423SLionel Sambuc 		if (!(flag & IPC_CREAT))
59*433d6423SLionel Sambuc 			return ENOENT;
60*433d6423SLionel Sambuc 		if (size <= 0)
61*433d6423SLionel Sambuc 			return EINVAL;
62*433d6423SLionel Sambuc 		/* round up to a multiple of PAGE_SIZE */
63*433d6423SLionel Sambuc 		if (size % PAGE_SIZE)
64*433d6423SLionel Sambuc 			size += PAGE_SIZE - size % PAGE_SIZE;
65*433d6423SLionel Sambuc 		if (size <= 0)
66*433d6423SLionel Sambuc 			return EINVAL;
67*433d6423SLionel Sambuc 
68*433d6423SLionel Sambuc 		if (shm_list_nr == MAX_SHM_NR)
69*433d6423SLionel Sambuc 			return ENOMEM;
70*433d6423SLionel Sambuc 		/* TODO: shmmni should be changed... */
71*433d6423SLionel Sambuc 		if (identifier == SHMMNI)
72*433d6423SLionel Sambuc 			return ENOSPC;
73*433d6423SLionel Sambuc 		shm = &shm_list[shm_list_nr];
74*433d6423SLionel Sambuc 		memset(shm, 0, sizeof(struct shm_struct));
75*433d6423SLionel Sambuc 		shm->page = (vir_bytes) mmap(0, size,
76*433d6423SLionel Sambuc 					PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
77*433d6423SLionel Sambuc 		if (shm->page == (vir_bytes) MAP_FAILED)
78*433d6423SLionel Sambuc 			return ENOMEM;
79*433d6423SLionel Sambuc 		shm->vm_id = vm_getphys(sef_self(), (void *) shm->page);
80*433d6423SLionel Sambuc 		memset((void *)shm->page, 0, size);
81*433d6423SLionel Sambuc 
82*433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.cuid =
83*433d6423SLionel Sambuc 			shm->shmid_ds.shm_perm.uid = getnuid(who_e);
84*433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.cgid =
85*433d6423SLionel Sambuc 			shm->shmid_ds.shm_perm.gid = getngid(who_e);
86*433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.mode = flag & 0777;
87*433d6423SLionel Sambuc 		shm->shmid_ds.shm_segsz = old_size;
88*433d6423SLionel Sambuc 		shm->shmid_ds.shm_atime = 0;
89*433d6423SLionel Sambuc 		shm->shmid_ds.shm_dtime = 0;
90*433d6423SLionel Sambuc 		shm->shmid_ds.shm_ctime = time(NULL);
91*433d6423SLionel Sambuc 		shm->shmid_ds.shm_cpid = getnpid(who_e);
92*433d6423SLionel Sambuc 		shm->shmid_ds.shm_lpid = 0;
93*433d6423SLionel Sambuc 		shm->shmid_ds.shm_nattch = 0;
94*433d6423SLionel Sambuc 		shm->id = id = identifier++;
95*433d6423SLionel Sambuc 		shm->key = key;
96*433d6423SLionel Sambuc 
97*433d6423SLionel Sambuc 		shm_list_nr++;
98*433d6423SLionel Sambuc 	}
99*433d6423SLionel Sambuc 
100*433d6423SLionel Sambuc 	m->m_lc_ipc_shmget.retid = id;
101*433d6423SLionel Sambuc 	return OK;
102*433d6423SLionel Sambuc }
103*433d6423SLionel Sambuc 
104*433d6423SLionel Sambuc /*===========================================================================*
105*433d6423SLionel Sambuc  *				do_shmat		     		     *
106*433d6423SLionel Sambuc  *===========================================================================*/
107*433d6423SLionel Sambuc int do_shmat(message *m)
108*433d6423SLionel Sambuc {
109*433d6423SLionel Sambuc 	int id, flag;
110*433d6423SLionel Sambuc 	vir_bytes addr;
111*433d6423SLionel Sambuc 	void *ret;
112*433d6423SLionel Sambuc 	struct shm_struct *shm;
113*433d6423SLionel Sambuc 
114*433d6423SLionel Sambuc 	id = m->m_lc_ipc_shmat.id;
115*433d6423SLionel Sambuc 	addr = (vir_bytes) m->m_lc_ipc_shmat.addr;
116*433d6423SLionel Sambuc 	flag = m->m_lc_ipc_shmat.flag;
117*433d6423SLionel Sambuc 
118*433d6423SLionel Sambuc 	if (addr && (addr % PAGE_SIZE)) {
119*433d6423SLionel Sambuc 		if (flag & SHM_RND)
120*433d6423SLionel Sambuc 			addr -= (addr % PAGE_SIZE);
121*433d6423SLionel Sambuc 		else
122*433d6423SLionel Sambuc 			return EINVAL;
123*433d6423SLionel Sambuc 	}
124*433d6423SLionel Sambuc 
125*433d6423SLionel Sambuc 	if (!(shm = shm_find_id(id)))
126*433d6423SLionel Sambuc 		return EINVAL;
127*433d6423SLionel Sambuc 
128*433d6423SLionel Sambuc 	if (flag & SHM_RDONLY)
129*433d6423SLionel Sambuc 		flag = 0444;
130*433d6423SLionel Sambuc 	else
131*433d6423SLionel Sambuc 		flag = 0666;
132*433d6423SLionel Sambuc 	if (!check_perm(&shm->shmid_ds.shm_perm, who_e, flag))
133*433d6423SLionel Sambuc 		return EACCES;
134*433d6423SLionel Sambuc 
135*433d6423SLionel Sambuc 	ret = vm_remap(who_e, sef_self(), (void *)addr, (void *)shm->page,
136*433d6423SLionel Sambuc 			shm->shmid_ds.shm_segsz);
137*433d6423SLionel Sambuc 	if (ret == MAP_FAILED)
138*433d6423SLionel Sambuc 		return ENOMEM;
139*433d6423SLionel Sambuc 
140*433d6423SLionel Sambuc 	shm->shmid_ds.shm_atime = time(NULL);
141*433d6423SLionel Sambuc 	shm->shmid_ds.shm_lpid = getnpid(who_e);
142*433d6423SLionel Sambuc 	/* nattach is updated lazily */
143*433d6423SLionel Sambuc 
144*433d6423SLionel Sambuc 	m->m_lc_ipc_shmat.retaddr = ret;
145*433d6423SLionel Sambuc 	return OK;
146*433d6423SLionel Sambuc }
147*433d6423SLionel Sambuc 
148*433d6423SLionel Sambuc /*===========================================================================*
149*433d6423SLionel Sambuc  *				update_refcount_and_destroy		     *
150*433d6423SLionel Sambuc  *===========================================================================*/
151*433d6423SLionel Sambuc void update_refcount_and_destroy(void)
152*433d6423SLionel Sambuc {
153*433d6423SLionel Sambuc 	int i, j;
154*433d6423SLionel Sambuc 
155*433d6423SLionel Sambuc 	for (i = 0, j = 0; i < shm_list_nr; i++) {
156*433d6423SLionel Sambuc 		u8_t rc;
157*433d6423SLionel Sambuc 
158*433d6423SLionel Sambuc 		rc = vm_getrefcount(sef_self(), (void *) shm_list[i].page);
159*433d6423SLionel Sambuc 		if (rc == (u8_t) -1) {
160*433d6423SLionel Sambuc 			printf("IPC: can't find physical region.\n");
161*433d6423SLionel Sambuc 			continue;
162*433d6423SLionel Sambuc 		}
163*433d6423SLionel Sambuc 		shm_list[i].shmid_ds.shm_nattch = rc - 1;
164*433d6423SLionel Sambuc 
165*433d6423SLionel Sambuc 		if (shm_list[i].shmid_ds.shm_nattch ||
166*433d6423SLionel Sambuc 			!(shm_list[i].shmid_ds.shm_perm.mode & SHM_DEST)) {
167*433d6423SLionel Sambuc 			if (i != j)
168*433d6423SLionel Sambuc 				shm_list[j] = shm_list[i];
169*433d6423SLionel Sambuc 			j++;
170*433d6423SLionel Sambuc 		} else {
171*433d6423SLionel Sambuc 			int size = shm_list[i].shmid_ds.shm_segsz;
172*433d6423SLionel Sambuc 			if (size % PAGE_SIZE)
173*433d6423SLionel Sambuc 				size += PAGE_SIZE - size % PAGE_SIZE;
174*433d6423SLionel Sambuc 			munmap((void *)shm_list[i].page, size);
175*433d6423SLionel Sambuc 		}
176*433d6423SLionel Sambuc 	}
177*433d6423SLionel Sambuc 	shm_list_nr = j;
178*433d6423SLionel Sambuc }
179*433d6423SLionel Sambuc 
180*433d6423SLionel Sambuc /*===========================================================================*
181*433d6423SLionel Sambuc  *				do_shmdt		     		     *
182*433d6423SLionel Sambuc  *===========================================================================*/
183*433d6423SLionel Sambuc int do_shmdt(message *m)
184*433d6423SLionel Sambuc {
185*433d6423SLionel Sambuc 	vir_bytes addr;
186*433d6423SLionel Sambuc 	phys_bytes vm_id;
187*433d6423SLionel Sambuc 	int i;
188*433d6423SLionel Sambuc 
189*433d6423SLionel Sambuc 	addr = (vir_bytes) m->m_lc_ipc_shmdt.addr;
190*433d6423SLionel Sambuc 
191*433d6423SLionel Sambuc 	if ((vm_id = vm_getphys(who_e, (void *) addr)) == 0)
192*433d6423SLionel Sambuc 		return EINVAL;
193*433d6423SLionel Sambuc 
194*433d6423SLionel Sambuc 	for (i = 0; i < shm_list_nr; i++) {
195*433d6423SLionel Sambuc 		if (shm_list[i].vm_id == vm_id) {
196*433d6423SLionel Sambuc 			struct shm_struct *shm = &shm_list[i];
197*433d6423SLionel Sambuc 
198*433d6423SLionel Sambuc 			shm->shmid_ds.shm_atime = time(NULL);
199*433d6423SLionel Sambuc 			shm->shmid_ds.shm_lpid = getnpid(who_e);
200*433d6423SLionel Sambuc 			/* nattch is updated lazily */
201*433d6423SLionel Sambuc 
202*433d6423SLionel Sambuc 			vm_unmap(who_e, (void *) addr);
203*433d6423SLionel Sambuc 			break;
204*433d6423SLionel Sambuc 		}
205*433d6423SLionel Sambuc 	}
206*433d6423SLionel Sambuc 	if (i == shm_list_nr)
207*433d6423SLionel Sambuc 		printf("IPC: do_shmdt impossible error! could not find id %lu to unmap\n",
208*433d6423SLionel Sambuc 			vm_id);
209*433d6423SLionel Sambuc 
210*433d6423SLionel Sambuc 	update_refcount_and_destroy();
211*433d6423SLionel Sambuc 
212*433d6423SLionel Sambuc 	return OK;
213*433d6423SLionel Sambuc }
214*433d6423SLionel Sambuc 
215*433d6423SLionel Sambuc /*===========================================================================*
216*433d6423SLionel Sambuc  *				do_shmctl		     		     *
217*433d6423SLionel Sambuc  *===========================================================================*/
218*433d6423SLionel Sambuc int do_shmctl(message *m)
219*433d6423SLionel Sambuc {
220*433d6423SLionel Sambuc 	int id = m->m_lc_ipc_shmctl.id;
221*433d6423SLionel Sambuc 	int cmd = m->m_lc_ipc_shmctl.cmd;
222*433d6423SLionel Sambuc 	struct shmid_ds *ds = (struct shmid_ds *)m->m_lc_ipc_shmctl.buf;
223*433d6423SLionel Sambuc 	struct shmid_ds tmp_ds;
224*433d6423SLionel Sambuc 	struct shm_struct *shm = NULL;
225*433d6423SLionel Sambuc 	struct shminfo sinfo;
226*433d6423SLionel Sambuc 	struct shm_info s_info;
227*433d6423SLionel Sambuc 	uid_t uid;
228*433d6423SLionel Sambuc 	int r, i;
229*433d6423SLionel Sambuc 
230*433d6423SLionel Sambuc 	if (cmd == IPC_STAT)
231*433d6423SLionel Sambuc 		update_refcount_and_destroy();
232*433d6423SLionel Sambuc 
233*433d6423SLionel Sambuc 	if ((cmd == IPC_STAT ||
234*433d6423SLionel Sambuc 		cmd == IPC_SET ||
235*433d6423SLionel Sambuc 		cmd == IPC_RMID) &&
236*433d6423SLionel Sambuc 		!(shm = shm_find_id(id)))
237*433d6423SLionel Sambuc 		return EINVAL;
238*433d6423SLionel Sambuc 
239*433d6423SLionel Sambuc 	switch (cmd) {
240*433d6423SLionel Sambuc 	case IPC_STAT:
241*433d6423SLionel Sambuc 		if (!ds)
242*433d6423SLionel Sambuc 			return EFAULT;
243*433d6423SLionel Sambuc 		/* check whether it has read permission */
244*433d6423SLionel Sambuc 		if (!check_perm(&shm->shmid_ds.shm_perm, who_e, 0444))
245*433d6423SLionel Sambuc 			return EACCES;
246*433d6423SLionel Sambuc 		r = sys_datacopy(SELF, (vir_bytes)&shm->shmid_ds,
247*433d6423SLionel Sambuc 			who_e, (vir_bytes)ds, sizeof(struct shmid_ds));
248*433d6423SLionel Sambuc 		if (r != OK)
249*433d6423SLionel Sambuc 			return EFAULT;
250*433d6423SLionel Sambuc 		break;
251*433d6423SLionel Sambuc 	case IPC_SET:
252*433d6423SLionel Sambuc 		uid = getnuid(who_e);
253*433d6423SLionel Sambuc 		if (uid != shm->shmid_ds.shm_perm.cuid &&
254*433d6423SLionel Sambuc 			uid != shm->shmid_ds.shm_perm.uid &&
255*433d6423SLionel Sambuc 			uid != 0)
256*433d6423SLionel Sambuc 			return EPERM;
257*433d6423SLionel Sambuc 		r = sys_datacopy(who_e, (vir_bytes)ds,
258*433d6423SLionel Sambuc 			SELF, (vir_bytes)&tmp_ds, sizeof(struct shmid_ds));
259*433d6423SLionel Sambuc 		if (r != OK)
260*433d6423SLionel Sambuc 			return EFAULT;
261*433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.uid = tmp_ds.shm_perm.uid;
262*433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.gid = tmp_ds.shm_perm.gid;
263*433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.mode &= ~0777;
264*433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.mode |= tmp_ds.shm_perm.mode & 0666;
265*433d6423SLionel Sambuc 		shm->shmid_ds.shm_ctime = time(NULL);
266*433d6423SLionel Sambuc 		break;
267*433d6423SLionel Sambuc 	case IPC_RMID:
268*433d6423SLionel Sambuc 		uid = getnuid(who_e);
269*433d6423SLionel Sambuc 		if (uid != shm->shmid_ds.shm_perm.cuid &&
270*433d6423SLionel Sambuc 			uid != shm->shmid_ds.shm_perm.uid &&
271*433d6423SLionel Sambuc 			uid != 0)
272*433d6423SLionel Sambuc 			return EPERM;
273*433d6423SLionel Sambuc 		shm->shmid_ds.shm_perm.mode |= SHM_DEST;
274*433d6423SLionel Sambuc 		/* destroy if possible */
275*433d6423SLionel Sambuc 		update_refcount_and_destroy();
276*433d6423SLionel Sambuc 		break;
277*433d6423SLionel Sambuc 	case IPC_INFO:
278*433d6423SLionel Sambuc 		if (!ds)
279*433d6423SLionel Sambuc 			return EFAULT;
280*433d6423SLionel Sambuc 		sinfo.shmmax = (unsigned long) -1;
281*433d6423SLionel Sambuc 		sinfo.shmmin = 1;
282*433d6423SLionel Sambuc 		sinfo.shmmni = MAX_SHM_NR;
283*433d6423SLionel Sambuc 		sinfo.shmseg = (unsigned long) -1;
284*433d6423SLionel Sambuc 		sinfo.shmall = (unsigned long) -1;
285*433d6423SLionel Sambuc 		r = sys_datacopy(SELF, (vir_bytes)&sinfo,
286*433d6423SLionel Sambuc 			who_e, (vir_bytes)ds, sizeof(struct shminfo));
287*433d6423SLionel Sambuc 		if (r != OK)
288*433d6423SLionel Sambuc 			return EFAULT;
289*433d6423SLionel Sambuc 		m->m_lc_ipc_shmctl.ret = (shm_list_nr - 1);
290*433d6423SLionel Sambuc 		if (m->m_lc_ipc_shmctl.ret < 0)
291*433d6423SLionel Sambuc 			m->m_lc_ipc_shmctl.ret = 0;
292*433d6423SLionel Sambuc 		break;
293*433d6423SLionel Sambuc 	case SHM_INFO:
294*433d6423SLionel Sambuc 		if (!ds)
295*433d6423SLionel Sambuc 			return EFAULT;
296*433d6423SLionel Sambuc 		s_info.used_ids = shm_list_nr;
297*433d6423SLionel Sambuc 		s_info.shm_tot = 0;
298*433d6423SLionel Sambuc 		for (i = 0; i < shm_list_nr; i++)
299*433d6423SLionel Sambuc 			s_info.shm_tot +=
300*433d6423SLionel Sambuc 				shm_list[i].shmid_ds.shm_segsz/PAGE_SIZE;
301*433d6423SLionel Sambuc 		s_info.shm_rss = s_info.shm_tot;
302*433d6423SLionel Sambuc 		s_info.shm_swp = 0;
303*433d6423SLionel Sambuc 		s_info.swap_attempts = 0;
304*433d6423SLionel Sambuc 		s_info.swap_successes = 0;
305*433d6423SLionel Sambuc 		r = sys_datacopy(SELF, (vir_bytes)&s_info,
306*433d6423SLionel Sambuc 			who_e, (vir_bytes)ds, sizeof(struct shm_info));
307*433d6423SLionel Sambuc 		if (r != OK)
308*433d6423SLionel Sambuc 			return EFAULT;
309*433d6423SLionel Sambuc 		m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
310*433d6423SLionel Sambuc 		if (m->m_lc_ipc_shmctl.ret < 0)
311*433d6423SLionel Sambuc 			m->m_lc_ipc_shmctl.ret = 0;
312*433d6423SLionel Sambuc 		break;
313*433d6423SLionel Sambuc 	case SHM_STAT:
314*433d6423SLionel Sambuc 		if (id < 0 || id >= shm_list_nr)
315*433d6423SLionel Sambuc 			return EINVAL;
316*433d6423SLionel Sambuc 		shm = &shm_list[id];
317*433d6423SLionel Sambuc 		r = sys_datacopy(SELF, (vir_bytes)&shm->shmid_ds,
318*433d6423SLionel Sambuc 			who_e, (vir_bytes)ds, sizeof(struct shmid_ds));
319*433d6423SLionel Sambuc 		if (r != OK)
320*433d6423SLionel Sambuc 			return EFAULT;
321*433d6423SLionel Sambuc 		m->m_lc_ipc_shmctl.ret = shm->id;
322*433d6423SLionel Sambuc 		break;
323*433d6423SLionel Sambuc 	default:
324*433d6423SLionel Sambuc 		return EINVAL;
325*433d6423SLionel Sambuc 	}
326*433d6423SLionel Sambuc 	return OK;
327*433d6423SLionel Sambuc }
328*433d6423SLionel Sambuc 
329*433d6423SLionel Sambuc #if 0
330*433d6423SLionel Sambuc static void list_shm_ds(void)
331*433d6423SLionel Sambuc {
332*433d6423SLionel Sambuc 	int i;
333*433d6423SLionel Sambuc 	printf("key\tid\tpage\n");
334*433d6423SLionel Sambuc 	for (i = 0; i < shm_list_nr; i++)
335*433d6423SLionel Sambuc 		printf("%ld\t%d\t%lx\n",
336*433d6423SLionel Sambuc 			shm_list[i].key,
337*433d6423SLionel Sambuc 			shm_list[i].id,
338*433d6423SLionel Sambuc 			shm_list[i].page);
339*433d6423SLionel Sambuc }
340*433d6423SLionel Sambuc #endif
341*433d6423SLionel Sambuc 
342*433d6423SLionel Sambuc /*===========================================================================*
343*433d6423SLionel Sambuc  *				is_shm_nil		     		     *
344*433d6423SLionel Sambuc  *===========================================================================*/
345*433d6423SLionel Sambuc int is_shm_nil(void)
346*433d6423SLionel Sambuc {
347*433d6423SLionel Sambuc 	return (shm_list_nr == 0);
348*433d6423SLionel Sambuc }
349