|
|
1.1 root 1: /* $Header: /usr/src/sys/i8086/drv/RCS/sem.c,v 2.1 88/09/03 13:11:37 src Exp $
2: *
3: * The information contained herein is a trade secret of INETCO
4: * Systems, and is confidential information. It is provided under
5: * a license agreement, and may be copied or disclosed only under
6: * the terms of that agreement. Any reproduction or disclosure of
7: * this material without the express written authorization of
8: * INETCO Systems or persuant to the license agreement is unlawful.
9: *
10: * Copyright (c) 1985
11: * An unpublished work by INETCO Systems, Ltd.
12: * All rights reserved.
13: */
14:
15: /*
16: * System V Compatible Semaphores
17: *
18: * This module provides System V compatible semaphore operations.
19: *
20: * Author: Allan Cornish, INETCO Systems Ltd., Sep 1984
21: *
22: * $Log: /usr/src/sys/i8086/drv/RCS/sem.c,v $
23: * Revision 2.1 88/09/03 13:11:37 src
24: * *** empty log message ***
25: *
26: * Revision 1.1 88/03/24 17:06:22 src
27: * Initial revision
28: *
29: * 85/08/06 Allan Cornish
30: * Sem.c split into configuration (semcon.c) and implementation (sem.c).
31: * Semload() renamed to seminit().
32: *
33: * 85/07/22 Allan Cornish
34: * Semctl, semget, semop now return immediately if u.u_error is set.
35: *
36: * 85/07/03 Allan Cornish
37: * Replaced use of EDOM with EIDRM.
38: * Eliminated semlock() and semunlock() functions.
39: * Replaced semaccess() by calls to ipcaccess(), increasing shared ipc code.
40: */
41:
42: #include <coherent.h>
43: #include <sched.h>
44: #include <types.h>
45: #include <uproc.h>
46: #include <errno.h>
47: #include <stat.h>
48: #include <con.h>
49: #include <sem.h>
50:
51: #ifndef EIDRM
52: #define EIDRM EDOM
53: #endif
54:
55: /*
56: * Semaphore Information
57: */
58:
59: #define NSEMVAL 32767
60:
61: static
62: struct semid_ds *semids = 0;
63:
64: unsigned NSEMID = 16;
65: unsigned NSEM = 16;
66:
67: /*
68: * Semaphore Initialization.
69: *
70: * Initialize semaphore ids.
71: */
72:
73: seminit()
74: {
75: register struct semid_ds *semidp;
76:
77: if ( semids = kalloc( NSEMID * sizeof(struct semid_ds) ) ) {
78:
79: for ( semidp = &semids[NSEMID]; --semidp >= semids; )
80: semidp->sem_perm.mode = 0;
81: }
82: else {
83: printf("could not allocate %u semaphore ids\n", NSEMID);
84: NSEMID = 0;
85: }
86: }
87:
88: /*
89: * Semctl - Semaphore Control Operations.
90: */
91:
92: usemctl( semid, semnum, cmd, arg )
93:
94: unsigned semid;
95: unsigned semnum;
96: int cmd;
97: union semun {
98: int val;
99: struct semid_ds *buf;
100: unsigned short *array;
101: } arg;
102:
103: {
104: register struct semid_ds *semidp;
105: register struct sem *semp;
106: int nsems, val;
107:
108: if ( u.u_error )
109: return -1;
110:
111: if ( semid >= NSEMID ) {
112: u.u_error = EINVAL;
113: return -1;
114: }
115:
116: semidp = &semids[semid];
117:
118: if ( (semidp->sem_perm.mode & IPC_ALLOC) == 0 ) {
119: u.u_error = EINVAL;
120: return -1;
121: }
122:
123: if ((ipcaccess( &semidp->sem_perm ) & SEM_R) == 0) { /* can't read */
124: u.u_error = EACCES;
125: return -1;
126: }
127:
128: if ( semnum >= semidp->sem_nsems ) {
129: u.u_error = EFBIG;
130: return -1;
131: }
132:
133: semp = &semidp->sem_base[semnum];
134:
135: switch ( cmd ) {
136:
137: case GETVAL: /* Return value of semval */
138: return semp->semval;
139:
140: case SETVAL: /* Set semval */
141: if ((ipcaccess( &semidp->sem_perm ) & SEM_A) == 0) {
142: u.u_error = EACCES; /* can't alter */
143: return -1;
144: }
145:
146: if ( arg.val < 0 ) { /* illegal value */
147: u.u_error = ERANGE;
148: return -1;
149: }
150:
151: if ( semp->semval = arg.val ) {
152:
153: if ( semp->semncnt )
154: wakeup( &semp->semncnt );
155: }
156: else {
157: if ( semp->semzcnt )
158: wakeup( &semp->semzcnt );
159: }
160:
161: return 0;
162:
163: case GETPID: /* Return value of sempid */
164: return semp->sempid;
165:
166: case GETNCNT: /* Return value of semncnt */
167: return semp->semncnt;
168:
169: case GETZCNT: /* Return value of semzcnt */
170: return semp->semzcnt;
171:
172: case GETALL: /* Return semvals array */
173: nsems = semidp->sem_nsems;
174: semp = semidp->sem_base;
175:
176: while ( --nsems >= 0 ) {
177:
178: putuwd( (arg.array)++, (semp++)->semval );
179:
180: if ( u.u_error )
181: return -1;
182: }
183: return 0;
184:
185: case SETALL: /* Set semvals array */
186: if ( (ipcaccess( &semidp->sem_perm ) & SEM_A) == 0 ) {
187: u.u_error = EACCES;
188: return -1;
189: }
190: nsems = semidp->sem_nsems;
191: semp = semidp->sem_base;
192:
193: while ( --nsems >= 0 ) {
194:
195: if ( (val = getuwd( arg.array )) < 0 ) {
196:
197: if ( u.u_error == 0 )
198: u.u_error = ERANGE;
199: }
200: else
201: semp->semval = val;
202: arg.array++;
203: semp++;
204: }
205: if ( u.u_error )
206: return -1;
207: return 0;
208:
209: case IPC_STAT:
210: kucopy( semidp, arg.buf, sizeof(struct semid_ds) );
211: return 0;
212:
213: case IPC_SET:
214: if ( (u.u_uid != 0) && (u.u_uid != semidp->sem_perm.uid) ) {
215: u.u_error = EPERM;
216: return -1;
217: }
218: semidp->sem_perm.uid = getuwd( &((arg.buf)->sem_perm.uid ) );
219: semidp->sem_perm.gid = getuwd( &((arg.buf)->sem_perm.gid ) );
220: semidp->sem_perm.mode =
221: (getuwd(&((arg.buf)->sem_perm.mode))&0777) | IPC_ALLOC;
222: return 0;
223:
224: case IPC_RMID:
225: if ( (u.u_uid != 0) && (u.u_uid != semidp->sem_perm.uid) ) {
226: u.u_error = EPERM;
227: return -1;
228: }
229: semidp->sem_perm.seq++;
230: semp = &semidp->sem_base[ semidp->sem_nsems ];
231:
232: while ( --semp >= semidp->sem_base ) {
233:
234: if ( semp->semncnt )
235: wakeup( &semp->semncnt );
236: if ( semp->semzcnt )
237: wakeup( &semp->semzcnt );
238: }
239:
240: kfree( semidp->sem_base );
241: semidp->sem_perm.mode = 0;
242: return 0;
243:
244: default:
245: u.u_error = EINVAL;
246: return -1;
247: }
248: }
249:
250: /*
251: * Semget - Get set of semaphores
252: */
253:
254: usemget( skey, nsems, semflg )
255:
256: key_t skey;
257: unsigned nsems;
258: int semflg;
259:
260: {
261: register struct semid_ds *semidp;
262: register struct sem *semp;
263: struct semid_ds *freeidp = 0;
264:
265: if ( u.u_error )
266: return -1;
267:
268: if ( nsems >= NSEM ) {
269: u.u_error = EINVAL;
270: return -1;
271: }
272:
273: for ( semidp = &semids[NSEMID]; --semidp >= semids; ) {
274:
275: if ( (semidp->sem_perm.mode & IPC_ALLOC) == 0 ) {
276:
277: if ((freeidp == 0) ||
278: (freeidp->sem_ctime > semidp->sem_ctime))
279: freeidp = semidp;
280: continue;
281: }
282:
283: #ifdef IPC_PRIVATE
284: if (skey == IPC_PRIVATE)
285: continue;
286: #endif
287:
288: if (skey == semidp->sem_perm.key) { /* found! */
289:
290: if ( (semflg & IPC_CREAT) && (semflg & IPC_EXCL) ) {
291: u.u_error = EEXIST;
292: return -1;
293: }
294:
295: if ((semidp->sem_perm.mode & semflg) != (semflg&0777)) {
296: u.u_error = EACCES;
297: return -1;
298: }
299:
300: if ( semidp->sem_nsems < nsems ) {
301: u.u_error = EINVAL;
302: return -1;
303: }
304:
305: return semidp - semids;
306: }
307: }
308:
309: if ( !(semflg & IPC_CREAT) ) {
310: u.u_error = ENOENT;
311: return -1;
312: }
313:
314: if ( freeidp == 0 ) {
315: u.u_error = ENOSPC;
316: return -1;
317: }
318:
319: semidp = freeidp;
320: semidp->sem_base = kalloc( nsems * sizeof(struct sem) );
321:
322: if (semidp->sem_base == 0 ) {
323: u.u_error = ENOSPC;
324: return -1;
325: }
326:
327: semidp->sem_nsems = nsems;
328: semidp->sem_otime = 0;
329: semidp->sem_ctime = timer.t_time;
330:
331: for ( semp = &semidp->sem_base[nsems]; --semp >= semidp->sem_base; )
332: semp->semval = semp->sempid = semp->semncnt = semp->semzcnt = 0;
333:
334: semidp->sem_perm.cuid = semidp->sem_perm.uid = u.u_uid;
335: semidp->sem_perm.cgid = semidp->sem_perm.gid = u.u_gid;
336: semidp->sem_perm.mode = (semflg & 0777) | IPC_ALLOC;
337: semidp->sem_perm.key = skey;
338:
339: return semidp - semids;
340: }
341:
342: /*
343: * Semop - Semaphore Operations.
344: */
345:
346: usemop( semid, sops, nsops )
347:
348: unsigned semid;
349: struct sembuf *sops;
350: unsigned nsops;
351:
352: {
353: register struct semid_ds *semidp;
354: register struct sem *semp;
355: struct sembuf *sp;
356: unsigned n, semnum, semflg;
357: int semop, oval;
358:
359: if ( u.u_error )
360: return -1;
361:
362: if ( semid >= NSEMID ) {
363: u.u_error = EINVAL;
364: return -1;
365: }
366:
367: if ( nsops >= NSEM ) {
368: u.u_error = E2BIG;
369: return -1;
370: }
371:
372: semidp = &semids[semid];
373:
374: if ( (semidp->sem_perm.mode & IPC_ALLOC) == 0 ) {
375: u.u_error = EINVAL;
376: return -1;
377: }
378:
379: if ( (ipcaccess( &semidp->sem_perm ) & SEM_A) == 0 ) {
380: u.u_error = EACCES;
381: return -1;
382: }
383:
384: sp = sops;
385: n = nsops;
386:
387: while ( n > 0 ) { /* do semaphore ops */
388:
389: semnum = getuwd( & (sp->sem_num) );
390: semop = getuwd( & (sp->sem_op ) );
391: semflg = getuwd( & (sp->sem_flg) );
392:
393: if ( (u.u_error != 0) || (semnum >= semidp->sem_nsems) ) {
394:
395: while ( --sp >= sops ) { /* undo prev semops */
396:
397: semnum = getuwd( &sp->sem_num );
398: semop = getuwd( &sp->sem_op );
399: semp = &semidp->sem_base[ semnum ];
400: semundo( semp, semop );
401: }
402:
403: if ( u.u_error == 0 )
404: u.u_error = EFBIG;
405: return -1;
406: }
407:
408: semp = &semidp->sem_base[semnum];
409:
410: if ( (oval = semdo( semp, semop )) < 0 ) { /* can't do semop */
411:
412: while ( --sp >= sops ) { /* undo prev semops */
413:
414: unsigned unnum = getuwd( &sp->sem_num );
415: int unop = getuwd( &sp->sem_op );
416: semundo( &semidp->sem_base[ unnum ], unop);
417: }
418:
419: if ( u.u_error )
420: return -1;
421:
422: if ( semflg & IPC_NOWAIT ) {
423: u.u_error = EAGAIN;
424: return -1;
425: }
426:
427: if ( semop < 0 ) { /* wait for non-zero */
428:
429: if (semwait( semidp, &semp->semncnt ) < 0 )
430: return -1;
431: }
432: else { /* wait for zero */
433:
434: if ( semwait( semidp, &semp->semzcnt ) < 0 )
435: return -1;
436: }
437:
438: sp = sops; /* retry set of semaphore operations */
439: n = nsops;
440: continue;
441: }
442:
443: ++sp;
444: --n;
445: }
446:
447: for (sp=sops,n=nsops; n > 0; --n,++sp) {/* save pid in each semaphore */
448:
449: semnum = getuwd( &sp->sem_num );
450: semidp->sem_base[ semnum ].sempid = SELF->p_pid;
451: }
452:
453: semidp->sem_otime = timer.t_time; /* ajust operation time */
454: return oval; /* return last prev semval */
455: }
456:
457: /*
458: * Do a Semaphore Operation.
459: *
460: * Input: semp = pointer to semaphore
461: * semop = semaphore operation
462: *
463: * Action: If semop < 0 and semval > semop then add semop to semval.
464: * If semop > 0 then add semop to semval.
465: *
466: * Return: Previous semval.
467: */
468:
469: static
470: semdo( semp, semop )
471:
472: register struct sem * semp;
473: register int semop;
474:
475: {
476: int ret;
477:
478: ret = semp->semval;
479:
480: if ( semop < 0 ) { /* want to decrement semval */
481:
482: semop = -semop;
483:
484: if ( semp->semval < semop ) /* can't decrement semval */
485: return -1;
486:
487: semp->semval -= semop;
488:
489: if ( (semp->semval == 0) && (semp->semzcnt != 0) )
490: wakeup( &semp->semzcnt );
491: }
492: else if ( semop > 0 ) { /* want to increment semval */
493:
494: if ( (semp->semval + semop) > NSEMVAL) {
495:
496: u.u_error = ERANGE;
497: return -1;
498: }
499:
500: semp->semval += semop;
501:
502: if ( semp->semncnt )
503: wakeup( &semp->semncnt );
504: }
505: else /* if ( semop == 0 ) */ {
506:
507: if ( semp->semval != 0 )
508: return -1;
509: }
510: return ret;
511: }
512:
513: /*
514: * Undo a Semaphore Operation.
515: */
516:
517: static
518: semundo( semp, semop )
519:
520: register struct sem * semp;
521: register int semop;
522:
523: {
524: if ( semp->semval -= semop ) {
525:
526: if ( semp->semncnt )
527: wakeup( &semp->semncnt );
528: }
529: else {
530: if ( semp->semzcnt )
531: wakeup( &semp->semzcnt );
532: }
533: }
534:
535: /*
536: * Wait on Semaphore Event
537: *
538: * Input: semidp = pointer to semaphore id structure.
539: * ep = pointer to semncnt or semzcnt event to wait for.
540: *
541: * Action: Sleep on a semaphore event.
542: * If semaphore id has been deleted, error return.
543: * If signal has been received, error return.
544: *
545: * Output: 0 = Status ok.
546: * -1 = Error occurred, errno is set.
547: */
548:
549: static
550: semwait( semidp, ep )
551:
552: register struct semid_ds * semidp;
553: register unsigned short *ep;
554: {
555: unsigned seqn;
556:
557: seqn = semidp->sem_perm.seq;
558: ++(*ep);
559: sleep( ep, CVTTOUT, IVTTOUT, SVTTOUT );
560:
561: if (semidp->sem_perm.seq != seqn ) { /* semaphore id gone */
562: u.u_error = EIDRM;
563: return -1;
564: }
565:
566: --(*ep);
567:
568: if ( SELF->p_ssig && nondsig() ) { /* signal received */
569: u.u_error = EINTR;
570: return -1;
571: }
572: return 0;
573: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.