Annotation of coherent/b/kernel/coh.386/rlock.c, revision 1.1.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.