예제 #1
0
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);
}
예제 #2
0
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,&current->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,&current->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);
}
예제 #3
0
파일: dispatch.c 프로젝트: rroart/freevms
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);
    }
}