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

📄 disksim_cachemem.c

📁 目前最精确的磁盘模拟器的第3版
💻 C
📖 第 1 页 / 共 5 页
字号:
   // 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 (cache_def *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 (cache_def *cache, int start, int end, cache_atom *startatom, cache_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 (cache_def *cache, int start, int end, cache_atom *startatom, cache_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 (cache_def *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 (cache_def *cache, cache_atom *dirtyline, cache_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)) {
            dirtystart = cache_flush_cluster(cache, dirtyatom->devno, dirtystart, 1, -1);
         }
         if (cache_issue_flushreq(cache, dirtystart, dirtyend, dirtyatom, allocdesc) == 0) {
            return(flushcnt);
         }
         dirtystart = -1;
         flushcnt++;
      }
      tmp = tmp->line_next;
   }
   if (dirtystart != -1) {
      int linesize = max(cache->linesize, 1);
      int linecnt;
      if ((cache->flush_maxlinecluster > 1) && (dirtystart == dirtyline->lbn)) {
         dirtystart = cache_flush_cluster(cache, dirtyatom->devno, dirtystart, 1, -1);
      }
      linecnt = 1 + ((dirtyline->lbn - dirtystart) / linesize);
      if ((linecnt < cache->flush_maxlinecluster) && (dirtyend == (dirtyline->lbn + linesize -1))) {
	 dirtyend = cache_flush_cluster(cache, dirtyatom->devno, dirtyend, linecnt, 1);
      }
      flushcnt += cache_issue_flushreq(cache, dirtystart, dirtyend, dirtyatom, allocdesc);
   }

   // fprintf (outputfile, "flushcnt %d\n", flushcnt);

   return(flushcnt);
}


static cache_event *cache_get_flushdesc()
{
   cache_event *flushdesc = (cache_event *) getfromextraq();
   flushdesc->type = CACHE_EVENT_SYNC;
   flushdesc->donefunc = &disksim->donefunc_cachemem_empty;
   flushdesc->req = NULL;
   return(flushdesc);
}


static void cache_cleanup_flushdesc (cache_event *flushdesc)
{
   if (flushdesc->req) {
      if (flushdesc->req->next == NULL) {
         flushdesc->accblkno = flushdesc->req->blkno;
      }
   } else {
      addtoextraq((event *) flushdesc);
   }
}


/* Not currently dealing with case of two-handed flushing.  Easiest way to */
/* do this will be to allocate the cache as one big chunk of memory.  Then,*/
/* use the addresses of cache_atoms rather than the pointers to traverse.  */

static void cache_periodic_flush (timer_event *timereq)
{
   cache_def *cache = (cache_def *) timereq->ptr;
   int segcnt = (cache->replacepolicy == CACHE_REPLACE_SLRU) ? cache->numsegs : 1;
   int i, j;
   cache_atom *line;
   cache_atom *stop;
   cache_atom *tmp;
   cache_event *flushdesc = cache_get_flushdesc();
   int flushcnt = 0;
   int startit;

   for (i=0; i<=cache->mapmask; i++) {
      for (j=0; j<segcnt; j++) {
         line = cache->map[i].lru[j];
         stop = line;
         startit = 1;
         while ((startit) || (line != stop)) {
            startit = 0;
            tmp = line;
            while (tmp) {
               if (tmp->state & CACHE_DIRTY) {
                  flushcnt += cache_initiate_dirty_block_flush(cache, tmp, flushdesc);
               }
               tmp = tmp->line_next;
            }
            line = line->lru_next;
         };
      }
   }
   cache_cleanup_flushdesc(flushdesc);
   timereq->time += cache->flush_period;
   addtointq((event *)timereq);

   // fprintf (outputfile, "%f: cache_periodic_flush, %d flushes started\n", simtime, flushcnt);
}


static void cache_idletime_detected (void *idleworkparam, int idledevno)
{
   cache_def *cache = idleworkparam;
   cache_atom *line = cache_get_replace_startpoint(cache, 0);
   cache_atom *stop = line;
   cache_atom *tmp;
   int segcnt = (cache->replacepolicy == CACHE_REPLACE_SLRU) ? cache->numsegs : 1;
   int i;
   cache_event *flushdesc;
   int startit;

   if (ioqueue_get_number_in_queue((*cache->queuefind)(cache->queuefindparam, idledevno))) {
      return;
   }

   flushdesc = cache_get_flushdesc();
   flushdesc->type = CACHE_EVENT_IDLESYNC;

   for (i=0; i<segcnt; i++) {
      if (i) {
         line = cache->map[0].lru[i];
         stop = line;
      }
      startit = 1;
      while ((startit) || (line != stop)) {
         startit = 0;
         if (line->devno == idledevno) {
            tmp = line;
            while (tmp) {
               if (tmp->state & CACHE_DIRTY) {
                  (void)cache_initiate_dirty_block_flush(cache, tmp, flushdesc);
                  if (flushdesc->req) {
                     goto cache_idletime_detected_idleused;
                  }
               }
               tmp = tmp->line_next;
            }
         }
         line = line->lru_next;
      }
   }

cache_idletime_detected_idleused:

   cache_cleanup_flushdesc(flushdesc);
}


static void cache_unmap_line (cache_def *cache, cache_atom *line, int set)
{
   cache_atom *tmp;

   if (line->lru_next) {
      cache_remove_from_lrulist(&cache->map[set], line, (line->state & CACHE_SEGNUM));
   }
   if (cache->linesize == 0) {
      while ((tmp = line)) {
         line = line->line_next;
         tmp->line_next = NULL;
         tmp->line_prev = NULL;
         cache_remove_entry_from_hash(cache, tmp);
         cache_add_to_lrulist(&cache->map[set], tmp, CACHE_SEGNUM);
      }
   } else {
      cache_add_to_lrulist(&cache->map[set], line, CACHE_SEGNUM);
      while (line) {
         cache_remove_entry_from_hash(cache, line);
         line = line->line_next;
      }
   }
}


static int cache_replace (cache_def *cache, int set, cache_event *allocdesc)
{
   int numwrites;
   cache_atom *line;
   cache_atom *tmp;
   cache_atom *stop;
   int dirty = FALSE;
   int locked = FALSE;
   cache_event *flushdesc = (cache->allocatepolicy & CACHE_ALLOCATE_NONDIRTY) ? NULL : allocdesc;

   if (cache->map[set].freelist) {
      return(0);
   }
   if ((line = cache_get_replace_startpoint(cache, set)) == NULL) {
          /* All lines between ownership */
      cache_replace_waitforline(cache, allocdesc);
      return(-1);
   }
   stop = line;

cache_replace_loop_continue:

   if (locked | dirty) {
      line = (cache->replacepolicy == CACHE_REPLACE_LIFO) ? line->lru_prev : line->lru_next;
   }
   if (line == stop) {
      if (locked) {
         if ((flushdesc) && (cache->allocatepolicy & CACHE_ALLOCATE_NONDIRTY)) {
            cache_cleanup_flushdesc(flushdesc);
         }
         cache_replace_waitforline(cache, allocdesc);
         return(-1);
      }
   }

   locked = FALSE;
   tmp = line;
   while (tmp) {
      if ((locked = (tmp->readlocks || tmp->writelock))) {
	 goto cache_replace_loop_continue;
      }
      tmp = tmp->line_next;
   }

   dirty = FALSE;
   tmp = line;
   while (tmp) {
      if ((dirty = tmp->state & CACHE_DIRTY)) {
         if (flushdesc == NULL) {
            flushdesc = cache_get_flushdesc();
         }
         numwrites = cache_initiate_dirty_block_flush(cache, tmp, flushdesc);
         if (cache->allocatepolicy & CACHE_ALLOCATE_NONDIRTY) {
            goto cache_replace_loop_continue;
         } else {
            return(numwrites);
         }
      }
      tmp = tmp->line_next;
   }

   cache_unmap_line(cache, line, set);

   return(0);

⌨️ 快捷键说明

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