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 + -
显示快捷键?