Annotation of coherent/b/STREAMS/coh.386/rlock.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * coh/rlock.c
        !             3:  * COHERENT record locking.
        !             4:  * Modified 5/92 by steve from tsm's old source.
        !             5:  * All record locking functions meet the system V standard.
        !             6:  */
        !             7: 
        !             8: #include <kernel/_sleep.h>
        !             9: #include <sys/coherent.h>
        !            10: #include <sys/errno.h>
        !            11: #include <fcntl.h>
        !            12: #include <sys/fd.h>
        !            13: #include <sys/proc.h>
        !            14: #include <sys/sched.h>
        !            15: #include <sys/file.h>
        !            16: #include <sys/inode.h>
        !            17: #include <sys/uproc.h>
        !            18: #include <unistd.h>
        !            19: 
        !            20: #include <kernel/rlock.h>
        !            21: 
        !            22: /* Globals. */
        !            23: RLOCK  *freerl;
        !            24: GATE   rlgate = { 0, 0};
        !            25: unsigned RLOCKS = 100;                 /* patchable */
        !            26: 
        !            27: /* Forward. */
        !            28: int            rlock();
        !            29: int            rlinit();
        !            30: static int     nextblock();
        !            31: static int     nextmeet();
        !            32: static RLOCK   *getlock();
        !            33: static RLOCK   *freelock();
        !            34: static int     extract();
        !            35: static int     remlock();
        !            36: static int     addlock();
        !            37: static int     waitlock();
        !            38: static int     waiting();
        !            39: 
        !            40: /*
        !            41:  * Record locking.
        !            42:  */
        !            43: int
        !            44: rlock(fdp, cmd, flp) register FD *fdp; register struct flock *flp;
        !            45: {
        !            46:        register RLOCK  *org;
        !            47:        register int    retval;
        !            48:        RLOCK           srl;
        !            49:        RLOCK           *rlp;
        !            50: 
        !            51:        org = (RLOCK *)&fdp->f_ip->i_rl;
        !            52:        retval = -1;
        !            53:        srl.rl_proc = SELF;
        !            54:        srl.rl_type = flp->l_type==F_RDLCK ? 0:1;
        !            55:        srl.rl_start = flp->l_start;
        !            56:        if (flp->l_whence == SEEK_CUR)
        !            57:                srl.rl_start += fdp->f_seek;
        !            58:        else if (flp->l_whence == SEEK_END)
        !            59:                srl.rl_start += fdp->f_ip->i_size;
        !            60:        srl.rl_end = srl.rl_start;
        !            61:        if (flp->l_len > 0)
        !            62:                srl.rl_end += flp->l_len - 1;
        !            63:        else if (flp->l_len == 0)
        !            64:                srl.rl_end = -1;
        !            65:        else {
        !            66:                srl.rl_start += flp->l_len;
        !            67:                srl.rl_end--;
        !            68:        }
        !            69:        if (srl.rl_start < 0  ||  srl.rl_end < -1
        !            70:            || srl.rl_end != -1 && srl.rl_start > srl.rl_end) {
        !            71:                u.u_error = EINVAL;
        !            72:                return -1;
        !            73:        }
        !            74:        lock(rlgate);
        !            75:        rlp = org;
        !            76:        if (cmd == F_GETLK) {
        !            77:                if (!nextblock(&rlp, &srl))
        !            78:                        flp->l_type = F_UNLCK;
        !            79:                else {
        !            80:                        flp->l_type = rlp->rl_type ? F_WRLCK:F_RDLCK;
        !            81:                        flp->l_whence = SEEK_SET;
        !            82:                        flp->l_start = rlp->rl_start;
        !            83:                        if (rlp->rl_end == -1)
        !            84:                                flp->l_len = 0;
        !            85:                        else
        !            86:                                flp->l_len = rlp->rl_end - flp->l_start + 1;
        !            87:                        flp->l_pid = rlp->rl_proc->p_pid;
        !            88:                }
        !            89:                retval = 0;
        !            90:        } else if (flp->l_type == F_UNLCK)
        !            91:                retval =  remlock(org, &srl);
        !            92:        else if (srl.rl_type && !fdp->f_flag & IPW
        !            93:              || !srl.rl_type && !fdp->f_flag & IPR)
        !            94:                u.u_error = EINVAL;
        !            95:        else if (cmd == F_SETLKW)
        !            96:                retval = waitlock(org, &srl);
        !            97:        else if (!nextblock(&rlp, &srl))
        !            98:                retval = addlock(org, &srl);
        !            99:        else
        !           100:                u.u_error = EACCES;
        !           101:        unlock(rlgate);
        !           102:        if (cmd != F_GETLK)
        !           103:                wakeup(org);
        !           104:        return retval;
        !           105: }
        !           106: 
        !           107: /* Allocate and initialize free record lock list. */
        !           108: int
        !           109: rlinit()
        !           110: {
        !           111:        register RLOCK  *rl;
        !           112: 
        !           113:        if (RLOCKS == 0) {
        !           114:                freerl = NULL;
        !           115:                return 0;
        !           116:        }
        !           117:        freerl = kalloc(RLOCKS * sizeof(RLOCK));
        !           118:        if (freerl == NULL)
        !           119:                panic("rlinit: no space for RLOCKs");
        !           120:        rl = &freerl[RLOCKS-1];
        !           121:        rl->rl_next = NULL;
        !           122:        while (--rl >= freerl)
        !           123:                rl->rl_next = rl+1;
        !           124:        return 1;
        !           125: }
        !           126: 
        !           127: /*
        !           128:  * Record locking subroutines.
        !           129:  * Most of them assume that rlgate is locked.
        !           130:  * The user is guaranteed no unwanted unlocks regardless of error.
        !           131:  * rlgate is locked whenever the lock list contents or free list is used.
        !           132:  * Be careful if you change anything that these things remain true.
        !           133:  */
        !           134: 
        !           135: /*
        !           136:  * In nextblock and nextmeet,
        !           137:  * list is a ptr to an RLOCK * which is owned by the caller.
        !           138:  * This allows calls to proceed down an rlock list.
        !           139:  * These routines should NOT be called with *list == NULL.
        !           140:  */
        !           141: 
        !           142: /* Set *list = next element in list conflicting with lock. */
        !           143: static
        !           144: int
        !           145: nextblock(list, lock) register RLOCK **list, *lock;
        !           146: {
        !           147:        while (nextmeet(list, lock)) {
        !           148:                if (lock->rl_proc != (*list)->rl_proc
        !           149:                   && (lock->rl_type || (*list)->rl_type)) {
        !           150:                        return 1;
        !           151:                }
        !           152:        }
        !           153:        return 0;
        !           154: }
        !           155: 
        !           156: /* Set *list = next element of list referencing a loc referenced by lock */
        !           157: static
        !           158: int
        !           159: nextmeet(list, lock) RLOCK **list, *lock;
        !           160: {
        !           161:        register RLOCK  *block;
        !           162:        register long top, bot;
        !           163: 
        !           164:        top = lock->rl_start;
        !           165:        bot = lock->rl_end;
        !           166:        for (block = (*list)->rl_next; block != NULL; block = block->rl_next) {
        !           167:                if (bot == -1) {
        !           168:                        if (block->rl_end == -1 || block->rl_end >= top)
        !           169:                                break;
        !           170:                } else if (bot >= block->rl_start)
        !           171:                        if (block->rl_end == -1 || block->rl_end >= top)
        !           172:                                break;
        !           173:        }
        !           174:        if ((*list = block) != NULL)
        !           175:                return 1;
        !           176:        return 0;
        !           177: }
        !           178: 
        !           179: /* Remove and return a lock from the free list. */
        !           180: static
        !           181: RLOCK *
        !           182: getlock()
        !           183: {
        !           184:        register RLOCK *rl;
        !           185: 
        !           186:        rl = freerl;
        !           187:        if (rl != NULL)
        !           188:                freerl = rl->rl_next;
        !           189:        else
        !           190:                u.u_error = ENOLCK;
        !           191:        return rl;
        !           192: }
        !           193: 
        !           194: /*
        !           195:  * Remove element from the lock list beginning at org and add it to the free list.
        !           196:  * Return pointer to (what used to be) its predecessor.
        !           197:  */
        !           198: static
        !           199: RLOCK *
        !           200: freelock(org, elt) register RLOCK *org, *elt;
        !           201: {
        !           202:        while (elt != org->rl_next)
        !           203:                org = org->rl_next;
        !           204:        org->rl_next = elt->rl_next;
        !           205:        elt->rl_next = freerl;
        !           206:        freerl = elt;
        !           207:        return org;
        !           208: }
        !           209: 
        !           210: /*
        !           211:  * Remove new lock from old. 
        !           212:  * Returns:
        !           213:  *     1 if caller should free old.
        !           214:  *     0 if caller should do nothing.
        !           215:  *     -1 if error (out of locks).
        !           216:  */
        !           217: static
        !           218: int
        !           219: extract(old, new) register RLOCK *old, *new;
        !           220: {
        !           221:        long            tend;
        !           222:        register RLOCK  *lock;
        !           223: 
        !           224:        if (new->rl_start <= old->rl_start) {
        !           225:                if (new->rl_end == -1
        !           226:                   || old->rl_end != -1 && new->rl_end >= old->rl_end)
        !           227:                        return 1;
        !           228:                old->rl_start = new->rl_end+1;
        !           229:                return 0;
        !           230:        }
        !           231:        tend = old->rl_end;
        !           232:        old->rl_end = new->rl_start - 1;
        !           233:        if (new->rl_end == -1
        !           234:           ||  tend != -1  &&  new->rl_end >= tend)
        !           235:                return 0;
        !           236:        if ((lock = getlock()) == NULL) {
        !           237:                old->rl_end = tend;
        !           238:                return -1;
        !           239:        }
        !           240:        lock->rl_type = old->rl_type;
        !           241:        lock->rl_proc = old->rl_proc;
        !           242:        lock->rl_start = new->rl_end+1;
        !           243:        lock->rl_end = tend;
        !           244:        lock->rl_next = old->rl_next;
        !           245:        old->rl_next = lock;
        !           246:        return 0;
        !           247: }
        !           248: 
        !           249: /* Extract lock from each element of list. */
        !           250: static
        !           251: int
        !           252: remlock(list, lock) RLOCK *list; register RLOCK *lock;
        !           253: {
        !           254:        RLOCK *org;
        !           255: 
        !           256:        org = list;
        !           257:        while (nextmeet(&list, lock)) {
        !           258:                if (list->rl_proc != lock->rl_proc)
        !           259:                        continue;
        !           260:                switch(extract(list, lock)) {
        !           261:                        case 1:
        !           262:                                list = freelock(org, list);
        !           263:                        case 0:
        !           264:                                break;
        !           265:                        default:
        !           266:                                return -1;
        !           267:                }
        !           268:        }
        !           269:        return 0;
        !           270: }
        !           271: 
        !           272: /*
        !           273:  * Install lock in list.
        !           274:  * Combine lock with neighbouring locks of same type and owner.
        !           275:  * Get space for new lock (best done here - OK since rllock locked).
        !           276:  * Remove old locks (always different type, same owner) and attach new lock.
        !           277:  * To avoid removing desired locks, addlock allows redundant locks to appear.
        !           278:  * This is always rectified by the future unlock and is rare.
        !           279:  */
        !           280: static
        !           281: int
        !           282: addlock(list, lock) RLOCK *list; register RLOCK *lock;
        !           283: {
        !           284:        RLOCK   *new, *org;
        !           285:        register long top, bot;
        !           286: 
        !           287:        org = list;
        !           288:        top = lock->rl_start;
        !           289:        bot = lock->rl_end;
        !           290:        if (top != 0)
        !           291:                lock->rl_start--;
        !           292:        if (bot != -1)
        !           293:                lock->rl_end++;
        !           294:        while (nextmeet(&list, lock)) {
        !           295:                if (list->rl_proc != lock->rl_proc
        !           296:                   || list->rl_type != lock->rl_type)
        !           297:                        continue;
        !           298:                if (list->rl_start < top)
        !           299:                        top = list->rl_start;
        !           300:                if (bot != -1 && (list->rl_end == -1 || list->rl_end >= bot))
        !           301:                                bot = list->rl_end;
        !           302:                list = freelock(org, list);
        !           303:        }
        !           304:        if ((new = getlock()) == NULL)
        !           305:                return -1;
        !           306:        new->rl_proc = lock->rl_proc;
        !           307:        new->rl_type = lock->rl_type;
        !           308:        lock = new;
        !           309:        lock->rl_start = top;
        !           310:        lock->rl_end = bot;
        !           311:        remlock(org, lock);
        !           312:        lock->rl_next = org->rl_next;
        !           313:        org->rl_next = lock;
        !           314:        return 0;
        !           315: }
        !           316: 
        !           317: /* Sleep until possible to install rl in list then do so. */
        !           318: #define cleanup()  SELF->p_prl = NULL;  rl->rl_next = freerl;  freerl = rl
        !           319: static
        !           320: int
        !           321: waitlock(list, srl) RLOCK *list, *srl;
        !           322: {
        !           323:        register RLOCK *org;
        !           324: 
        !           325:        org = list;
        !           326:        if (nextblock(&list, srl)) {
        !           327:                register RLOCK *rl = getlock();
        !           328:        
        !           329:                if (rl == NULL)
        !           330:                        return -1;
        !           331:                *rl = *srl;
        !           332:                rl->rl_next = org;
        !           333:                SELF->p_prl = rl;
        !           334:                do {
        !           335:                        __sleep_t       sleep;
        !           336: 
        !           337:                        do {
        !           338:                                if (waiting(list->rl_proc)) {
        !           339:                                        u.u_error = EDEADLK;
        !           340:                                        cleanup();
        !           341:                                        return -1;
        !           342:                                }
        !           343:                        } while (nextblock(&list, rl));
        !           344:                        unlock(rlgate);
        !           345:                        sleep = x_sleep (org, primed, slpriSigCatch, "rlock");
        !           346:                        lock(rlgate);
        !           347:                        if (sleep == PROCESS_SIGNALLED) {
        !           348:                                u.u_error = EINTR;
        !           349:                                cleanup();
        !           350:                                return -1;
        !           351:                        }
        !           352:                        list = org;
        !           353:                } while (nextblock(&list, rl));
        !           354:                cleanup();
        !           355:        }
        !           356:        return addlock(org, srl);
        !           357: }
        !           358: 
        !           359: /* True if pp has requested a lock (even indirectly) pending on SELF. */
        !           360: static
        !           361: int
        !           362: waiting(pp) PROC *pp;
        !           363: {
        !           364:        RLOCK           *list;
        !           365:        register RLOCK  *lock;
        !           366: 
        !           367:        lock = pp->p_prl;
        !           368:        if (lock == NULL)
        !           369:                return 0;
        !           370:        list = lock->rl_next;
        !           371:        while (nextblock(&list, lock)) {
        !           372:                if (list->rl_proc == SELF)
        !           373:                        return 1;
        !           374:                if (waiting(list->rl_proc))
        !           375:                        return 1;
        !           376:        }
        !           377:        return 0;
        !           378: }
        !           379: 
        !           380: /* end of coh/rlock.c */

unix.superglobalmegacorp.com

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