15e96a66cSDavid du Colombier #include "stdinc.h" 25e96a66cSDavid du Colombier 35e96a66cSDavid du Colombier #include "9.h" 45e96a66cSDavid du Colombier 55e96a66cSDavid du Colombier static struct { 65e96a66cSDavid du Colombier VtLock* lock; 75e96a66cSDavid du Colombier 85e96a66cSDavid du Colombier Excl* head; 95e96a66cSDavid du Colombier Excl* tail; 105e96a66cSDavid du Colombier } ebox; 115e96a66cSDavid du Colombier 12*e12a9870SDavid du Colombier struct Excl { 135e96a66cSDavid du Colombier Fsys* fsys; 145e96a66cSDavid du Colombier uvlong path; 155e96a66cSDavid du Colombier ulong time; 165e96a66cSDavid du Colombier 175e96a66cSDavid du Colombier Excl* next; 185e96a66cSDavid du Colombier Excl* prev; 19*e12a9870SDavid du Colombier }; 205e96a66cSDavid du Colombier 215e96a66cSDavid du Colombier enum { 225e96a66cSDavid du Colombier LifeTime = (5*60), 235e96a66cSDavid du Colombier }; 245e96a66cSDavid du Colombier 255e96a66cSDavid du Colombier int exclAlloc(Fid * fid)265e96a66cSDavid du ColombierexclAlloc(Fid* fid) 275e96a66cSDavid du Colombier { 285e96a66cSDavid du Colombier ulong t; 295e96a66cSDavid du Colombier Excl *excl; 305e96a66cSDavid du Colombier 315e96a66cSDavid du Colombier assert(fid->excl == nil); 325e96a66cSDavid du Colombier 335e96a66cSDavid du Colombier t = time(0L); 345e96a66cSDavid du Colombier vtLock(ebox.lock); 355e96a66cSDavid du Colombier for(excl = ebox.head; excl != nil; excl = excl->next){ 365e96a66cSDavid du Colombier if(excl->fsys != fid->fsys || excl->path != fid->qid.path) 375e96a66cSDavid du Colombier continue; 385e96a66cSDavid du Colombier /* 395e96a66cSDavid du Colombier * Found it. 405e96a66cSDavid du Colombier * Now, check if it's timed out. 415e96a66cSDavid du Colombier * If not, return error, it's locked. 425e96a66cSDavid du Colombier * If it has timed out, zap the old 435e96a66cSDavid du Colombier * one and continue on to allocate a 445e96a66cSDavid du Colombier * a new one. 455e96a66cSDavid du Colombier */ 465e96a66cSDavid du Colombier if(excl->time >= t){ 475e96a66cSDavid du Colombier vtUnlock(ebox.lock); 485e96a66cSDavid du Colombier vtSetError("exclusive lock"); 495e96a66cSDavid du Colombier return 0; 505e96a66cSDavid du Colombier } 515e96a66cSDavid du Colombier excl->fsys = nil; 525e96a66cSDavid du Colombier } 535e96a66cSDavid du Colombier 545e96a66cSDavid du Colombier /* 555e96a66cSDavid du Colombier * Not found or timed-out. 565e96a66cSDavid du Colombier * Alloc a new one and initialise. 575e96a66cSDavid du Colombier */ 585e96a66cSDavid du Colombier excl = vtMemAllocZ(sizeof(Excl)); 595e96a66cSDavid du Colombier excl->fsys = fid->fsys; 605e96a66cSDavid du Colombier excl->path = fid->qid.path; 615e96a66cSDavid du Colombier excl->time = t+LifeTime; 625e96a66cSDavid du Colombier if(ebox.tail != nil){ 635e96a66cSDavid du Colombier excl->prev = ebox.tail; 645e96a66cSDavid du Colombier ebox.tail->next = excl; 655e96a66cSDavid du Colombier } 665e96a66cSDavid du Colombier else{ 675e96a66cSDavid du Colombier ebox.head = excl; 685e96a66cSDavid du Colombier excl->prev = nil; 695e96a66cSDavid du Colombier } 705e96a66cSDavid du Colombier ebox.tail = excl; 715e96a66cSDavid du Colombier excl->next = nil; 725e96a66cSDavid du Colombier vtUnlock(ebox.lock); 735e96a66cSDavid du Colombier 745e96a66cSDavid du Colombier fid->excl = excl; 755e96a66cSDavid du Colombier return 1; 765e96a66cSDavid du Colombier } 775e96a66cSDavid du Colombier 785e96a66cSDavid du Colombier int exclUpdate(Fid * fid)795e96a66cSDavid du ColombierexclUpdate(Fid* fid) 805e96a66cSDavid du Colombier { 815e96a66cSDavid du Colombier ulong t; 825e96a66cSDavid du Colombier Excl *excl; 835e96a66cSDavid du Colombier 845e96a66cSDavid du Colombier excl = fid->excl; 855e96a66cSDavid du Colombier 865e96a66cSDavid du Colombier t = time(0L); 875e96a66cSDavid du Colombier vtLock(ebox.lock); 885e96a66cSDavid du Colombier if(excl->time < t || excl->fsys != fid->fsys){ 895e96a66cSDavid du Colombier vtUnlock(ebox.lock); 905e96a66cSDavid du Colombier vtSetError("exclusive lock broken"); 915e96a66cSDavid du Colombier return 0; 925e96a66cSDavid du Colombier } 935e96a66cSDavid du Colombier excl->time = t+LifeTime; 945e96a66cSDavid du Colombier vtUnlock(ebox.lock); 955e96a66cSDavid du Colombier 965e96a66cSDavid du Colombier return 1; 975e96a66cSDavid du Colombier } 985e96a66cSDavid du Colombier 995e96a66cSDavid du Colombier void exclFree(Fid * fid)1005e96a66cSDavid du ColombierexclFree(Fid* fid) 1015e96a66cSDavid du Colombier { 1025e96a66cSDavid du Colombier Excl *excl; 1035e96a66cSDavid du Colombier 1045e96a66cSDavid du Colombier if((excl = fid->excl) == nil) 1055e96a66cSDavid du Colombier return; 1065e96a66cSDavid du Colombier fid->excl = nil; 1075e96a66cSDavid du Colombier 1085e96a66cSDavid du Colombier vtLock(ebox.lock); 1095e96a66cSDavid du Colombier if(excl->prev != nil) 1105e96a66cSDavid du Colombier excl->prev->next = excl->next; 1115e96a66cSDavid du Colombier else 1125e96a66cSDavid du Colombier ebox.head = excl->next; 1135e96a66cSDavid du Colombier if(excl->next != nil) 1145e96a66cSDavid du Colombier excl->next->prev = excl->prev; 1155e96a66cSDavid du Colombier else 1165e96a66cSDavid du Colombier ebox.tail = excl->prev; 1175e96a66cSDavid du Colombier vtUnlock(ebox.lock); 1185e96a66cSDavid du Colombier 1195e96a66cSDavid du Colombier vtMemFree(excl); 1205e96a66cSDavid du Colombier } 1215e96a66cSDavid du Colombier 1225e96a66cSDavid du Colombier void exclInit(void)1235e96a66cSDavid du ColombierexclInit(void) 1245e96a66cSDavid du Colombier { 1255e96a66cSDavid du Colombier ebox.lock = vtLockAlloc(); 1265e96a66cSDavid du Colombier } 127