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

📄 disksim_cachemem.c

📁 disksim是一个非常优秀的磁盘仿真工具
💻 C
📖 第 1 页 / 共 5 页
字号:
      if (!(allocdesc->flags & CACHE_FLAG_LINELOCKED_ALLOCATE)) {         cache->linewaiters = allocdesc;      }   } else {      allocdesc->next = allocdesc;      cache->linewaiters = allocdesc;   }   allocdesc->flags |= CACHE_FLAG_LINELOCKED_ALLOCATE;}static cache_atom *cache_get_replace_startpoint (struct cache_mem *cache, int set){   cache_atom *line = cache->map[set].lru[0];   if (line) {      if (cache->replacepolicy == CACHE_REPLACE_RANDOM) {         int choice = cache->map[set].numactive[0] * DISKSIM_drand48();         int i;         for (i=0; i<choice; i++) {            line = line->lru_prev;         }      } else if (cache->replacepolicy == CACHE_REPLACE_LIFO) {         line = line->lru_prev;      } else if ((cache->replacepolicy != CACHE_REPLACE_FIFO) && (cache->replacepolicy != CACHE_REPLACE_SLRU)) {         fprintf(stderr, "Unknown replacement policy at cache_get_replace_startpoint: %d\n", cache->replacepolicy);         exit(1);      }   }   return(line);}/* Add identifier to lockstruct only if not already present */static void cache_add_to_lockstruct (struct cachelockw **head, void *identifier){   struct cachelockw *tmp = *head;   int start = FALSE;   int i;   if (tmp == NULL) {      tmp = (struct cachelockw *) getfromextraq();	  memset((char *)tmp, 0, sizeof(struct cachelockw));      /* bzero ((char *)tmp, sizeof(struct cachelockw)); */      tmp->entry[0] = identifier;      *head = tmp;   } else {      while (tmp->next) {         for (i=0; i<CACHE_LOCKSPERSTRUCT; i++) {            if (tmp->entry[i] == identifier) {               return;            }         }         tmp = tmp->next;      }      for (i=0; i<CACHE_LOCKSPERSTRUCT; i++) {         if (tmp->entry[i] == identifier) {            return;         } else if (tmp->entry[i]) {            start = TRUE;         } else if (start) {            tmp->entry[i] = identifier;            return;         }      }      tmp->next = (struct cachelockw *) getfromextraq();      tmp = tmp->next;	  memset ((char *)tmp, 0, sizeof(struct cachelockw));      /* bzero ((char *)tmp, sizeof(struct cachelockw)); */      tmp->entry[0] = identifier;   }}/* Does anyone have a write lock on the atom?? */static int cache_atom_iswritelocked (struct cache_mem *cache, cache_atom *target){   while (target->lbn % cache->lockgran) {      target = target->line_prev;   }   return(target->writelock != NULL);}/* Does anyone have any lock on the atom?? */static int cache_atom_islocked (struct cache_mem *cache, cache_atom *target){   while (target->lbn % cache->lockgran) {      target = target->line_prev;   }   return(target->readlocks || target->writelock);}#if 0/* should change this code so that newly enabled "I-streams" do not *//* necessarily preempt the "I-stream" that freed the lock...        */static void cache_give_lock_to_waiter (struct cache_mem *cache, cache_atom *target, struct cache_mem_event *rwdesc){   switch (rwdesc->type) {      case CACHE_EVENT_READ:                               cache_read_continue(cache, rwdesc);                               break;      case CACHE_EVENT_WRITE:                               cache_write_continue(cache, rwdesc);                               break;      default:       fprintf(stderr, "Unknown type at cache_give_lock_to_waiter: %d\n", rwdesc->type);       exit(1);   }}#endifstatic void cache_lock_free (struct cache_mem *cache, cache_atom *target){   cache_lockwaiters *tmp;   int writelocked = FALSE;	      /* Can't give away a line that is writelock'd */   ASSERT(!target->writelock);   if ((tmp = target->lockwaiters)) {      int i = 0;      while ((tmp) && (!writelocked) && (!target->writelock)) {         struct cache_mem_event *waiter = NULL;         if (tmp->entry[i]) {            writelocked = (cache->sharedreadlocks == 0) || tmp->entry[i]->locktype;            if ((!writelocked) || (target->readlocks == NULL)) {               waiter = tmp->entry[i];               tmp->entry[i] = NULL;            }         }         i++;         if (i == CACHE_LOCKSPERSTRUCT) {            target->lockwaiters = tmp->next;            addtoextraq((event *) tmp);            tmp = target->lockwaiters;            i = 0;         }         if (waiter) {	    (*cache->wakeupfunc)(cache->wakeupparam, (struct cacheevent *)waiter);         }      }   } else if (cache->linewaiters) {      int linesize = max(cache->linesize, 1);      struct cache_mem_event *allocdesc;      while (target->lbn % linesize) {         target = target->line_prev;      }      while (target) {         if ((target->writelock) || (target->readlocks)) {            return;         }         target = target->line_next;      }      allocdesc = cache->linewaiters->next;      if (allocdesc->next == allocdesc) {         cache->linewaiters = NULL;      } else {         cache->linewaiters->next = allocdesc->next;      }      allocdesc->next = NULL;      // fprintf (outputfile, "allocation continuing: line finally freed\n");      (*cache->wakeupfunc)(cache->wakeupparam, (struct cacheevent *)allocdesc);   }}/* gransize is assumed to be a factor of linesize */static int cache_get_write_lock (struct cache_mem *cache, cache_atom *target, struct cache_mem_event *rwdesc){   //fprintf (outputfile, "Entered cache_get_write_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran);   while (target->lbn % cache->lockgran) {      target = target->line_prev;   }   // fprintf (outputfile, "doing cache_get_write_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran);   if (target->writelock == rwdesc->req) {      return(cache->lockgran);   } else if ((target->writelock) || (target->readlocks)) {      rwdesc->locktype = 1;      cache_add_to_lockstruct(&target->lockwaiters, rwdesc);      return(0);   } else {      target->writelock = rwdesc->req;      return(cache->lockgran);   }}static int cache_free_write_lock (struct cache_mem *cache, cache_atom *target, ioreq_event *owner){   // fprintf (outputfile, "Entered cache_free_write_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran);   while (target->lbn % cache->lockgran) {      target = target->line_prev;   }   // fprintf (outputfile, "doing cache_free_write_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran);   if (owner == target->writelock) {      target->writelock = NULL;      cache_lock_free(cache, target);      return(cache->lockgran);   } else {      return(0);   }}static int cache_get_read_lock (struct cache_mem *cache, cache_atom *target, struct cache_mem_event *rwdesc){   // fprintf (outputfile, "Entered cache_get_read_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran);   if (!cache->sharedreadlocks) {      return(cache_get_write_lock(cache, target, rwdesc));   }   while (target->lbn % cache->lockgran) {      target = target->line_prev;   }   // fprintf (outputfile, "doing cache_get_read_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran);   if ((target->writelock) && (target->writelock != rwdesc->req)) {      rwdesc->locktype = 0;      cache_add_to_lockstruct(&target->lockwaiters, rwdesc);      return(0);   } else {      cache_add_to_lockstruct((struct cachelockw **)&target->readlocks, rwdesc->req);      if (target->writelock) {         target->writelock = NULL;         cache_lock_free(cache, target);      }      return(cache->lockgran);   }}static int cache_free_read_lock (struct cache_mem *cache, cache_atom *target, ioreq_event *owner){   cache_lockholders *tmp;   int found = FALSE;   int i;   // fprintf (outputfile, "Entered cache_free_read_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran);   if (!cache->sharedreadlocks) {      return(cache_free_write_lock(cache, target, owner));   }   // fprintf (outputfile, "doing cache_free_read_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran);   while (target->lbn % cache->lockgran) {      target = target->line_prev;   }   tmp = target->readlocks;   while ((tmp) && (!found)) {      int active = FALSE;      for (i=0; i<CACHE_LOCKSPERSTRUCT; i++) {         if (tmp->entry[i] == owner) {            tmp->entry[i] = 0;            found = TRUE;         } else if (tmp->entry[i]) {            active = TRUE;         }      }      if ((tmp == target->readlocks) && (active == FALSE)) {         target->readlocks = tmp->next;         addtoextraq((event *) tmp);         tmp = target->readlocks;      } else {         tmp = tmp->next;      }   }   if (found) {      if (!target->readlocks) {         cache_lock_free(cache, target);      }      return(cache->lockgran);   } else {      return(0);   }}static void cache_get_read_lock_range (struct cache_mem *cache, int start, int end, cache_atom *startatom, struct cache_mem_event *waiter){   cache_atom *line = (startatom->lbn == start) ? startatom : NULL;   int lockgran = 1;   int i;   for (i=start; i<=end; i++) {      if (line == NULL) {         line = cache_find_atom(cache, startatom->devno, i);         ASSERT(line != NULL);      }      if ((line->lbn % lockgran) == 0) {         lockgran = cache_get_read_lock(cache, line, waiter);             /* Must not fail to acquire lock */         ASSERT(lockgran != 0);      }      line = line->line_next;   }}static int cache_issue_flushreq (struct cache_mem *cache, int start, int end, cache_atom *startatom, struct cache_mem_event *waiter){   ioreq_event *flushreq;   ioreq_event *flushwait;   int waiting = (cache->IOwaiters == waiter) ? 1 : 0;   // fprintf (outputfile, "Entered issue_flushreq: start %d, end %d\n", start, end);   flushreq = (ioreq_event *) getfromextraq();   flushreq->devno = startatom->devno;   flushreq->blkno = start;   flushreq->bcount = end - start + 1;   flushreq->busno = startatom->busno;   flushreq->slotno = startatom->slotno;   flushreq->type = IO_ACCESS_ARRIVE;   flushreq->flags = 0;   flushwait = (ioreq_event *) getfromextraq();   flushwait->type = IO_REQUEST_ARRIVE;   flushwait->devno = flushreq->devno;   flushwait->blkno = flushreq->blkno;   flushwait->bcount = flushreq->bcount;   flushwait->next = waiter->req;   flushwait->prev = NULL;   if (waiter->req) {      waiter->req->prev = flushwait;   }   waiter->req = flushwait;   waiter->accblkno = -1;   if (!waiting) {      cache_waitfor_IO(cache, 1, waiter, flushwait);   }   waiter->accblkno = -1;   cache->stat.destagewrites++;   cache->stat.destagewriteatoms += end - start + 1;   cache_get_read_lock_range(cache, start, end, startatom, waiter);   // fprintf (outputfile, "Issueing dirty block write-back: blkno %d, bcount %d, devno %d\n", flushreq->blkno, flushreq->bcount, flushreq->devno);   (*cache->issuefunc)(cache->issueparam, flushreq);   return(1);}static int cache_flush_cluster (struct cache_mem *cache, int devno, int blkno, int linecnt, int dir){   cache_atom *line = NULL;   int lastclean = 0;   int writelocked;   ASSERT1((dir == 1) || (dir == -1), "dir", dir);   while (linecnt <= cache->flush_maxlinecluster) {      if (line == NULL) {	 line = cache_find_atom(cache, devno, (blkno+dir));	 if ((line == NULL) || (lastclean)) {	    break;	 }	 linecnt++;	 continue;      }      writelocked = cache_atom_iswritelocked(cache, line);      if ((line->state & CACHE_DIRTY) && (!writelocked)) {         line->state &= ~CACHE_DIRTY;	 lastclean = 0;	 blkno = line->lbn;      } else if ((writelocked) || (!(line->state & CACHE_VALID))) {	 break;      } else {	 lastclean = 1;      }      line = (dir == 1) ? line->line_next : line->line_prev;   }   return(blkno);}static int cache_initiate_dirty_block_flush (struct cache_mem *cache, cache_atom *dirtyline, struct cache_mem_event *allocdesc){   cache_atom *dirtyatom = 0;   int dirtyend = 0;   int dirtystart = -1;   cache_atom *tmp = dirtyline;   int flushcnt = 0;   // fprintf (outputfile, "Entered cache_initiate_dirty_block_flush: %d\n", dirtyline->lbn);   while (tmp) {      int writelocked = cache_atom_iswritelocked(cache, tmp);      if ((tmp->state & CACHE_DIRTY) && (!writelocked)) {         tmp->state &= ~CACHE_DIRTY;         if (dirtystart == -1) {            dirtyatom = tmp;            dirtystart = tmp->lbn;         }         dirtyend = tmp->lbn;      } else if ((dirtystart != -1) && ((!(tmp->state & CACHE_VALID)) || (writelocked))) {         if ((cache->flush_maxlinecluster > 1) && (dirtystart == dirtyline->lbn)) {

⌨️ 快捷键说明

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