int lck$deqlock(struct _lkb *lck, int flags, unsigned int lkid) { vmslock(&SPIN_SCS,IPL$_SCS); struct _rsb * res = lck->lkb$l_rsb; int newmode; remque(&lck->lkb$l_ownqfl,0); remque(&lck->lkb$l_sqfl,0); // check if no locks on resource, remove the resource then newmode=find_highest(lck,res); res->rsb$b_fgmode=newmode; res->rsb$b_ggmode=newmode; res->rsb$b_cgmode=newmode; grant_queued(res,0,1,1); if (lck->lkb$b_state) { } kfree(lck); lockidtbl[lkid] = lkid + 1; if (aqempty(&res->rsb$l_grqfl) && aqempty(&res->rsb$l_cvtqfl) && aqempty(&res->rsb$l_wtqfl) && aqempty(&res->rsb$l_rrsfl) && aqempty(&res->rsb$l_srsfl)) { remque(res, 0); kfree(res); } vmsunlock(&SPIN_SCS,IPL$_ASTDEL); }
asmlinkage int exe$enq(unsigned int efn, unsigned int lkmode, struct _lksb *lksb, unsigned int flags, void *resnam, unsigned int parid, void (*astadr)(), unsigned long astprm, void (*blkastadr)(), unsigned int acmode, unsigned int rsdm_id) { int convert; int retval=SS$_NORMAL; int sts; // some tests. one only for now, should be more. if (lkmode>LCK$K_EXMODE) return SS$_BADPARAM; vmslock(&SPIN_SCS,IPL$_SCS); // check. probably too early convert=flags&LCK$M_CONVERT; if (!convert) { /* new lock */ struct _rsb * res = 0; struct _rsb * old; struct _lkb * lck = 0, *par = 0; struct dsc$descriptor * resnamdsc; int sserror=0; resnamdsc=resnam; if (resnamdsc->dsc$w_length==0 || resnamdsc->dsc$w_length>RSB$K_MAXLEN) { sserror=SS$_IVBUFLEN; goto error; } if (flags&LCK$M_EXPEDITE) if (lkmode!=LCK$K_NLMODE) { sserror=SS$_UNSUPPORTED; goto error; } if (lkmode!=LCK$K_NLMODE) { sserror=SS$_UNSUPPORTED; goto error; } res=kmalloc(sizeof(struct _rsb),GFP_KERNEL); memset(res,0,sizeof(struct _rsb)); lck=kmalloc(sizeof(struct _lkb),GFP_KERNEL); memset(lck,0,sizeof(struct _lkb)); lck->lkb$b_efn=efn; lck->lkb$l_flags=flags; lck->lkb$b_rqmode=lkmode; lck->lkb$l_cplastadr=astadr; lck->lkb$l_blkastadr=blkastadr; lck->lkb$l_astprm=astprm; lck->lkb$l_pid=current->pcb$l_pid; lck->lkb$l_lksb=lksb; qhead_init(&lck->lkb$l_sqfl); qhead_init(&lck->lkb$l_ownqfl); strncpy(res->rsb$t_resnam,resnamdsc->dsc$a_pointer,resnamdsc->dsc$w_length); res->rsb$b_rsnlen=resnamdsc->dsc$w_length; setipl(IPL$_SCS); // do scs spinlock //setipl(IPL$_ASTDEL); if (flags&LCK$M_SYSTEM) { /* priv checks */ } else { } if (parid==0) { //list_add(&res->lr_childof, &ns->ns_root_list); //this is added to lck$gl_rrsfl down below, I think } else { //check valid lock // check lock access mode par=lockidtbl[parid]; if (current->pcb$l_pid != par->lkb$l_pid) { vmsunlock(&SPIN_SCS,IPL$_ASTDEL); return SS$_IVLOCKID; } //check if parent granted, if not return SS$_PARNOTGRANT; if (par->lkb$b_state!=LKB$K_CONVERT || par->lkb$b_state!=LKB$K_GRANTED) if ((par->lkb$l_flags & LCK$M_CONVERT) == 0) { vmsunlock(&SPIN_SCS,IPL$_ASTDEL); return SS$_PARNOTGRANT; } par->lkb$w_refcnt++; res->rsb$l_parent = par->lkb$l_rsb; // should not be here? //check if uic-specific resource //check if system-wide //charge lock against quota //list_add(&res->lr_childof, &parent->lr_children); //res->rsb$l_rtrsb=enq_find_oldest_parent(r,p->lkb$l_rsb); lck->lkb$l_parent=par; } old=find_reshashtbl(resnamdsc); if (!old) { lck$gl_rsbcnt++; lck$gl_lckcnt++; if (flags & LCK$M_SYNCSTS) retval=SS$_SYNCH; qhead_init(&res->rsb$l_grqfl); qhead_init(&res->rsb$l_cvtqfl); qhead_init(&res->rsb$l_wtqfl); //insque(&lck->lkb$l_sqfl,res->rsb$l_grqfl); lck->lkb$l_rsb=res; insert_reshashtbl(res); if (parid==0) { insque(&res->rsb$l_rrsfl,lck$gl_rrsfl); qhead_init(&res->rsb$l_srsfl); res->rsb$b_depth=0; res->rsb$l_rtrsb=res; exe$clref(lck->lkb$b_efn); insque(&lck->lkb$l_ownqfl,¤t->pcb$l_lockqfl); //?if (q->flags & LKB$M_DCPLAST) lksb->lksb$l_lkid=insert_lck(lck); lksb->lksb$w_status=SS$_NORMAL; sts = lck$grant_lock(lck ,res ,-1,lkmode,flags,efn,res->rsb$b_ggmode); goto end; } else { // it has a parid non-zero res->rsb$l_csid=par->lkb$l_rsb->rsb$l_csid; par->lkb$l_rsb->rsb$w_refcnt++; res->rsb$b_depth=par->lkb$l_rsb->rsb$b_depth+1; //check maxdepth if (res->rsb$b_depth>10) { // pick a number ? retval=SS$_EXDEPTH; goto error; } res->rsb$l_rtrsb=par->lkb$l_rsb->rsb$l_rtrsb; insque(&res->rsb$l_srsfl,&par->lkb$l_rsb->rsb$l_srsfl); if (par->lkb$l_csid) { //remote lck$snd_granted(lck); } else { sts = lck$grant_lock(lck,res,-1,lkmode,flags,efn,res->rsb$b_ggmode); } } } else { /* old, found in resource hash table */ /* something else? */ int granted = 0; if (flags & LCK$M_SYNCSTS) retval=SS$_SYNCH; kfree(res); res=old; lck->lkb$l_rsb=res; //after, also check whether something in cvtqfl or wtqfl -> insque wtqfl if (0!=test_bit(res->rsb$b_ggmode,&lck$ar_compat_tbl[lck->lkb$b_rqmode])) { if (aqempty(res->rsb$l_wtqfl)) { granted=1; //sts = lck$grant_lock(lck ,res ,-1,lkmode,flags,efn); } else { if (flags&LCK$M_NOQUEUE) { res->rsb$w_lckcnt--; kfree(lck); vmsunlock(&SPIN_SCS,IPL$_ASTDEL); return SS$_NOTQUEUED; } else { lck->lkb$b_state=LKB$K_WAITING; insque(&lck->lkb$l_sqfl,res->rsb$l_wtqfl); lksb->lksb$w_status=0; lck->lkb$l_status|=LKB$M_ASYNC; maybe_blkast(res,lck); } } } else { // if not compatible if (flags&LCK$M_NOQUEUE) { res->rsb$w_lckcnt--; kfree(lck); vmsunlock(&SPIN_SCS,IPL$_ASTDEL); return SS$_NOTQUEUED; } else { lck->lkb$b_state=LKB$K_WAITING; insque(&lck->lkb$l_sqfl,res->rsb$l_wtqfl); lksb->lksb$w_status=0; lck->lkb$l_status|=LKB$M_ASYNC; maybe_blkast(res,lck); // insque(&lck->lkb$l_ownqfl,¤t->pcb$l_lockqfl); } } lksb->lksb$l_lkid=insert_lck(lck); lksb->lksb$w_status=SS$_NORMAL; if ((granted & 1)==1) { if (0/*par->lkb$l_csid*/) { //remote lck$snd_granted(lck); } else { sts = lck$grant_lock(lck, res, -1,lkmode,flags,efn,res->rsb$b_ggmode); } } } end: /* raise ipl */ vmsunlock(&SPIN_SCS,IPL$_ASTDEL); return retval; error: /* ipl back */ kfree(res); kfree(lck); vmsunlock(&SPIN_SCS,IPL$_ASTDEL); return sserror; } else { // convert /* convert */ int granted = 0, newmodes = 0; struct _lkb * lck; struct _rsb * res; void * dummy; int newmode; lck=lockidtbl[lksb->lksb$l_lkid]; res=lck->lkb$l_rsb; if (lck->lkb$b_state!=LKB$K_GRANTED) { vmsunlock(&SPIN_SCS,IPL$_ASTDEL); return SS$_CVTUNGRANT; } lck->lkb$b_efn=efn; lck->lkb$l_flags=flags; lck->lkb$b_rqmode=lkmode; lck->lkb$l_cplastadr=astadr; lck->lkb$l_blkastadr=blkastadr; lck->lkb$l_astprm=astprm; lck->lkb$l_lksb=lksb; remque(&lck->lkb$l_sqfl,&lck->lkb$l_sqfl);// ? //remque(&res->rsb$l_grqfl,dummy); // superfluous if (aqempty(res->rsb$l_cvtqfl) && aqempty(res->rsb$l_grqfl)) { sts = lck$grant_lock(lck ,res,lck->lkb$b_grmode,lkmode,flags,efn,-1); vmsunlock(&SPIN_SCS,IPL$_ASTDEL); return SS$_NORMAL; } else { // convert, something in cvtqfl or grqfl if (res->rsb$b_cgmode!=lck->lkb$b_grmode) { newmode=res->rsb$b_ggmode; } else { newmode=find_highest(lck,res); newmodes= 0; } if (test_bit(lkmode,&lck$ar_compat_tbl[newmode])) { //sts = lck$grant_lock(lck,res,lck->lkb$b_grmode,lkmode,flags,efn); granted = 1; } } if (granted) { if (newmodes) { res->rsb$b_fgmode=newmode; res->rsb$b_ggmode=newmode; res->rsb$b_cgmode=newmode; } sts = lck$grant_lock(lck,res,lck->lkb$b_grmode,lkmode /*newmode*/,flags,efn,res->rsb$b_ggmode); grant_queued(res,newmode,1,1); } else { int wasempty=aqempty(&res->rsb$l_cvtqfl); lck->lkb$b_rqmode=lkmode; insque(&lck->lkb$l_sqfl,res->rsb$l_cvtqfl); lck->lkb$b_state=LKB$K_CONVERT; lksb->lksb$w_status=0; lck->lkb$l_status|=LKB$M_ASYNC; maybe_blkast(res,lck); if (wasempty) res->rsb$b_cgmode=newmode; sts=SS$_NORMAL; } vmsunlock(&SPIN_SCS,IPL$_ASTDEL); return sts; } vmsunlock(&SPIN_SCS,IPL$_ASTDEL); }
void f11b$dispatcher(void) { int pid=current->pcb$l_pid; struct _irp * i; int sts; int fcode, fmode; pid=0; while (!aqempty(&xqp->xqp_head)) { i=remque(xqp->xqp_head,0); xqp->io_channel=i->irp$w_chan; xqp->current_ucb=i->irp$l_ucb; xqp->current_vcb=((struct _ucb *)xqp->current_ucb)->ucb$l_vcb; fcode=i->irp$v_fcode; fmode=i->irp$v_fmod; iosbret(i,SS$_NORMAL); switch (fcode) { case IO$_ACCESS: { struct _vcb * vcb = i->irp$l_ucb->ucb$l_vcb; struct dsc$descriptor * fibdsc=i->irp$l_qio_p1; struct dsc$descriptor * filedsc=i->irp$l_qio_p2; unsigned short *reslen=i->irp$l_qio_p3; struct dsc$descriptor * resdsc=i->irp$l_qio_p4; void * atrp=i->irp$l_qio_p5; struct _fibdef * fib=(struct _fibdef *)fibdsc->dsc$a_pointer; unsigned action=0; if (i->irp$l_func & IO$M_ACCESS) action=0; if (i->irp$l_func & IO$M_CREATE) action=2; if (i->irp$l_func & IO$M_DELETE) action=1; //if (fib->fib$w_did_num>0) sts=f11b_access(vcb,i); if (sts==SS$_NOSUCHFILE && (i->irp$l_func & IO$M_CREATE)) goto create; } break; case IO$_READVBLK: case IO$_WRITEVBLK: { char * buffer; f11b_read_writevb(i); //return; // too early, maybe, but because of io_done //accesschunk(0,i->irp$l_qio_p3,&buffer,0,0,i); //memcpy(i->irp$l_qio_p1,buffer,512); } break; case IO$_CREATE: { struct _vcb * vcb = i->irp$l_ucb->ucb$l_vcb; //f11b$create(vcb,i); create: f11b_create(vcb,i); } break; case IO$_DELETE: { struct _vcb * vcb = i->irp$l_ucb->ucb$l_vcb; f11b_delete(vcb,i); } break; case IO$_MODIFY: { struct _vcb * vcb = i->irp$l_ucb->ucb$l_vcb; f11b_modify(vcb,i); } break; default: printk ("xqp %x code not implemented yet\n",fcode); if (i->irp$l_iosb) ((struct _iosb *)i->irp$l_iosb)->iosb$w_status = 1; break; } unlock_xqp("f11b$s", xqp); if (i) f11b_io_done(i); } }