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