disksim_cachedev.c

来自「disksim是一个非常优秀的磁盘仿真工具」· C语言 代码 · 共 803 行 · 第 1/2 页

C
803
字号
   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          */static int cachedev_free_block_dirty (struct cache_if *c, 			   ioreq_event *req, 			   void (**donefunc)(void *, ioreq_event *), 			   void *doneparam){  struct cache_dev *cache = (struct cache_dev *)c;   ioreq_event *flushreq;   struct cache_dev_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 (struct cache_if *c){  return(0);}static void *cachedev_disk_access_complete (struct cache_if *c,			       ioreq_event *curr){  struct cache_dev *cache = (struct cache_dev *)c;   struct cache_dev_event *rwdesc = curr->buf;   struct cache_dev_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);   switch(rwdesc->type) {   case 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);      break;   case 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;      }      break;   case CACHE_EVENT_POPULATE_ONLY:     cachedev_setbits (cache->validmap, curr);     cachedev_remove_ongoing_request (cache, rwdesc);      addtoextraq ((event *) rwdesc);      cache->bufferspace -= curr->bcount;      break;         case CACHE_EVENT_POPULATE_ALSO:     cachedev_setbits (cache->validmap, curr);     rwdesc->type = CACHE_EVENT_READ;     break;   case CACHE_EVENT_FLUSH:      cachedev_clearbits (cache->dirtymap, curr);      cachedev_remove_ongoing_request (cache, rwdesc);      addtoextraq ((event *) rwdesc);      cache->bufferspace -= curr->bcount;      break;   case 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;     } break;   case 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;     break;   default:     ddbg_assert2(0, "Unknown cachedev event type");     break;   }   addtoextraq((event *) curr);   /* returned cacheevent will get forwarded to cachedev_wakeup_continue... */   return(tmp);}static void cachedev_wakeup_complete (struct cache_if *c, 			  void *d) // really struct cache_dev_event{  struct cache_dev_event *desc = (struct cache_dev_event *)d;  struct cache_dev *cache = (struct cache_dev *)c;  ASSERT (0);  // ???#if 0   switch(desc->type) {   case CACHE_EVENT_READ:      cache_read_continue(cache, desc);      break;   case CACHE_EVENT_WRITE:     cache_write_continue(cache, desc);     break;   case CACHE_EVENT_FLUSH:      (*desc->donefunc)(desc->doneparam, desc->req);      addtoextraq((event *) desc);      break;   default:     ddbg_assert2(0, "Unknown cachedev event type");     break;   }#endif}static void cachedev_resetstats (struct cache_if *c){  struct cache_dev *cache = (struct cache_dev *)c;  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(void){  disksim->donefunc_cachedev_empty = cachedev_empty_donefunc;  disksim->idlework_cachedev = cachedev_idlework_callback;  disksim->timerfunc_cachedev = cachedev_periodic_callback;}static void cachedev_initialize (struct cache_if *c, 		     void (**issuefunc)(void *,ioreq_event *), 		     void *issueparam, 		     struct ioq * (**queuefind)(void *,int), 		     void *queuefindparam, 		     void (**wakeupfunc)(void *, struct cacheevent *), 		     void *wakeupparam, 		     int numdevs){  struct cache_dev *cache = (struct cache_dev *)c;  StaticAssert (sizeof(struct cache_dev_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(c);   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));      ddbg_assert(0);   }}static void cachedev_cleanstats (struct cache_if *cache){}static void cachedev_printstats (struct cache_if *c, char *prefix){  struct cache_dev *cache = (struct cache_dev *)c;   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);}static struct cache_if * cachedev_copy (struct cache_if *c){  struct cache_dev *cache = (struct cache_dev *)c;  struct cache_dev *new = (struct cache_dev *) DISKSIM_malloc(sizeof(struct cache_dev));  ASSERT(new != NULL);  bzero (new, sizeof(struct cache_dev));    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 (struct cache_if *)new;}static struct cache_if disksim_cache_dev = {  cachedev_setcallbacks,  cachedev_initialize,  cachedev_resetstats,  cachedev_printstats,  cachedev_cleanstats,  cachedev_copy,  cachedev_get_block,  cachedev_free_block_clean,  cachedev_free_block_dirty,  cachedev_disk_access_complete,  cachedev_wakeup_complete,  cachedev_sync,  cachedev_get_maxreqsize};struct cache_if *disksim_cachedev_loadparams(struct lp_block *b){  int c;  struct cache_dev *result;  result = calloc(1, sizeof(struct cache_dev));  result->hdr = disksim_cache_dev;   result->name = b->name ? strdup(b->name) : 0;      //#include "modules/disksim_cachedev_param.c"  lp_loadparams(result, b, &disksim_cachedev_mod);  return (struct cache_if *)result;}

⌨️ 快捷键说明

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