📄 disksim_diskctlr.c
字号:
} seg->state = BUFFER_WRITING; if(nextdiskreq->inblkno < (nextioreq->blkno + nextioreq->bcount)) { *initiate_seek = TRUE; } else { *immediate_release = TRUE; } } if(ok_to_check_bus && (currdisk->extradisc_diskreq != nextdiskreq)) { disk_check_bus(currdisk,nextdiskreq); }} /* Attempt to start hda activity. * 1. If effectivehda already set, do nothing. * 2. If currdiskreq is NULL, attempt to find the appropriate next * request from the queue. */static void disk_check_hda(disk *currdisk, diskreq *currdiskreq, int ok_to_check_bus){ segment *seg; diskreq *nextdiskreq = 0; ioreq_event *nextioreq = 0; int initiate_seek = FALSE; int immediate_release = FALSE; double delay = 0.0; double mintime = 0.0; if(disk_printhack && (simtime >= disk_printhacktime)) { fprintf (outputfile, "%12.6f %8p Entering disk_check_hda" " for disk %d\n", simtime, currdiskreq,currdisk->devno); fflush(outputfile); } if(currdisk->const_acctime) { return; } // 1. If effectivehda already set, do nothing. if(currdisk->effectivehda) { return; } else { // try to get an effectivehda disk_get_effectivehda(currdisk, currdiskreq); if(!currdisk->effectivehda) { return; } } nextdiskreq = currdisk->effectivehda; // oops. the above code doesn't guarantee that seg is valid! assert(nextdiskreq->seg != 0); seg = nextdiskreq->seg; if(nextdiskreq->ioreqlist) { disk_check_hda_pending(currdisk, nextioreq, nextdiskreq, seg, ok_to_check_bus, &mintime, &immediate_release, &initiate_seek); } else { // there aren't any requests so we're only prefetching seg->state = BUFFER_READING; if(seg->endblkno < seg->maxreadaheadblkno) { if(seg->access->type != NULL_EVENT) { /* * if((seg->access->blkno != seg->endblkno) && * (seg->access->blkno != (seg->endblkno + 1)) && * (seg->access->blkno != currdisk->firstblkontrack)) { * fprintf(stderr, "non-NULL seg->access->type with * incorrect seg->access->blkno found for pure read * segment in disk_check_hda\n"); exit(1); } */ } else { seg->access->blkno = seg->endblkno; } seg->access->flags = READ | BUFFER_BACKGROUND; currdisk->immed = currdisk->immedread; if(seg->access->type == NULL_EVENT) { initiate_seek = TRUE; } } else { immediate_release = TRUE; } } // pure prefetch case if(disk_printhack && (simtime >= disk_printhacktime)) { fprintf (outputfile, " " "initiate_seek = %d, immediate_release = %d\n", initiate_seek, immediate_release); fflush(outputfile); } if(initiate_seek) { if(nextdiskreq->overhead_done > simtime) { delay += nextdiskreq->overhead_done - simtime; } if(disk_seek_stoptime > simtime) { delay += disk_seek_stoptime - simtime; } if(!disk_initiate_seek(currdisk, seg, seg->access, TRUE, delay, mintime)) { disk_release_hda(currdisk, nextdiskreq); } } else if(immediate_release) { disk_release_hda(currdisk, nextdiskreq); } if(!immediate_release && (seg->state == BUFFER_READING) && (seg->access->flags & BUFFER_BACKGROUND)) { disk_check_prefetch_swap(currdisk); }} // static void disk_check_hda()/* prematurely stop a prefetch */static void disk_buffer_stop_access (disk *currdisk){ diskreq* effective = currdisk->effectivehda; segment* seg; if(disk_printhack && (simtime >= disk_printhacktime)) { fprintf (outputfile, "%12.6f %8p Entering disk_buffer_stop_access\n", simtime, effective); fflush(outputfile); } ddbg_assert2(effective != 0, "disk has NULL effectivehda"); ddbg_assert(effective == currdisk->currenthda); seg = effective->seg; ddbg_assert((seg->access->flags & BUFFER_BACKGROUND) && (seg->access->flags & READ)); if(seg->access->type != NULL_EVENT) { int rv = removefromintq((event *)seg->access); ddbg_assert3(rv != FALSE, ("Non-null seg->access does not appear on the intq %d\n", seg->access->type)); seg->access->type = NULL_EVENT; } seg->state = ((!(effective->flags & COMPLETION_RECEIVED) || currdisk->enablecache || seg->diskreqlist->seg_next) ? BUFFER_CLEAN : BUFFER_EMPTY); if(effective->flags & COMPLETION_RECEIVED) { ddbg_assert2(effective->ioreqlist == 0, "Pure prefetch with non-NULL ioreqlist detected"); disk_buffer_remove_from_seg(effective); addtoextraq((event *) effective); if(seg->diskreqlist) { disk_find_new_seg_owner(currdisk,seg); } } currdisk->effectivehda = currdisk->currenthda = NULL;}/* attempt to take over control of the hda from an ongoing prefetch */static int disk_buffer_attempt_access_swap(disk *currdisk, diskreq *currdiskreq){ diskreq *effective = currdisk->effectivehda; ioreq_event *currioreq; segment *seg; if(disk_printhack && (simtime >= disk_printhacktime)) { fprintf (outputfile, "%12.6f %8p Entering disk_buffer_attempt_access_swap\n", simtime, currdiskreq); fprintf (outputfile, " trying to swap %8p\n", effective); fflush(outputfile); } ddbg_assert2(effective != 0, "disk has NULL effectivehda"); seg = effective->seg; ddbg_assert(seg->access->flags & READ); ddbg_assert(currdiskreq->ioreqlist != NULL); /* Since "free" reads are not allowed to prefetch currently, we don't really need the first clause. But, better safe than sorry... */ if((effective == currdisk->currenthda) && (seg->access->flags & BUFFER_BACKGROUND) && (!swap_forward_only || !effective->ioreqlist || (effective->ioreqlist->blkno < currdiskreq->ioreqlist->blkno))) { if(effective->flags & COMPLETION_RECEIVED) { ddbg_assert(effective->ioreqlist == NULL); disk_buffer_remove_from_seg(effective); addtoextraq((event *) effective); } else { ddbg_assert(effective->ioreqlist != NULL); currioreq = currdiskreq->ioreqlist; ddbg_assert(currioreq != NULL); while (currioreq->next) { currioreq = currioreq->next; } seg->access->flags = currioreq->flags; seg->minreadaheadblkno = max(seg->minreadaheadblkno, min((currioreq->blkno + currioreq->bcount + currdisk->minreadahead), currdisk->model->dm_sectors)); seg->maxreadaheadblkno = max(seg->maxreadaheadblkno, min(disk_buffer_get_max_readahead(currdisk,seg,currioreq), currdisk->model->dm_sectors)); if((seg->endblkno >= (currioreq->blkno + currioreq->bcount)) && (seg->endblkno < seg->maxreadaheadblkno)) { seg->access->flags |= BUFFER_BACKGROUND; } } currdisk->effectivehda = currdisk->currenthda = NULL; if(disk_printhack && (simtime >= disk_printhacktime)) { fprintf (outputfile, " Swap successful\n"); fflush(outputfile); } return(TRUE); } if(disk_printhack && (simtime >= disk_printhacktime)) { fprintf (outputfile, " Swap unsuccessful\n"); fflush(outputfile); } return(FALSE);}/* setseg indicates that currdiskreq->seg has not been permanently * "set", and should be nullified if the hda cannot be obtained or * set if it is obtained */static void disk_activate_read(disk *currdisk, diskreq *currdiskreq, int setseg, int ok_to_check_bus){ ioreq_event *currioreq; if(disk_printhack && (simtime >= disk_printhacktime)) { fprintf (outputfile, "%12.6f %8p Entering disk_activate_read\n", simtime, currdiskreq); fprintf (outputfile, " setseg = %d\n", setseg); fflush(outputfile); } /* use specified access time instead of simulating mechanical activity */ if(currdisk->const_acctime) { if(!currdisk->currenthda) { currdisk->currenthda = currdisk->effectivehda = currdisk->currentbus = currdiskreq; currdiskreq->overhead_done = simtime + currdisk->acctime; currioreq = ioreq_copy(currdiskreq->ioreqlist); currioreq->ioreq_hold_diskreq = currdiskreq; currioreq->type = DEVICE_PREPARE_FOR_DATA_TRANSFER; currioreq->time = currdiskreq->overhead_done; addtointq((event *) currioreq); ioqueue_set_starttime(currdisk->queue,currdiskreq->ioreqlist); } return; } /* Is there a request being serviced right now? If so, can it be interrupted? */ if(!(currdiskreq->flags & HDA_OWNED) && currdisk->effectivehda && (currdisk->effectivehda != currdiskreq) && (currdiskreq->hittype != BUFFER_COLLISION) && (!currdiskreq->seg || (currdiskreq->seg->recyclereq == currdiskreq) || (currdiskreq->seg->state != BUFFER_DIRTY)) && disk_buffer_stopable_access(currdisk,currdiskreq)) { if((currdiskreq->seg != currdisk->effectivehda->seg) || (currdiskreq->hittype == BUFFER_NOMATCH)) { disk_buffer_stop_access(currdisk); } else { disk_buffer_attempt_access_swap(currdisk,currdiskreq); } } /* If we have a segment then try to own it */ if(currdiskreq->seg && setseg) { if(currdisk->effectivehda) { if(currdiskreq->seg->recyclereq == currdiskreq) { /* I don't think the following code ever gets used... */ fprintf(stderr,"GOT HERE! SURPRISE, SURPRISE!\n"); currdiskreq->seg->recyclereq = NULL; } currdiskreq->seg = NULL; currdiskreq->hittype = BUFFER_NOMATCH; } else { disk_buffer_set_segment(currdisk,currdiskreq); } } /* if we have a segment but don't own it, try to own it */ if(currdiskreq->seg && !(currdiskreq->flags & SEG_OWNED)) { disk_buffer_attempt_seg_ownership(currdisk,currdiskreq); } if(!(currdiskreq->flags & HDA_OWNED) && (currdiskreq->hittype != BUFFER_COLLISION)) { disk_check_hda(currdisk,currdiskreq,ok_to_check_bus); } if(!(currdiskreq->flags & HDA_OWNED) && (currdisk->currentbus == currdiskreq)) { currioreq = currdiskreq->ioreqlist; while (currioreq) { ioqueue_set_starttime(currdisk->queue,currioreq); currioreq = currioreq->next; } }}/* setseg indicates that currdiskreq->seg has not been permanently * "set", and should be nullified if the hda cannot be obtained or set * if it is obtained */static void disk_activate_write(disk *currdisk, diskreq *currdiskreq, int setseg, int ok_to_check_bus){ ioreq_event *currioreq; if(disk_printhack && (simtime >= disk_printhacktime)) { fprintf (outputfile, "%12.6f %8p Entering disk_activate_write\n", simtime, currdiskreq); fprintf (outputfile, " setseg = %d\n", setseg); fflush(outputfile); } if(!currdisk->currenthda && (currdisk->const_acctime)) { currdisk->currenthda = currdisk->effectivehda = currdisk->currentbus = currdiskreq; currdiskreq->overhead_done = simtime + currdisk->acctime; currioreq = ioreq_copy(currdiskreq->ioreqlist); currioreq->ioreq_hold_diskreq = currdiskreq; currioreq->type = DEVICE_PREPARE_FOR_DATA_TRANSFER; currioreq->time = currdiskreq->overhead_done; addtointq((event *) currioreq); ioqueue_set_starttime(currdisk->queue,currdiskreq->ioreqlist); return; } if(!(currdiskreq->flags & HDA_OWNED) && currdisk->effectivehda && (currdisk->effectivehda != currdiskreq) && disk_buffer_stopable_access(currdisk,currdiskreq)) { if((currdiskreq->seg != currdisk->effectivehda->seg) || (currdiskreq->hittype != BUFFER_APPEND)) { disk_buffer_stop_access(currdisk); } } if(currdiskreq->seg && setseg) { if(currdisk->effectivehda) { if(currdiskreq->seg->recyclereq == currdiskreq) { /* I don't think the following code ever gets used... */ fprintf(stderr,"GOT HERE! SURPRISE, SURPRISE, SURPRISE!\n"); currdiskreq->seg->recyclereq = NULL; } currdiskreq->seg = NULL; currdiskreq->hittype = BUFFER_NOMATCH; } else { disk_buffer_set_segment(currdisk,currdiskreq); } } if(currdiskreq->seg && !(currdiskreq->flags & SEG_OWNED)) { disk_buffer_attempt_seg_ownership(currdisk,currdiskreq); } if(!(currdiskreq->flags & HDA_OWNED) && (currdiskreq->hittype != BUFFER_COLLISION)) { disk_check_hda(currdisk,currdiskreq,ok_to_check_bus); } if(!(currdiskreq->flags & HDA_OWNED) && (currdisk->currentbus == currdiskreq)) { currioreq = currdiskreq->ioreqlist; while (currioreq) { ioqueue_set_starttime(currdisk->queue,currioreq); currioreq = currioreq->next; } }}static void disk_read_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -