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