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

📄 disksim_cachedev.c

📁 目前最精确的磁盘模拟器的第3版
💻 C
📖 第 1 页 / 共 2 页
字号:
   ioreq_event *fillreq;
   int devno;

   // fprintf (outputfile, "totalreqs = %d\n", disksim->totalreqs);
   // fprintf (outputfile, "%.5f: Entered cache_get_block: rw %d, devno %d, blkno %d, size %d\n", simtime, (req->flags & READ), req->devno, req->blkno, req->bcount);

   if (req->devno != cache->real_devno) {
      fprintf (stderr, "cachedev_get_block trying to cache blocks for wrong device (%d should be %d)\n", req->devno, cache->real_devno);
      ASSERT(0);
      exit(1);
   }

   /* Ignore request overlap and locking issues for now.  */
   /* Also ignore buffer space limitation issues for now. */
   cache->bufferspace += req->bcount;
   if (cache->bufferspace > cache->stat.maxbufferspace) {
      cache->stat.maxbufferspace = cache->bufferspace;
   }

   rwdesc->type = (req->flags & READ) ? CACHE_EVENT_READ : CACHE_EVENT_WRITE;
   rwdesc->donefunc = donefunc;
   rwdesc->doneparam = doneparam;
   rwdesc->req = req;
   req->next = NULL;
   req->prev = NULL;
   rwdesc->flags = 0;
   cachedev_add_ongoing_request (cache, rwdesc);

   if (req->flags & READ) {
      cache->stat.reads++;
      cache->stat.readblocks += req->bcount;

      /* Send read straight to whichever device has it (preferably cachedev). */
      if (cachedev_isreadhit (cache, req)) {
         devno = cache->cache_devno;
         cache->stat.readhitsfull++;
      } else {
         devno = cache->real_devno;
         cache->stat.readmisses++;
      }
      /* For now, just assume both device's store bits at same LBNs */
      fillreq = ioreq_copy (req);
      fillreq->buf = rwdesc;
      fillreq->type = IO_ACCESS_ARRIVE;
      fillreq->devno = devno;

      // fprintf (outputfile, "fillreq: devno %d, blkno %d, buf %p\n", fillreq->devno, fillreq->blkno, fillreq->buf);

      (*cache->issuefunc)(cache->issueparam, fillreq);
      return (1);

   } else {
      /* Grab buffer space and let the controller fill in data to be written. */
      /* (for now, just assume that there is buffer space available)          */

      (*donefunc)(doneparam, req);
      return (0);
   }
}


/* frees the block after access complete, block is clean so remove locks */
/* and update lru                                                        */

void cachedev_free_block_clean (cache_def *cache, ioreq_event *req)
{
   cache_event *rwdesc;

   // fprintf (outputfile, "%.5f: Entered cache_free_block_clean: blkno %d, bcount %d, devno %d\n", simtime, req->blkno, req->bcount, req->devno);

   /* For now, just find relevant rwdesc and free it.                       */
   /* Later, write it to the cache device (and update the cache map thusly. */

   rwdesc = cachedev_find_ongoing_request (cache, req);
   ASSERT (rwdesc != NULL);

   if (rwdesc->type == CACHE_EVENT_READ) {
      cache->bufferspace -= req->bcount;
      cachedev_remove_ongoing_request (cache, rwdesc);
      addtoextraq ((event *) rwdesc);
   } else {
      ASSERT (rwdesc->type == CACHE_EVENT_POPULATE_ALSO);
      rwdesc->type = CACHE_EVENT_POPULATE_ONLY;
   }
}


/* a delayed write - set dirty bits, remove locks and update lru.        */
/* If cache doesn't allow delayed writes, forward this to async          */

int cachedev_free_block_dirty (cache_def *cache, ioreq_event *req, void (**donefunc)(void *, ioreq_event *), void *doneparam)
{
   ioreq_event *flushreq;
   cache_event *writedesc;

   // fprintf (outputfile, "%.5f, Entered cache_free_block_dirty: blkno %d, size %d\n", simtime, req->blkno, req->bcount);

   cache->stat.writes++;
   cache->stat.writeblocks += req->bcount;

   writedesc = cachedev_find_ongoing_request (cache, req);
   ASSERT (writedesc != NULL);
   ASSERT (writedesc->type == CACHE_EVENT_WRITE);

   writedesc->donefunc = donefunc;
   writedesc->doneparam = doneparam;
   writedesc->req = req;
   req->type = IO_REQUEST_ARRIVE;
   req->next = NULL;
   req->prev = NULL;

   /* For now, just assume both device's store bits at same LBNs */
   flushreq = ioreq_copy(req);
   flushreq->type = IO_ACCESS_ARRIVE;
   flushreq->buf = writedesc;
   if (cachedev_iswritehit (cache, req)) {
      flushreq->devno = cache->cache_devno;
      cache->stat.writehitsfull++;
   } else {
      cache->stat.writemisses++;
   }

   // fprintf (outputfile, "flushreq: devno %d, blkno %d, buf %p\n", flushreq->devno, flushreq->blkno, flushreq->buf);

   (*cache->issuefunc)(cache->issueparam, flushreq);

#if 0
   if (cache->flush_idledelay >= 0.0) {
      ioqueue_reset_idledetecter((*cache->queuefind)(cache->queuefindparam, req->devno), 0);
   }
#endif

   return(1);
}


int cachedev_sync (cache_def *cache)
{
   return(0);
}


struct cacheevent *cachedev_disk_access_complete (cache_def *cache, ioreq_event *curr)
{
   cache_event *rwdesc = curr->buf;
   cache_event *tmp = NULL;

   // fprintf (outputfile, "Entered cache_disk_access_complete: blkno %d, bcount %d, devno %d, buf %p\n", curr->blkno, curr->bcount, curr->devno, curr->buf);

   if (rwdesc->type == CACHE_EVENT_READ) {
      /* Consider writing same buffer to cache_devno, in order to populate it.*/
      /* Not clear whether it is more appropriate to do it from here or from  */
      /* "free_block_clean" -- do it here for now to get more overlap.        */
      if (curr->devno == cache->real_devno) {
         ioreq_event *flushreq = ioreq_copy(rwdesc->req);
         flushreq->type = IO_ACCESS_ARRIVE;
         flushreq->buf = rwdesc;
         flushreq->flags = WRITE;
         flushreq->devno = cache->cache_devno;
         rwdesc->type = CACHE_EVENT_POPULATE_ALSO;
         (*cache->issuefunc)(cache->issueparam, flushreq);
         cache->stat.popwrites++;
         cache->stat.popwriteblocks += rwdesc->req->bcount;
      }

      /* Ongoing read request can now proceed, so call donefunc from get_block*/
      (*rwdesc->donefunc)(rwdesc->doneparam,rwdesc->req);

   } else if (rwdesc->type == CACHE_EVENT_WRITE) {

      /* finished writing to cache-device */
      if (curr->devno == cache->cache_devno) {
         cachedev_setbits (cache->validmap, curr);
         cachedev_setbits (cache->dirtymap, curr);
         if (cache->writescheme == CACHE_WRITE_THRU) {
            ioreq_event *flushreq = ioreq_copy(rwdesc->req);
            flushreq->type = IO_ACCESS_ARRIVE;
            flushreq->buf = rwdesc;
            flushreq->flags = WRITE;
            flushreq->devno = cache->real_devno;
            rwdesc->type = CACHE_EVENT_FLUSH;
            (*cache->issuefunc)(cache->issueparam, flushreq);
            cache->stat.destagewrites++;
            cache->stat.destagewriteblocks += rwdesc->req->bcount;
         }
      }
      (*rwdesc->donefunc)(rwdesc->doneparam,rwdesc->req);

      if (rwdesc->type != CACHE_EVENT_FLUSH) {
         cachedev_remove_ongoing_request (cache, rwdesc);
         addtoextraq ((event *) rwdesc);
         cache->bufferspace -= curr->bcount;
      }

   } else if (rwdesc->type == CACHE_EVENT_POPULATE_ONLY) {
      cachedev_setbits (cache->validmap, curr);
      cachedev_remove_ongoing_request (cache, rwdesc);
      addtoextraq ((event *) rwdesc);
      cache->bufferspace -= curr->bcount;

   } else if (rwdesc->type == CACHE_EVENT_POPULATE_ALSO) {
      cachedev_setbits (cache->validmap, curr);
      rwdesc->type = CACHE_EVENT_READ;

   } else if (rwdesc->type == CACHE_EVENT_FLUSH) {
      cachedev_clearbits (cache->dirtymap, curr);
      cachedev_remove_ongoing_request (cache, rwdesc);
      addtoextraq ((event *) rwdesc);
      cache->bufferspace -= curr->bcount;

   } else if (rwdesc->type == CACHE_EVENT_IDLEFLUSH_READ) {
      ioreq_event *flushreq = ioreq_copy (curr);
      flushreq->type = IO_ACCESS_ARRIVE;
      flushreq->flags = WRITE;
      flushreq->devno = cache->real_devno;
      rwdesc->type = CACHE_EVENT_IDLEFLUSH_FLUSH;
      (*cache->issuefunc)(cache->issueparam, flushreq);
      cache->stat.destagewrites++;
      cache->stat.destagewriteblocks += curr->bcount;

   } else if (rwdesc->type == CACHE_EVENT_IDLEFLUSH_FLUSH) {
      cachedev_clearbits (cache->dirtymap, curr);
      cachedev_remove_ongoing_request (cache, rwdesc);
      addtoextraq ((event *) rwdesc);
      cachedev_idlework_callback (cache, curr->devno);
      cache->bufferspace -= curr->bcount;

   } else {
      fprintf(stderr, "Unknown type at cachedev_disk_access_complete: %d\n", rwdesc->type);
      ASSERT(0);
      exit(1);
   }

   addtoextraq((event *) curr);

   /* returned cacheevent will get forwarded to cachedev_wakeup_continue... */
   return(tmp);
}


void cachedev_wakeup_complete (cache_def *cache, cache_event *desc)
{
   ASSERT (0);
#if 0
   if (desc->type == CACHE_EVENT_READ) {
      cache_read_continue(cache, desc);
   } else if (desc->type == CACHE_EVENT_WRITE) {
      cache_write_continue(cache, desc);
   } else if (desc->type == CACHE_EVENT_FLUSH) {
      (*desc->donefunc)(desc->doneparam, desc->req);
      addtoextraq((event *) desc);
   } else {
      fprintf(stderr, "Unknown event type in cache_wakeup_complete: %d\n", desc->type);
      assert(0);
      exit(1);
   }
#endif
}


void cachedev_resetstats (cache_def *cache)
{
   cache->stat.reads = 0;
   cache->stat.readblocks = 0;
   cache->stat.readhitsfull = 0;
   cache->stat.readmisses = 0;
   cache->stat.popwrites = 0;
   cache->stat.popwriteblocks = 0;
   cache->stat.writes = 0;
   cache->stat.writeblocks = 0;
   cache->stat.writehitsfull = 0;
   cache->stat.writemisses = 0;
   cache->stat.destagereads = 0;
   cache->stat.destagereadblocks = 0;
   cache->stat.destagewrites = 0;
   cache->stat.destagewriteblocks = 0;
   cache->stat.maxbufferspace = 0;
}


void cachedev_setcallbacks ()
{
   disksim->donefunc_cachedev_empty = cachedev_empty_donefunc;
   disksim->idlework_cachedev = cachedev_idlework_callback;
   disksim->timerfunc_cachedev = cachedev_periodic_callback;
}


void cachedev_initialize (cache_def *cache, 
			  void (**issuefunc)(void *,ioreq_event *), 
			  void *issueparam, 
			  struct ioq * (**queuefind)(void *,int), 
			  void *queuefindparam, 
			  void (**wakeupfunc)(void *,struct cacheevent *), 
			  void *wakeupparam, 
			  int numdevs)
{
   StaticAssert (sizeof(cache_event) <= DISKSIM_EVENT_SIZE);

   cache->issuefunc = issuefunc;
   cache->issueparam = issueparam;
   cache->queuefind = queuefind;
   cache->queuefindparam = queuefindparam;
   cache->wakeupfunc = wakeupfunc;
   cache->wakeupparam = wakeupparam;
   cache->bufferspace = 0;
   cache->ongoing_requests = NULL;
   bzero (cache->validmap, bitstr_size(cache->size));
   bzero (cache->dirtymap, bitstr_size(cache->size));
   cachedev_resetstats(cache);

   if (cache->flush_idledelay) {
      struct ioq *queue = (*queuefind)(queuefindparam,cache->real_devno);
      ASSERT (queue != NULL);
      ioqueue_set_idlework_function (queue, &disksim->idlework_cachedev, cache, cache->flush_idledelay);
   }

   if (device_get_number_of_blocks(cache->cache_devno) < cache->size) {
      fprintf (stderr, "Size of cachedev exceeds that of actual cache device (devno %d): %d > %d\n", cache->cache_devno, cache->size, device_get_number_of_blocks(cache->cache_devno));
      exit (0);
   }
}


void cachedev_cleanstats (cache_def *cache)
{
}


void cachedev_printstats (cache_def *cache, char *prefix)
{
   int reqs = cache->stat.reads + cache->stat.writes;
   int blocks = cache->stat.readblocks + cache->stat.writeblocks;

   fprintf (outputfile, "%scache requests:             %6d\n", prefix, reqs);
   if (reqs == 0) {
      return;
   }
   fprintf (outputfile, "%scache read requests:        %6d  \t%6.4f\n", prefix, cache->stat.reads, ((double) cache->stat.reads / (double) reqs));
   if (cache->stat.reads) {
      fprintf(outputfile, "%scache blocks read:           %6d  \t%6.4f\n", prefix, cache->stat.readblocks, ((double) cache->stat.readblocks / (double) blocks));
      fprintf(outputfile, "%scache read misses:          %6d  \t%6.4f  \t%6.4f\n", prefix, cache->stat.readmisses, ((double) cache->stat.readmisses / (double) reqs), ((double) cache->stat.readmisses / (double) cache->stat.reads));
      fprintf(outputfile, "%scache read full hits:       %6d  \t%6.4f  \t%6.4f\n", prefix, cache->stat.readhitsfull, ((double) cache->stat.readhitsfull / (double) reqs), ((double) cache->stat.readhitsfull / (double) cache->stat.reads));
      fprintf(outputfile, "%scache population writes:         %6d  \t%6.4f  \t%6.4f\n", prefix, cache->stat.popwrites, ((double) cache->stat.popwrites / (double) reqs), ((double) cache->stat.popwrites / (double) cache->stat.reads));
      fprintf(outputfile, "%scache block population writes:    %6d  \t%6.4f  \t%6.4f\n", prefix, cache->stat.popwriteblocks, ((double) cache->stat.popwriteblocks / (double) blocks), ((double) cache->stat.popwriteblocks / (double) cache->stat.readblocks));
   }
   fprintf(outputfile, "%scache write requests:       %6d  \t%6.4f\n", prefix, cache->stat.writes, ((double) cache->stat.writes / (double) reqs));
   if (cache->stat.writes) {
      fprintf(outputfile, "%scache blocks written:        %6d  \t%6.4f\n", prefix, cache->stat.writeblocks, ((double) cache->stat.writeblocks / (double) blocks));
      fprintf(outputfile, "%scache write misses:         %6d  \t%6.4f  \t%6.4f\n", prefix, cache->stat.writemisses, ((double) cache->stat.writemisses / (double) reqs), ((double) cache->stat.writemisses / (double) cache->stat.writes));
      fprintf(outputfile, "%scache full write hits:   %6d  \t%6.4f  \t%6.4f\n", prefix, cache->stat.writehitsfull, ((double) cache->stat.writehitsfull / (double) reqs), ((double) cache->stat.writehitsfull / (double) cache->stat.writes));
      fprintf(outputfile, "%scache destage pre-reads:     %6d  \t%6.4f  \t%6.4f\n", prefix, cache->stat.destagereads, ((double) cache->stat.destagereads / (double) reqs), ((double) cache->stat.destagereads / (double) cache->stat.writes));
      fprintf(outputfile, "%scache block destage pre-reads: %6d  \t%6.4f  \t%6.4f\n", prefix, cache->stat.destagereadblocks, ((double) cache->stat.destagereadblocks / (double) blocks), ((double) cache->stat.destagereadblocks / (double) cache->stat.writeblocks));
      fprintf(outputfile, "%scache destages (write):     %6d  \t%6.4f  \t%6.4f\n", prefix, cache->stat.destagewrites, ((double) cache->stat.destagewrites / (double) reqs), ((double) cache->stat.destagewrites / (double) cache->stat.writes));
      fprintf(outputfile, "%scache block destages (write): %6d  \t%6.4f  \t%6.4f\n", prefix, cache->stat.destagewriteblocks, ((double) cache->stat.destagewriteblocks / (double) blocks), ((double) cache->stat.destagewriteblocks / (double) cache->stat.writeblocks));
      fprintf(outputfile, "%scache end dirty blocks:      %6d  \t%6.4f\n", prefix, cachedev_count_dirty_blocks(cache), ((double) cachedev_count_dirty_blocks(cache) / (double) cache->stat.writeblocks));
   }
   fprintf (outputfile, "%scache bufferspace use end:             %6d\n", prefix, cache->bufferspace);
   fprintf (outputfile, "%scache bufferspace use max:             %6d\n", prefix, cache->stat.maxbufferspace);
}


cache_def * cachedev_copy (cache_def *cache)
{
   cache_def *new = (cache_def *) DISKSIM_malloc(sizeof(cache_def));

   ASSERT(new != NULL);
   bzero (new, sizeof(cache_def));

   new->cachetype = cache->cachetype;
   new->issuefunc = cache->issuefunc;
   new->issueparam = cache->issueparam;
   new->queuefind = cache->queuefind;
   new->queuefindparam = cache->queuefindparam;
   new->wakeupfunc = cache->wakeupfunc;
   new->wakeupparam = cache->wakeupparam;
   new->size = cache->size;
   new->maxreqsize = cache->maxreqsize;

   return(new);
}



struct cache_def *disksim_cachedev_loadparams(struct lp_block *b)
{
  int c;
  struct cache_def *result;

  result = malloc(sizeof(struct cache_def));
  bzero(result, sizeof(struct cache_def));


  result->cachetype = CACHE_DEVICE;
  result->name = b->name ? strdup(b->name) : 0;

    
#include "modules/disksim_cachedev_param.c"


  return result;
}



⌨️ 快捷键说明

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