📄 disksim_cachedev.c
字号:
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 + -