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