📄 disksim_cachemem.c
字号:
if (!(allocdesc->flags & CACHE_FLAG_LINELOCKED_ALLOCATE)) { cache->linewaiters = allocdesc; } } else { allocdesc->next = allocdesc; cache->linewaiters = allocdesc; } allocdesc->flags |= CACHE_FLAG_LINELOCKED_ALLOCATE;}static cache_atom *cache_get_replace_startpoint (struct cache_mem *cache, int set){ cache_atom *line = cache->map[set].lru[0]; if (line) { if (cache->replacepolicy == CACHE_REPLACE_RANDOM) { int choice = cache->map[set].numactive[0] * DISKSIM_drand48(); int i; for (i=0; i<choice; i++) { line = line->lru_prev; } } else if (cache->replacepolicy == CACHE_REPLACE_LIFO) { line = line->lru_prev; } else if ((cache->replacepolicy != CACHE_REPLACE_FIFO) && (cache->replacepolicy != CACHE_REPLACE_SLRU)) { fprintf(stderr, "Unknown replacement policy at cache_get_replace_startpoint: %d\n", cache->replacepolicy); exit(1); } } return(line);}/* Add identifier to lockstruct only if not already present */static void cache_add_to_lockstruct (struct cachelockw **head, void *identifier){ struct cachelockw *tmp = *head; int start = FALSE; int i; if (tmp == NULL) { tmp = (struct cachelockw *) getfromextraq(); memset((char *)tmp, 0, sizeof(struct cachelockw)); /* bzero ((char *)tmp, sizeof(struct cachelockw)); */ tmp->entry[0] = identifier; *head = tmp; } else { while (tmp->next) { for (i=0; i<CACHE_LOCKSPERSTRUCT; i++) { if (tmp->entry[i] == identifier) { return; } } tmp = tmp->next; } for (i=0; i<CACHE_LOCKSPERSTRUCT; i++) { if (tmp->entry[i] == identifier) { return; } else if (tmp->entry[i]) { start = TRUE; } else if (start) { tmp->entry[i] = identifier; return; } } tmp->next = (struct cachelockw *) getfromextraq(); tmp = tmp->next; memset ((char *)tmp, 0, sizeof(struct cachelockw)); /* bzero ((char *)tmp, sizeof(struct cachelockw)); */ tmp->entry[0] = identifier; }}/* Does anyone have a write lock on the atom?? */static int cache_atom_iswritelocked (struct cache_mem *cache, cache_atom *target){ while (target->lbn % cache->lockgran) { target = target->line_prev; } return(target->writelock != NULL);}/* Does anyone have any lock on the atom?? */static int cache_atom_islocked (struct cache_mem *cache, cache_atom *target){ while (target->lbn % cache->lockgran) { target = target->line_prev; } return(target->readlocks || target->writelock);}#if 0/* should change this code so that newly enabled "I-streams" do not *//* necessarily preempt the "I-stream" that freed the lock... */static void cache_give_lock_to_waiter (struct cache_mem *cache, cache_atom *target, struct cache_mem_event *rwdesc){ switch (rwdesc->type) { case CACHE_EVENT_READ: cache_read_continue(cache, rwdesc); break; case CACHE_EVENT_WRITE: cache_write_continue(cache, rwdesc); break; default: fprintf(stderr, "Unknown type at cache_give_lock_to_waiter: %d\n", rwdesc->type); exit(1); }}#endifstatic void cache_lock_free (struct cache_mem *cache, cache_atom *target){ cache_lockwaiters *tmp; int writelocked = FALSE; /* Can't give away a line that is writelock'd */ ASSERT(!target->writelock); if ((tmp = target->lockwaiters)) { int i = 0; while ((tmp) && (!writelocked) && (!target->writelock)) { struct cache_mem_event *waiter = NULL; if (tmp->entry[i]) { writelocked = (cache->sharedreadlocks == 0) || tmp->entry[i]->locktype; if ((!writelocked) || (target->readlocks == NULL)) { waiter = tmp->entry[i]; tmp->entry[i] = NULL; } } i++; if (i == CACHE_LOCKSPERSTRUCT) { target->lockwaiters = tmp->next; addtoextraq((event *) tmp); tmp = target->lockwaiters; i = 0; } if (waiter) { (*cache->wakeupfunc)(cache->wakeupparam, (struct cacheevent *)waiter); } } } else if (cache->linewaiters) { int linesize = max(cache->linesize, 1); struct cache_mem_event *allocdesc; while (target->lbn % linesize) { target = target->line_prev; } while (target) { if ((target->writelock) || (target->readlocks)) { return; } target = target->line_next; } allocdesc = cache->linewaiters->next; if (allocdesc->next == allocdesc) { cache->linewaiters = NULL; } else { cache->linewaiters->next = allocdesc->next; } allocdesc->next = NULL; // fprintf (outputfile, "allocation continuing: line finally freed\n"); (*cache->wakeupfunc)(cache->wakeupparam, (struct cacheevent *)allocdesc); }}/* gransize is assumed to be a factor of linesize */static int cache_get_write_lock (struct cache_mem *cache, cache_atom *target, struct cache_mem_event *rwdesc){ //fprintf (outputfile, "Entered cache_get_write_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran); while (target->lbn % cache->lockgran) { target = target->line_prev; } // fprintf (outputfile, "doing cache_get_write_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran); if (target->writelock == rwdesc->req) { return(cache->lockgran); } else if ((target->writelock) || (target->readlocks)) { rwdesc->locktype = 1; cache_add_to_lockstruct(&target->lockwaiters, rwdesc); return(0); } else { target->writelock = rwdesc->req; return(cache->lockgran); }}static int cache_free_write_lock (struct cache_mem *cache, cache_atom *target, ioreq_event *owner){ // fprintf (outputfile, "Entered cache_free_write_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran); while (target->lbn % cache->lockgran) { target = target->line_prev; } // fprintf (outputfile, "doing cache_free_write_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran); if (owner == target->writelock) { target->writelock = NULL; cache_lock_free(cache, target); return(cache->lockgran); } else { return(0); }}static int cache_get_read_lock (struct cache_mem *cache, cache_atom *target, struct cache_mem_event *rwdesc){ // fprintf (outputfile, "Entered cache_get_read_lock: target %p, lbn %d, lockgran %d\n", target, target->lbn, cache->lockgran); if (!cache->sharedreadlocks) { return(cache_get_write_lock(cache, target, rwdesc)); } while (target->lbn % cache->lockgran) { target = target->line_prev; } // 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 (struct cache_mem *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 (struct cache_mem *cache, int start, int end, cache_atom *startatom, struct cache_mem_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 (struct cache_mem *cache, int start, int end, cache_atom *startatom, struct cache_mem_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 (struct cache_mem *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 (struct cache_mem *cache, cache_atom *dirtyline, struct cache_mem_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)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -