⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rf_stripelocks.c

📁 RAIDFrame是个非常好的磁盘阵列RAID仿真工具
💻 C
📖 第 1 页 / 共 2 页
字号:
  RF_ASSERT(RF_IO_IS_R_OR_W(lockReqDesc->type));  if (rf_stripeLockDebug) {    rf_get_threadid(tid);    if (stripeID == -1) Dprintf1("[%d] Lock acquisition supressed (stripeID == -1)\n",tid);    else {      Dprintf8("[%d] Trying to acquire stripe lock table 0x%lx SID %ld type %c range %ld-%ld, range2 %ld-%ld hashval %d\n",        tid, (unsigned long) lockTable, stripeID, lockReqDesc->type, lockReqDesc->start,        lockReqDesc->stop, lockReqDesc->start2, lockReqDesc->stop2);      Dprintf3("[%d] lock %ld hashval %d\n", tid, stripeID, hashval);      FLUSH;    }  }  if (stripeID == -1) return(0);  lockReqDesc->next = NULL;                       /* just to be sure */    RF_LOCK_MUTEX(lockTable[hashval].mutex);  for (lockDesc = lockTable[hashval].descList; lockDesc; lockDesc=lockDesc->next) {    if (lockDesc->stripeID == stripeID) break;  }    if (!lockDesc) {            /* no entry in table => no one reading or writing */    lockDesc = AllocStripeLockDesc(stripeID);    lockDesc->next = lockTable[hashval].descList;    lockTable[hashval].descList = lockDesc;    if (lockReqDesc->type == RF_IO_TYPE_WRITE) lockDesc->nWriters++;    lockDesc->granted = lockReqDesc;    if (rf_stripeLockDebug) {Dprintf7("[%d] no one waiting: lock %ld %c %ld-%ld %ld-%ld granted\n",				tid,stripeID,lockReqDesc->type,lockReqDesc->start,lockReqDesc->stop,lockReqDesc->start2,lockReqDesc->stop2); FLUSH;}  } else {    if (lockReqDesc->type == RF_IO_TYPE_WRITE) lockDesc->nWriters++;        if (lockDesc->nWriters == 0) {                        /* no need to search any lists if there are no writers anywhere */      lockReqDesc->next = lockDesc->granted;      lockDesc->granted = lockReqDesc;      if (rf_stripeLockDebug) {Dprintf7("[%d] no writers: lock %ld %c %ld-%ld %ld-%ld granted\n",				  tid,stripeID,lockReqDesc->type,lockReqDesc->start,lockReqDesc->stop,lockReqDesc->start2,lockReqDesc->stop2); FLUSH;}    } else {      /* search the granted & waiting lists for a conflict.  stop searching as soon as we find one */      retcode = 0;      for (p = lockDesc->granted; p; p=p->next) if (STRIPELOCK_CONFLICT(lockReqDesc, p)) {retcode = 1; break;}      if (!retcode) for (p = lockDesc->waitersH; p; p=p->next) if (STRIPELOCK_CONFLICT(lockReqDesc, p)) {retcode = 2; break;}      if (!retcode) {	lockReqDesc->next = lockDesc->granted;                                   /* no conflicts found => grant lock */	lockDesc->granted = lockReqDesc;	if (rf_stripeLockDebug) {		Dprintf7("[%d] no conflicts: lock %ld %c %ld-%ld %ld-%ld granted\n",			tid,stripeID,lockReqDesc->type,lockReqDesc->start,lockReqDesc->stop,			lockReqDesc->start2,lockReqDesc->stop2);		FLUSH;	}      } else {	if (rf_stripeLockDebug) {		Dprintf6("[%d] conflict: lock %ld %c %ld-%ld hashval=%d not granted\n",				tid,stripeID,lockReqDesc->type,lockReqDesc->start,lockReqDesc->stop,				hashval);		Dprintf3("[%d] lock %ld retcode=%d\n", tid, stripeID, retcode);		FLUSH;	}	AddToWaitersQueue(lockTable, lockDesc, lockReqDesc);                     /* conflict => the current access must wait */      }    }  }  RF_UNLOCK_MUTEX(lockTable[hashval].mutex);  return(retcode);}void rf_ReleaseStripeLock(  RF_LockTableEntry_t  *lockTable,  RF_StripeNum_t        stripeID,  RF_LockReqDesc_t     *lockReqDesc){  RF_StripeLockDesc_t *lockDesc, *ld_t;  RF_LockReqDesc_t    *lr, *lr_t, *callbacklist, *t;  RF_IoType_t type = lockReqDesc->type;  int tid, hashval = HASH_STRIPEID(stripeID);  int release_it, consider_it;  RF_LockReqDesc_t *candidate, *candidate_t, *predecessor;  RF_ASSERT(RF_IO_IS_R_OR_W(type));  if (rf_stripeLockDebug) {    rf_get_threadid(tid);    if (stripeID == -1) Dprintf1("[%d] Lock release supressed (stripeID == -1)\n",tid);    else {Dprintf8("[%d] Releasing stripe lock on stripe ID %ld, type %c range %ld-%ld %ld-%ld table 0x%lx\n",		 tid,stripeID,lockReqDesc->type,lockReqDesc->start,lockReqDesc->stop,lockReqDesc->start2,lockReqDesc->stop2, lockTable); FLUSH;}  }  if (stripeID == -1) return;    RF_LOCK_MUTEX(lockTable[hashval].mutex);  /* find the stripe lock descriptor */  for (ld_t = NULL, lockDesc = lockTable[hashval].descList; lockDesc; ld_t = lockDesc, lockDesc=lockDesc->next) {    if (lockDesc->stripeID == stripeID) break;  }  RF_ASSERT(lockDesc);                                    /* major error to release a lock that doesn't exist */  /* find the stripe lock request descriptor & delete it from the list */  for (lr_t = NULL, lr = lockDesc->granted; lr; lr_t = lr, lr=lr->next) if (lr == lockReqDesc) break;    RF_ASSERT(lr && (lr == lockReqDesc));                            /* major error to release a lock that hasn't been granted */  if (lr_t) lr_t->next = lr->next; else {    RF_ASSERT(lr == lockDesc->granted);    lockDesc->granted = lr->next;  }  lr->next = NULL;    if (lockReqDesc->type == RF_IO_TYPE_WRITE) lockDesc->nWriters--;  /* search through the waiters list to see if anyone needs to be woken up.   * for each such descriptor in the wait list, we check it against everything granted and against   * everything _in front_ of it in the waiters queue.  If it conflicts with none of these, we release it.   *   * DON'T TOUCH THE TEMPLINK POINTER OF ANYTHING IN THE GRANTED LIST HERE.  This will roach the case where   * the callback tries to acquire a new lock in the same stripe.  There are some asserts to try and detect this.   *   * We apply 2 performance optimizations:   * (1) if releasing this lock results in no more writers to this stripe, we just release everybody waiting,   * since we place no restrictions on the number of concurrent reads.   * (2) we consider as candidates for wakeup only those waiters that have a range overlap with either   * the descriptor being woken up or with something in the callbacklist (i.e. something we've just now woken up).   * This allows us to avoid the long evaluation for some descriptors.   */    callbacklist = NULL;  if (lockDesc->nWriters == 0) {                          /* performance tweak (1) */    while (lockDesc->waitersH) {            lr = lockDesc->waitersH;                            /* delete from waiters list */      lockDesc->waitersH = lr->next;            RF_ASSERT(lr->type == RF_IO_TYPE_READ);            lr->next = lockDesc->granted;                       /* add to granted list */      lockDesc->granted = lr;      RF_ASSERT(!lr->templink);      lr->templink = callbacklist;                        /* put on callback list so that we'll invoke callback below */      callbacklist = lr;      if (rf_stripeLockDebug) {Dprintf8("[%d] No writers: granting lock stripe ID %ld, type %c range %ld-%ld %ld-%ld table 0x%lx\n",				     tid,stripeID,lr->type,lr->start,lr->stop,lr->start2,lr->stop2,(unsigned long) lockTable); FLUSH;}    }    lockDesc->waitersT = NULL;                            /* we've purged the whole waiters list */        } else for (candidate_t = NULL, candidate = lockDesc->waitersH; candidate; ) {      /* performance tweak (2) */    consider_it = 0;    if (RANGE_OVERLAP(lockReqDesc, candidate)) consider_it = 1;    else for (t = callbacklist; t; t=t->templink) if (RANGE_OVERLAP(t, candidate)) {      consider_it = 1;      break;    }    if (!consider_it) {      if (rf_stripeLockDebug) {Dprintf8("[%d] No overlap: rejecting candidate stripeID %ld, type %c range %ld-%ld %ld-%ld table 0x%lx\n",				     tid, stripeID, candidate->type, candidate->start, candidate->stop, candidate->start2, candidate->stop2,				     (unsigned long) lockTable); FLUSH;}      candidate_t = candidate; candidate = candidate->next;      continue;    }            /* we have a candidate for release.  check to make sure it is not blocked by any granted locks */    release_it = 1;    for (predecessor = lockDesc->granted; predecessor; predecessor = predecessor->next) {      if (STRIPELOCK_CONFLICT(candidate, predecessor)) {	if (rf_stripeLockDebug) {	  Dprintf8("[%d] Conflicts with granted lock: rejecting candidate stripeID %ld, type %c range %ld-%ld %ld-%ld table 0x%lx\n",		   tid, stripeID, candidate->type, candidate->start, candidate->stop, candidate->start2, candidate->stop2,		   (unsigned long) lockTable); FLUSH;	}	release_it = 0; break;      }    }        /* now check to see if the candidate is blocked by any waiters that occur before it it the wait queue */    if (release_it) for (predecessor = lockDesc->waitersH; predecessor != candidate; predecessor = predecessor->next) {      if (STRIPELOCK_CONFLICT(candidate, predecessor)) {	if (rf_stripeLockDebug) {	  Dprintf8("[%d] Conflicts with waiting lock: rejecting candidate stripeID %ld, type %c range %ld-%ld %ld-%ld table 0x%lx\n",		   tid, stripeID, candidate->type, candidate->start, candidate->stop, candidate->start2, candidate->stop2,		   (unsigned long) lockTable); FLUSH;	}	release_it = 0; break;      }    }        /* release it if indicated */    if (release_it) {      if (rf_stripeLockDebug) {Dprintf8("[%d] Granting lock to candidate stripeID %ld, type %c range %ld-%ld %ld-%ld table 0x%lx\n",				     tid, stripeID, candidate->type, candidate->start, candidate->stop, candidate->start2, candidate->stop2,				     (unsigned long) lockTable); FLUSH;}      if (candidate_t) {	candidate_t->next = candidate->next;	if (lockDesc->waitersT == candidate) lockDesc->waitersT = candidate_t;       /* cannot be waitersH since candidate_t is not NULL */      } else {	RF_ASSERT(candidate == lockDesc->waitersH);	lockDesc->waitersH = lockDesc->waitersH->next;	if (!lockDesc->waitersH) lockDesc->waitersT = NULL;      }      candidate->next = lockDesc->granted;                    /* move it to the granted list */      lockDesc->granted = candidate;            RF_ASSERT(!candidate->templink);      candidate->templink = callbacklist;                     /* put it on the list of things to be called after we release the mutex */      callbacklist = candidate;            if (!candidate_t) candidate = lockDesc->waitersH; else candidate = candidate_t->next;     /* continue with the rest of the list */    } else {      candidate_t = candidate; candidate = candidate->next;                                     /* continue with the rest of the list */    }  }  /* delete the descriptor if no one is waiting or active */  if (!lockDesc->granted && !lockDesc->waitersH) {    RF_ASSERT(lockDesc->nWriters == 0);    if (rf_stripeLockDebug) {      Dprintf3("[%d] Last lock released (table 0x%lx): deleting desc for stripeID %ld\n",tid,(unsigned long) lockTable, stripeID); FLUSH;    }    if (ld_t) ld_t->next = lockDesc->next; else {      RF_ASSERT(lockDesc == lockTable[hashval].descList);      lockTable[hashval].descList = lockDesc->next;    }    FreeStripeLockDesc(lockDesc);    lockDesc = NULL;                                                               /* only for the ASSERT below */  }	  RF_UNLOCK_MUTEX(lockTable[hashval].mutex);  /* now that we've unlocked the mutex, invoke the callback on all the descriptors in the list */  RF_ASSERT(!( (callbacklist) && (!lockDesc) ));                   /* if we deleted the descriptor, we should have no callbacks to do */  for (candidate = callbacklist; candidate; ) {    t = candidate;    candidate = candidate->templink;    t->templink = NULL;    (t->cbFunc)(t->cbArg);  }}/* must have the indicated lock table mutex upon entry */static void AddToWaitersQueue(  RF_LockTableEntry_t  *lockTable,  RF_StripeLockDesc_t  *lockDesc,  RF_LockReqDesc_t     *lockReqDesc){  int tid;  if (rf_stripeLockDebug) {    rf_get_threadid(tid);    Dprintf3("[%d] Waiting on lock for stripe %ld table 0x%lx\n", tid, lockDesc->stripeID, (unsigned long) lockTable); FLUSH;  }  if (!lockDesc->waitersH) {    lockDesc->waitersH = lockDesc->waitersT = lockReqDesc;  } else {    lockDesc->waitersT->next = lockReqDesc;    lockDesc->waitersT = lockReqDesc;  }}static RF_StripeLockDesc_t *AllocStripeLockDesc(RF_StripeNum_t stripeID){	RF_StripeLockDesc_t *p;	RF_FREELIST_GET(rf_stripelock_freelist,p,next,(RF_StripeLockDesc_t *));	if (p) {		p->stripeID = stripeID;	}	return(p);}static void FreeStripeLockDesc(RF_StripeLockDesc_t *p){	RF_FREELIST_FREE(rf_stripelock_freelist,p,next);}static void PrintLockedStripes(lockTable)  RF_LockTableEntry_t  *lockTable;{  int i, j, foundone = 0, did;  RF_StripeLockDesc_t *p;  RF_LockReqDesc_t *q;  RF_LOCK_MUTEX(rf_printf_mutex);  printf("Locked stripes:\n");  for (i=0; i<rf_lockTableSize; i++) if (lockTable[i].descList) {    foundone = 1;    for (p = lockTable[i].descList; p; p=p->next) {      printf("Stripe ID 0x%lx (%d) nWriters %d\n",p->stripeID, p->stripeID, p->nWriters);            if (! (p->granted) ) printf("Granted: (none)\n"); else printf("Granted:\n");      for (did=1,j=0,q = p->granted; q; j++,q=q->next) {	printf("  %c(%ld-%ld",q->type,q->start,q->stop);	if (q->start2 != -1) printf(",%ld-%ld) ",q->start2,q->stop2); else printf(") ");	if (j && !(j%4)) {printf("\n"); did=1;} else did=0;      }      if (!did) printf("\n");            if (! (p->waitersH) ) printf("Waiting: (none)\n"); else printf("Waiting:\n");      for (did=1,j=0,q = p->waitersH; q; j++,q=q->next) {	printf("%c(%ld-%ld",q->type,q->start,q->stop);	if (q->start2 != -1) printf(",%ld-%ld) ",q->start2,q->stop2); else printf(") ");	if (j && !(j%4)) {printf("\n         "); did=1;} else did=0;      }      if (!did) printf("\n");    }  }  if (!foundone) printf("(none)\n"); else printf("\n");  RF_UNLOCK_MUTEX(rf_printf_mutex);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -