Annotation of coherent/b/kernel/io.386/sem.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.