|
|
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.