Annotation of coherent/b/kernel/io.386/sem.c, revision 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.