static void simpledisk_completion_done (ioreq_event *curr) { simpledisk_t *currdisk = getsimpledisk (curr->devno); // fprintf (outputfile, "Entering simpledisk_completion for disk %d: %12.6f\n", currdisk->devno, simtime); addtoextraq((event *) curr); if (currdisk->busowned != -1) { bus_ownership_release(currdisk->busowned); currdisk->busowned = -1; } /* check for and start next queued request, if any */ curr = ioqueue_get_next_request(currdisk->queue); if (curr != NULL) { ASSERT (currdisk->media_busy == FALSE); if (curr->flags & READ) { currdisk->media_busy = TRUE; stat_update (&currdisk->stat.acctimestats, currdisk->acctime); curr->time = simtime + currdisk->acctime; curr->type = DEVICE_ACCESS_COMPLETE; addtointq ((event *)curr); } else { curr->type = IO_INTERRUPT_ARRIVE; curr->cause = RECONNECT; simpledisk_send_event_up_path (curr, currdisk->bus_transaction_latency); currdisk->reconnect_reason = IO_INTERRUPT_ARRIVE; } } }
void iodriver_trace_request_start (int iodriverno, ioreq_event *curr) { ioreq_event *tmp; device *currdev = &iodrivers[iodriverno]->devices[(curr->devno)]; double tdiff = simtime - currdev->lastevent; if (currdev->flag == 1) { stat_update(&initiatenextstats, tdiff); } else if (currdev->flag == 2) { stat_update(&emptyqueuestats, tdiff); } currdev->flag = 0; tmp = ioqueue_get_specific_request(currdev->queue, curr); addtoextraq((event *) curr); ASSERT(tmp != NULL); schedule_disk_access(iodrivers[iodriverno], tmp); tmp->time = simtime; tmp->type = IO_ACCESS_ARRIVE; tmp->slotno = 0; if (tmp->time == simtime) { iodriver_schedule(iodriverno, tmp); } else { addtointq((event *) tmp); } }
static void controller_smart_host_data_transfer_complete (controller *currctlr, ioreq_event *curr) { /* DMA to/from host complete */ if (curr->flags & READ) { currctlr->cache->cache_free_block_clean(currctlr->cache, curr); controller_smart_request_complete(currctlr, curr); } else { /* cache will call "done" function if request doesn't block */ currctlr->cache->cache_free_block_dirty(currctlr->cache, curr, &disksim->donefunc_ctlrsmart_write, currctlr); } if (currctlr->hostwaiters) { curr = currctlr->hostwaiters->next; if (curr->next == curr) { currctlr->hostwaiters = NULL; } else { currctlr->hostwaiters->next = curr->next; } curr->next = NULL; /* Time for DMA */ curr->time = simtime + ((double) curr->bcount * currctlr->blktranstime); addtointq((event *) curr); } else { currctlr->hosttransfer = FALSE; } }
static void controller_smart_host_data_transfer (void *donefuncparam, ioreq_event *curr) { controller *currctlr = donefuncparam; /* DMA data to/from host */ curr->type = CONTROLLER_DATA_TRANSFER_COMPLETE; curr->tempint2 = currctlr->ctlno; curr->tempptr1 = NULL; if (currctlr->hosttransfer) { if (currctlr->hostwaiters) { curr->next = currctlr->hostwaiters->next; currctlr->hostwaiters->next = curr; } else { curr->next = curr; } currctlr->hostwaiters = curr; return; } /* Time for DMA */ curr->time = simtime + ((double) curr->bcount * currctlr->blktranstime); currctlr->hosttransfer = TRUE; addtointq((event *) curr); }
static void simpledisk_bustransfer_complete (ioreq_event *curr) { simpledisk_t *currdisk; // fprintf (outputfile, "Entering simpledisk_bustransfer_complete for disk %d: %12.6f\n", curr->devno, simtime); currdisk = getsimpledisk (curr->devno); if (curr->flags & READ) { simpledisk_request_complete (curr); } else { simpledisk_t *currdisk = getsimpledisk (curr->devno); if (currdisk->neverdisconnect == FALSE) { /* disconnect from bus */ ioreq_event *tmp = ioreq_copy (curr); tmp->type = IO_INTERRUPT_ARRIVE; tmp->cause = DISCONNECT; simpledisk_send_event_up_path (tmp, currdisk->bus_transaction_latency); } /* do media access */ currdisk->media_busy = TRUE; stat_update (&currdisk->stat.acctimestats, currdisk->acctime); curr->time = simtime + currdisk->acctime; curr->type = DEVICE_ACCESS_COMPLETE; addtointq ((event *) curr); } }
static void controller_53c700_data_transfer_complete (controller *currctlr, ioreq_event *curr) { ioreq_event *tmp; #ifdef DEBUG_CTLRDUMB fprintf (outputfile, "*** %f: controller_53c700_data_transfer_complete - devno %d, blkno %d\n, bcount %d, flags 0x%x\n", simtime, curr->devno, curr->blkno, curr->bcount, curr->flags ); fflush(outputfile ); #endif tmp = (ioreq_event *) curr->tempptr1; tmp->bcount -= curr->bcount; addtoextraq((event *) curr); if (tmp->bcount < 0) { fprintf(stderr, "Transfered more than requested at controller_data_transfer_done\n"); exit(1); } else if (tmp->bcount == 0) { if (tmp->next) { tmp->next->prev = tmp->prev; } if (tmp->prev) { tmp->prev->next = tmp->next; } else { currctlr->datatransfers = tmp->next; } tmp->time = simtime; addtointq((event *) tmp); } else { fprintf(stderr, "Haven't required less than all out transfer at controller_data_transfer_done\n"); exit(1); } }
static void controller_smart_disk_data_transfer (controller *currctlr, ioreq_event *curr) { ioreq_event *tmp = (ioreq_event *) getfromextraq(); /* fprintf (outputfile, "%f: controller_smart_disk_data_transfer: devno %d, bcount %d\n", simtime, curr->devno, curr->bcount); */ curr->time = max(device_get_blktranstime(curr), currctlr->blktranstime); tmp->time = simtime + ((double) curr->bcount * curr->time); tmp->type = CONTROLLER_DATA_TRANSFER_COMPLETE; tmp->devno = curr->devno; tmp->blkno = curr->blkno; tmp->bcount = curr->bcount; tmp->tempint2 = currctlr->ctlno; tmp->tempptr1 = curr; /* want to use the tempptr1 value for something else! */ curr->tempptr1 = tmp; curr->next = currctlr->datatransfers; curr->prev = NULL; if (curr->next) { curr->next->prev = curr; } currctlr->datatransfers = curr; addtointq((event *) tmp); }
void ssd_event_arrive (ioreq_event *curr) { ssd_t *currdisk; // fprintf (outputfile, "Entered ssd_event_arrive: time %f (simtime %f)\n", curr->time, simtime); // fprintf (outputfile, " - devno %d, blkno %d, type %d, cause %d, read = %d\n", curr->devno, curr->blkno, curr->type, curr->cause, curr->flags & READ); currdisk = getssd (curr->devno); switch (curr->type) { case IO_ACCESS_ARRIVE: curr->time = simtime + currdisk->overhead; curr->type = DEVICE_OVERHEAD_COMPLETE; addtointq((event *) curr); break; case DEVICE_OVERHEAD_COMPLETE: ssd_request_arrive(curr); break; case DEVICE_ACCESS_COMPLETE: ssd_access_complete (curr); break; case DEVICE_DATA_TRANSFER_COMPLETE: ssd_bustransfer_complete(curr); break; case IO_INTERRUPT_COMPLETE: ssd_interrupt_complete(curr); break; case IO_QLEN_MAXCHECK: /* Used only at initialization time to set up queue stuff */ curr->tempint1 = -1; curr->tempint2 = ssd_get_maxoutstanding(curr->devno); curr->bcount = 0; break; case SSD_CLEAN_GANG: ssd_clean_gang_complete(curr); break; case SSD_CLEAN_ELEMENT: ssd_clean_element_complete(curr); break; default: fprintf(stderr, "Unrecognized event type at ssd_event_arrive\n"); exit(1); } // fprintf (outputfile, "Exiting ssd_event_arrive\n"); }
static void simpledisk_request_arrive (ioreq_event *curr) { ioreq_event *intrp; simpledisk_t *currdisk; #ifdef DEBUG_SIMPLEDISK fprintf (outputfile, "*** %f: simpledisk_request_arrive - devno %d, blkno %d, bcount %d, flags 0x%x\n", simtime, curr->devno, curr->blkno, curr->bcount, curr->flags ); #endif currdisk = getsimpledisk(curr->devno); /* verify that request is valid. */ if ((curr->blkno < 0) || (curr->bcount <= 0) || ((curr->blkno + curr->bcount) > currdisk->numblocks)) { fprintf(stderr, "Invalid set of blocks requested from simpledisk - blkno %lld, bcount %d, numblocks %lld\n", curr->blkno, curr->bcount, currdisk->numblocks); exit(1); } /* create a new request, set it up for initial interrupt */ currdisk->busowned = simpledisk_get_busno(curr); if (ioqueue_get_reqoutstanding (currdisk->queue) == 0) { ioqueue_add_new_request(currdisk->queue, curr); curr = ioqueue_get_next_request (currdisk->queue); intrp = curr; /* initiate media access if request is a READ */ if (curr->flags & READ) { ioreq_event *tmp = ioreq_copy (curr); currdisk->media_busy = TRUE; stat_update (&currdisk->stat.acctimestats, currdisk->acctime); tmp->time = simtime + currdisk->acctime; tmp->type = DEVICE_ACCESS_COMPLETE; addtointq ((event *)tmp); } /* if not disconnecting, then the READY_TO_TRANSFER is like a RECONNECT */ currdisk->reconnect_reason = IO_INTERRUPT_ARRIVE; if (curr->flags & READ) { intrp->cause = (currdisk->neverdisconnect) ? READY_TO_TRANSFER : DISCONNECT; } else { intrp->cause = READY_TO_TRANSFER; } } else { intrp = ioreq_copy(curr); ioqueue_add_new_request(currdisk->queue, curr); intrp->cause = DISCONNECT; } intrp->type = IO_INTERRUPT_ARRIVE; simpledisk_send_event_up_path(intrp, currdisk->bus_transaction_latency); }
static void iodriver_check_c700_based_status (iodriver *curriodriver, int devno, int cause, int type, LBA_t blkno) { ctlr *ctl; ioreq_event *tmp; ctl = curriodriver->devices[devno].ctl; if ((ctl == NULL) || (!(ctl->flags & DRIVER_C700))) { return; } if (type == IO_INTERRUPT_ARRIVE) { if (ctl->pendio != NULL) { tmp = ctl->pendio->next; if ((tmp->devno == devno) && (tmp->blkno == blkno)) { if (ctl->pendio == tmp) { ctl->pendio = NULL; } else { ctl->pendio->next = tmp->next; } addtoextraq((event *) tmp); } } switch (cause) { case COMPLETION: case DISCONNECT: case RECONNECT: case READY_TO_TRANSFER: ctl->flags |= DRIVER_CTLR_BUSY; break; default: fprintf(stderr, "Unknown interrupt cause at iodriver_check_c700_based_status - cause %d\n", cause); exit(1); } } else { switch (cause) { case COMPLETION: case DISCONNECT: ctl->flags &= ~DRIVER_CTLR_BUSY; if (ctl->pendio != NULL) { tmp = ioreq_copy(ctl->pendio->next); tmp->time = simtime; addtointq((event *) tmp); } break; case RECONNECT: case READY_TO_TRANSFER: ctl->flags |= DRIVER_CTLR_BUSY; break; default: fprintf(stderr, "Unknown interrupt cause at iodriver_check_c700_based_status - cause %d\n", cause); exit(1); } } }
static int ssd_invoke_gang_cleaning(int gang_num, ssd_t *s) { int i; int elem_num; double max_cost = 0; double elem_clean_cost; int cleaning_invoked = 0; gang_metadata *g = &s->gang_meta[gang_num]; // all the elements in the gang must be free ASSERT(g->busy == FALSE); ASSERT(g->cleaning == FALSE); // invoke cleaning on all the elements for (i = 0; i < s->params.elements_per_gang; i ++) { elem_num = gang_num * s->params.elements_per_gang + i; elem_clean_cost = _ssd_invoke_element_cleaning(elem_num, s); // stat s->elements[elem_num].stat.tot_clean_time += max_cost; if (max_cost < elem_clean_cost) { max_cost = elem_clean_cost; } } // cleaning was invoked on all the elements. we can start // the next operation on this gang only after the cleaning // gets over on all the elements. if (max_cost > 0) { ioreq_event *tmp; g->busy = 1; g->cleaning = 1; cleaning_invoked = 1; // we use the 'blkno' field to store the gang number tmp = (ioreq_event *)getfromextraq(); tmp->devno = s->devno; tmp->time = simtime + max_cost; tmp->blkno = gang_num; tmp->ssd_gang_num = gang_num; tmp->type = SSD_CLEAN_GANG; tmp->flags = SSD_CLEAN_GANG; tmp->busno = -1; tmp->bcount = -1; stat_update (&s->stat.acctimestats, max_cost); addtointq ((event *)tmp); } return cleaning_invoked; }
void io_catch_stray_events (ioreq_event *curr) { switch (curr->type) { case DEVICE_DATA_TRANSFER_COMPLETE: curr->time = device_get_blktranstime(curr); curr->time = simtime + (curr->time * (double) curr->bcount); addtointq((event *) curr); break; default: fprintf(stderr, "Unknown event type at io_catch_stray_events\n"); exit(1); } }
void simpledisk_event_arrive (ioreq_event *curr) { simpledisk_t *currdisk; #ifdef DEBUG_SIMPLEDISK fprintf (outputfile, "*** %f: simpledisk_event_arrive - devno %d, blkno %d, bcount %d, flags 0x%x, cause %d\n", simtime, curr->devno, curr->blkno, curr->bcount, curr->flags, curr->cause ); // fprintf (outputfile, "Entered simpledisk_event_arrive: time %f (simtime %f)\n", curr->time, simtime); // fprintf (outputfile, " - devno %d, blkno %d, type %d, cause %d, read = %d\n", curr->devno, curr->blkno, curr->type, curr->cause, curr->flags & READ); #endif currdisk = getsimpledisk (curr->devno); switch (curr->type) { case IO_ACCESS_ARRIVE: curr->time = simtime + currdisk->overhead; curr->type = DEVICE_OVERHEAD_COMPLETE; addtointq((event *) curr); break; case DEVICE_OVERHEAD_COMPLETE: simpledisk_request_arrive(curr); break; case DEVICE_ACCESS_COMPLETE: simpledisk_access_complete (curr); break; case DEVICE_DATA_TRANSFER_COMPLETE: simpledisk_bustransfer_complete(curr); break; case IO_INTERRUPT_COMPLETE: simpledisk_interrupt_complete(curr); break; case IO_QLEN_MAXCHECK: /* Used only at initialization time to set up queue stuff */ curr->tempint1 = -1; curr->tempint2 = simpledisk_get_maxoutstanding(curr->devno); curr->bcount = 0; break; default: fprintf(stderr, "Unrecognized event type at simpledisk_event_arrive\n"); exit(1); } // fprintf (outputfile, "Exiting simpledisk_event_arrive\n"); }
void iodriver_interrupt_arrive (int iodriverno, intr_event *intrp) { event *tmp; ioreq_event *infoptr = (ioreq_event *) intrp->infoptr; #ifdef DEBUG_IODRIVER fprintf (outputfile, "%f, iodriver_interrupt_arrive - cause %d, blkno %lld\n", simtime, infoptr->cause, infoptr->blkno); #endif if ((iodrivers[iodriverno]->consttime == 0.0) || (iodrivers[iodriverno]->consttime == IODRIVER_TRACED_QUEUE_TIMES)) { intrp->time = iodriver_get_time_to_handle_interrupt(iodrivers[iodriverno], infoptr->cause, (infoptr->flags & READ)); iodriver_check_c700_based_status(iodrivers[iodriverno], infoptr->devno, infoptr->cause, IO_INTERRUPT_ARRIVE, infoptr->blkno); } else { intrp->time = 0.0; } if (iodrivers[iodriverno]->type == STANDALONE) { intrp->time += simtime; intrp->type = IO_INTERRUPT_COMPLETE; addtointq((event *) intrp); } else { tmp = getfromextraq(); intrp->time /= (double) 5; tmp->time = intrp->time; tmp->type = INTEND_EVENT; tmp->next = NULL; ((intr_event *)tmp)->vector = IO_INTERRUPT; intrp->eventlist = tmp; if (infoptr->cause == COMPLETION) { tmp = getfromextraq(); tmp->time = 0.0; tmp->type = IO_ACCESS_COMPLETE; tmp->next = intrp->eventlist; ((ioreq_event *)tmp)->tempptr1 = intrp; intrp->eventlist = tmp; } tmp = getfromextraq(); tmp->time = iodriver_get_time_to_respond_to_device(iodrivers[iodriverno], infoptr->cause, intrp->time); tmp->type = IO_RESPOND_TO_DEVICE; tmp->next = intrp->eventlist; ((ioreq_event *)tmp)->tempptr1 = intrp; intrp->eventlist = tmp; } }
static int ssd_invoke_element_cleaning(int elem_num, ssd_t *s) { double max_cost = 0; int cleaning_invoked = 0; ssd_element *elem = &s->elements[elem_num]; // element must be free ASSERT(elem->media_busy == FALSE); max_cost = _ssd_invoke_element_cleaning(elem_num, s); // cleaning was invoked on this element. we can start // the next operation on this elem only after the cleaning // gets over. if (max_cost > 0) { ioreq_event *tmp; elem->media_busy = 1; cleaning_invoked = 1; // we use the 'blkno' field to store the element number tmp = (ioreq_event *)getfromextraq(); tmp->devno = s->devno; tmp->time = simtime + max_cost; tmp->blkno = elem_num; tmp->ssd_elem_num = elem_num; tmp->type = SSD_CLEAN_ELEMENT; tmp->flags = SSD_CLEAN_ELEMENT; tmp->busno = -1; tmp->bcount = -1; stat_update (&s->stat.acctimestats, max_cost); addtointq ((event *)tmp); // stat elem->stat.tot_clean_time += max_cost; elem->power_stat.acc_time += max_cost; ssd_dpower(s, max_cost); } return cleaning_invoked; }
void ssd_invoke_element_refresh_fcfs(int elem_num,listnode *blocks_to_refresh,ssd_t *currdisk) { int block_len = 0; int i; double cost = 0; block_len = ll_get_size(blocks_to_refresh); block_metadata *currblock = 0; listnode *currnode = 0; //for all blocks in every element. for(i=0;i<block_len;i++) { currnode = ll_get_nth_node(blocks_to_refresh,i); currblock = (block_metadata*)currnode->data; ASSERT(currblock->elem_num == elem_num); cost+= ssd_refresh_block(currblock,currdisk); //sum every cost, because we are not applying refresh in batches } ssd_element *elem = &currdisk->elements[elem_num]; if (cost > 0) { ioreq_event *tmp; elem->media_busy = TRUE; // we use the 'blkno' field to store the element number tmp = (ioreq_event *)getfromextraq(); tmp->devno = currdisk->devno; tmp->time = simtime + cost; tmp->blkno = elem_num; tmp->ssd_elem_num = elem_num; tmp->type = SSD_REFRESH_ELEMENT; tmp->flags = SSD_REFRESH_ELEMENT; tmp->busno = -1; tmp->bcount = -1; stat_update (&currdisk->stat.acctimestats, cost); addtointq ((event *)tmp); // stat elem->stat.tot_refresh_time += cost; } }
static void controller_smart_disk_data_transfer_complete (controller *currctlr, ioreq_event *curr) { ioreq_event *tmp = (ioreq_event *) curr->tempptr1; tmp->bcount -= curr->bcount; addtoextraq((event *) curr); ASSERT(tmp->bcount >= 0); if (tmp->bcount == 0) { if (tmp->next) { tmp->next->prev = tmp->prev; } if (tmp->prev) { tmp->prev->next = tmp->next; } else { currctlr->datatransfers = tmp->next; } tmp->time = simtime; addtointq((event *) tmp); } else { fprintf(stderr, "Haven't required less than all out transfer at controller_smart_disk_data_transfer_complete\n"); exit(1); } }
static void controller_53c700_data_transfer (controller *currctlr, ioreq_event *curr) { ioreq_event *tmp; #ifdef DEBUG_CTLRDUMB fprintf (outputfile, "*** %f: controller_53c700_data_transfer - devno %d, blkno %d\n, bcount %d, flags 0x%x\n", simtime, curr->devno, curr->blkno, curr->bcount, curr->flags ); fflush(outputfile ); /* fprintf (outputfile, "Entered controller_53c700_data_transfer - ctlno %d, devno %d, blkno %d, bcount %d\n", ctlno, curr->devno, curr->blkno, curr->bcount); */ #endif if (curr->type == DEVICE_DATA_TRANSFER_COMPLETE) { curr->time = max(device_get_blktranstime(curr), currctlr->blktranstime); } else if (curr->type == CONTROLLER_DATA_TRANSFER_COMPLETE) { fprintf(stderr, "Not yet equiped to handle controller to controller transfers\n"); exit(1); } else { fprintf(stderr, "Illegal event type at controller_53c700_data_transfer\n"); exit(1); } curr->next = currctlr->datatransfers; curr->prev = NULL; if (curr->next) { curr->next->prev = curr; } currctlr->datatransfers = curr; tmp = (ioreq_event *) getfromextraq(); tmp->time = simtime + (curr->time * (double) curr->bcount); tmp->type = CONTROLLER_DATA_TRANSFER_COMPLETE; tmp->blkno = curr->blkno; tmp->bcount = curr->bcount; tmp->tempint2 = currctlr->ctlno; tmp->tempptr1 = curr; curr->buf = tmp; addtointq((event *) tmp); }
void iodriver_access_complete (int iodriverno, intr_event *intrp) { int i; int numreqs; ioreq_event *tmp; ioreq_event *del; ioreq_event *req; int devno; int skip = 0; ctlr *ctl = NULL; time_t now; if (iodrivers[iodriverno]->type == STANDALONE) { req = ioreq_copy((ioreq_event *) intrp->infoptr); } else { req = (ioreq_event *) intrp->infoptr; } #ifdef DEBUG_IODRIVER fprintf (outputfile, "*** %f: iodriver_access_complete - devno %d, blkno %d, bcount %d, read %d\n", simtime, req->devno, req->blkno, req->bcount, (req->flags & READ)); fflush(outputfile); #endif time( & now ); disksim_exectrace( "Request completion: simtime %f, devno %d, blkno %lld, bcount %d, flags %X, time %s\n", simtime, req->devno, req->blkno, req->bcount, req->flags, asctime( localtime(& now)) ); if (iodrivers[iodriverno]->devices[(req->devno)].queuectlr != -1) { int ctlrno = iodrivers[iodriverno]->devices[(req->devno)].queuectlr; ctl = &iodrivers[iodriverno]->ctlrs[ctlrno]; tmp = ctl->oversized; numreqs = 1; while (((numreqs) || (tmp != ctl->oversized)) && (tmp) && (tmp->next) && ((tmp->next->devno != req->devno) || (tmp->next->opid != req->opid) || (req->blkno < tmp->next->blkno) || (req->blkno >= (tmp->next->blkno + tmp->next->bcount)))) { // fprintf (outputfile, "oversized request in list: opid %d, blkno %lld, bcount %d\n", tmp->opid, tmp->blkno, tmp->bcount); numreqs = 0; tmp = tmp->next; } if ((tmp) && (tmp->next->devno == req->devno) && (tmp->next->opid == req->opid) && (req->blkno >= tmp->next->blkno) && (req->blkno < (tmp->next->blkno + tmp->next->bcount))) { fprintf (outputfile, "%f, part of oversized request completed: opid %d, blkno %lld, bcount %d, maxreqsize %d\n", simtime, req->opid, req->blkno, req->bcount, ctl->maxreqsize); if ((req->blkno + ctl->maxreqsize) < (tmp->next->blkno + tmp->next->bcount)) { fprintf (outputfile, "more to go\n"); req->blkno += ctl->maxreqsize; req->bcount = min(ctl->maxreqsize, (tmp->next->blkno + tmp->next->bcount - req->blkno)); goto schedule_next; } else { fprintf (outputfile, "done for real\n"); addtoextraq((event *) req); req = tmp->next; tmp->next = tmp->next->next; if (ctl->oversized == req) { ctl->oversized = (req != req->next) ? req->next : NULL; } req->next = NULL; } } } devno = req->devno; req = ioqueue_physical_access_done(iodrivers[iodriverno]->devices[devno].queue, req); if (ctl) { ctl->numoutstanding--; } // special case for validate: if (disksim->traceformat == VALIDATE) { tmp = (ioreq_event *) getfromextraq(); io_validate_do_stats1(); tmp = iotrace_validate_get_ioreq_event(disksim->iotracefile, tmp); if (tmp) { io_validate_do_stats2(tmp); tmp->type = IO_REQUEST_ARRIVE; addtointq((event *) tmp); disksim_exectrace("Request issue: simtime %f, devno %d, blkno %lld, time %f\n", simtime, tmp->devno, tmp->blkno, tmp->time); } else { disksim_simstop(); } } else if (disksim->closedios) { tmp = (ioreq_event *) io_get_next_external_event(disksim->iotracefile); if (tmp) { io_using_external_event ((event *)tmp); tmp->time = simtime + disksim->closedthinktime; tmp->type = IO_REQUEST_ARRIVE; addtointq((event *) tmp); } else { disksim_simstop(); } } while (req) { tmp = req; req = req->next; tmp->next = NULL; update_iodriver_statistics(); if ((numreqs = logorg_mapcomplete(sysorgs, numsysorgs, tmp)) == COMPLETE) { /* update up overall I/O system stats for this completed request */ ioreq_event *temp = ioqueue_get_specific_request (OVERALLQUEUE, tmp); ioreq_event *temp2 = ioqueue_physical_access_done (OVERALLQUEUE, temp); ASSERT (temp2 != NULL); addtoextraq((event *)temp); temp = NULL; if (iodrivers[iodriverno]->type != STANDALONE) { iodriver_add_to_intrp_eventlist(intrp, io_done_notify(tmp), iodrivers[iodriverno]->scale); } else { io_done_notify (tmp); } } else if (numreqs > 0) { for (i = 0; i < numreqs; i++) { del = tmp->next; tmp->next = del->next; del->next = NULL; del->type = IO_REQUEST_ARRIVE; del->flags |= MAPPED; skip |= (del->devno == devno); if (iodrivers[iodriverno]->type == STANDALONE) { del->time += simtime + 0.0000000001; /* to affect an ordering */ addtointq((event *) del); } else { iodriver_add_to_intrp_eventlist(intrp, (event *) del, iodrivers[iodriverno]->scale); } } } addtoextraq((event *) tmp); } if ((iodrivers[iodriverno]->consttime == IODRIVER_TRACED_QUEUE_TIMES) || (iodrivers[iodriverno]->consttime == IODRIVER_TRACED_BOTH_TIMES)) { if (ioqueue_get_number_in_queue(iodrivers[iodriverno]->devices[devno].queue) > 0) { iodrivers[iodriverno]->devices[devno].flag = 1; iodrivers[iodriverno]->devices[devno].lastevent = simtime; } return; } if (skip) { return; } // fprintf(outputfile, "iodriver_access_complete:: calling ioqueue_get_next_request\n"); req = ioqueue_get_next_request(iodrivers[iodriverno]->devices[devno].queue); // fprintf (outputfile, "next scheduled: req %p, req->blkno %d, req->flags %x\n", req, ((req) ? req->blkno : 0), ((req) ? req->flags : 0)); schedule_next: if (req) { req->type = IO_ACCESS_ARRIVE; req->next = NULL; if (ctl) { ctl->numoutstanding++; } if (iodrivers[iodriverno]->type == STANDALONE) { req->time = simtime; addtointq((event *) req); } else { iodriver_add_to_intrp_eventlist(intrp, (event *) req, iodrivers[iodriverno]->scale); } } }
static void ssd_activate_elem(ssd_t *currdisk, int elem_num) { ioreq_event *req; ssd_req **read_reqs; ssd_req **write_reqs; int i; int read_total = 0; int write_total = 0; double schtime = 0; int max_reqs; int tot_reqs_issued; double max_time_taken = 0; ssd_element *elem = &currdisk->elements[elem_num]; // if the media is busy, we can't do anything, so return if (elem->media_busy == TRUE) { return; } ASSERT(ioqueue_get_reqoutstanding(elem->queue) == 0); // we can invoke cleaning in the background whether there // is request waiting or not if (currdisk->params.cleaning_in_background) { // if cleaning was invoked, wait until // it is over ... if (ssd_invoke_element_cleaning(elem_num, currdisk)) { return; } } ASSERT(elem->metadata.reqs_waiting == ioqueue_get_number_in_queue(elem->queue)); if (elem->metadata.reqs_waiting > 0) { // invoke cleaning in foreground when there are requests waiting if (!currdisk->params.cleaning_in_background) { // if cleaning was invoked, wait until // it is over ... if (ssd_invoke_element_cleaning(elem_num, currdisk)) { return; } } // how many reqs can we issue at once if (currdisk->params.copy_back == SSD_COPY_BACK_DISABLE) { max_reqs = 1; } else { if (currdisk->params.num_parunits == 1) { max_reqs = 1; } else { max_reqs = MAX_REQS_ELEM_QUEUE; } } // ideally, we should issue one req per plane, overlapping them all. // in order to simplify the overlapping strategy, let's issue // requests of the same type together. read_reqs = (ssd_req **) malloc(max_reqs * sizeof(ssd_req *)); write_reqs = (ssd_req **) malloc(max_reqs * sizeof(ssd_req *)); // collect the requests while ((req = ioqueue_get_next_request(elem->queue)) != NULL) { int found = 0; elem->metadata.reqs_waiting --; // see if we already have the same request in the list. // this usually doesn't happen -- but on synthetic traces // this weird case can occur. if (req->flags & READ) { found = ssd_already_present(read_reqs, read_total, req); } else { found = ssd_already_present(write_reqs, write_total, req); } if (!found) { // this is a valid request ssd_req *r = malloc(sizeof(ssd_req)); r->blk = req->blkno; r->count = req->bcount; r->is_read = req->flags & READ; r->org_req = req; r->plane_num = -1; // we don't know to which plane this req will be directed at if (req->flags & READ) { read_reqs[read_total] = r; read_total ++; } else { write_reqs[write_total] = r; write_total ++; } // if we have more reqs than we can handle, quit if ((read_total >= max_reqs) || (write_total >= max_reqs)) { break; } } else { // throw this request -- it doesn't make sense stat_update (&currdisk->stat.acctimestats, 0); req->time = simtime; req->ssd_elem_num = elem_num; req->type = DEVICE_ACCESS_COMPLETE; addtointq ((event *)req); } } if (read_total > 0) { // first issue all the read requests (it doesn't matter what we // issue first). i chose read because reads are mostly synchronous. // find the time taken to serve these requests. ssd_compute_access_time(currdisk, elem_num, read_reqs, read_total); // add an event for each request completion for (i = 0; i < read_total; i ++) { elem->media_busy = TRUE; // find the maximum time taken by a request if (schtime < read_reqs[i]->schtime) { schtime = read_reqs[i]->schtime; } stat_update (&currdisk->stat.acctimestats, read_reqs[i]->acctime); read_reqs[i]->org_req->time = simtime + read_reqs[i]->schtime; read_reqs[i]->org_req->ssd_elem_num = elem_num; read_reqs[i]->org_req->type = DEVICE_ACCESS_COMPLETE; //printf("R: blk %d elem %d acctime %f simtime %f\n", read_reqs[i]->blk, // elem_num, read_reqs[i]->acctime, read_reqs[i]->org_req->time); addtointq ((event *)read_reqs[i]->org_req); free(read_reqs[i]); } } free(read_reqs); max_time_taken = schtime; if (write_total > 0) { // next issue the write requests ssd_compute_access_time(currdisk, elem_num, write_reqs, write_total); // add an event for each request completion. // note that we can issue the writes only after all the reads above are // over. so, include the maximum read time when creating the event. for (i = 0; i < write_total; i ++) { elem->media_busy = TRUE; stat_update (&currdisk->stat.acctimestats, write_reqs[i]->acctime); write_reqs[i]->org_req->time = simtime + schtime + write_reqs[i]->schtime; //printf("blk %d elem %d acc time %f\n", write_reqs[i]->blk, elem_num, write_reqs[i]->acctime); if (max_time_taken < (schtime+write_reqs[i]->schtime)) { max_time_taken = (schtime+write_reqs[i]->schtime); } write_reqs[i]->org_req->ssd_elem_num = elem_num; write_reqs[i]->org_req->type = DEVICE_ACCESS_COMPLETE; //printf("W: blk %d elem %d acctime %f simtime %f\n", write_reqs[i]->blk, // elem_num, write_reqs[i]->acctime, write_reqs[i]->org_req->time); addtointq ((event *)write_reqs[i]->org_req); free(write_reqs[i]); } } free(write_reqs); // statistics tot_reqs_issued = read_total + write_total; ASSERT(tot_reqs_issued > 0); currdisk->elements[elem_num].stat.tot_reqs_issued += tot_reqs_issued; currdisk->elements[elem_num].stat.tot_time_taken += max_time_taken; } }
event * iodriver_request (int iodriverno, ioreq_event *curr) { ioreq_event *temp = NULL; ioreq_event *ret = NULL; ioreq_event *retlist = NULL; int numreqs; /* printf ("Entered iodriver_request - simtime %f, devno %d, blkno %lld, cause %d\n", simtime, curr->devno, curr->blkno, curr->cause); fprintf (outputfile, "Entered iodriver_request - simtime %f, devno %d, blkno %lld, cause %d\n", simtime, curr->devno, curr->blkno, curr->cause); fprintf (stderr, "Entered iodriver_request - simtime %f, devno %d, blkno %lld, cause %d\n", simtime, curr->devno, curr->blkno, curr->cause); */ if (NULL != OUTIOS) { fprintf(OUTIOS, "%.6f,%d,%lld,%d,%x,%d,%p\n", simtime, curr->devno, curr->blkno, curr->bcount, curr->flags, OVERALLQUEUE->base.listlen + 1, curr ); fflush( OUTIOS ); } #if 0 fprintf (stderr, "Entered iodriver_request - simtime %f, devno %d, blkno %lld, cause %d\n", simtime, curr->devno, curr->blkno, curr->cause); #endif /* add to the overall queue to start tracking */ ret = ioreq_copy (curr); ioqueue_add_new_request (OVERALLQUEUE, ret); ret = NULL; disksim->totalreqs++; if ((disksim->checkpoint_iocnt > 0) && ((disksim->totalreqs % disksim->checkpoint_iocnt) == 0)) { disksim_register_checkpoint (simtime); } if (disksim->totalreqs == disksim->warmup_iocnt) { warmuptime = simtime; resetstats(); } numreqs = logorg_maprequest(sysorgs, numsysorgs, curr); temp = curr->next; for (; numreqs>0; numreqs--) { /* Request list size must match numreqs */ ASSERT(curr != NULL); curr->next = NULL; if ((iodrivers[iodriverno]->consttime == IODRIVER_TRACED_QUEUE_TIMES) || (iodrivers[iodriverno]->consttime == IODRIVER_TRACED_BOTH_TIMES)) { ret = ioreq_copy(curr); ret->time = simtime + (double) ret->tempint1 / (double) 1000; ret->type = IO_TRACE_REQUEST_START; addtointq((event *) ret); ret = NULL; if ((curr->slotno == 1) && (ioqueue_get_number_in_queue(iodrivers[iodriverno]->devices[(curr->devno)].queue) == 0)) { iodrivers[(iodriverno)]->devices[(curr->devno)].flag = 2; iodrivers[(iodriverno)]->devices[(curr->devno)].lastevent = simtime; } } ret = handle_new_request(iodrivers[iodriverno], curr); if ((ret) && (iodrivers[iodriverno]->type == STANDALONE) && (ret->time == 0.0)) { ret->type = IO_ACCESS_ARRIVE; ret->time = simtime; iodriver_schedule(iodriverno, ret); } else if (ret) { ret->type = IO_ACCESS_ARRIVE; ret->next = retlist; ret->prev = NULL; retlist = ret; } curr = temp; temp = (temp) ? temp->next : NULL; } if (iodrivers[iodriverno]->type == STANDALONE) { while (retlist) { ret = retlist; retlist = ret->next; ret->next = NULL; ret->time += simtime; addtointq((event *) ret); } } /* fprintf (outputfile, "leaving iodriver_request: retlist %p\n", retlist); */ return((event *) retlist); }
/* * collects 1 request from each chip in the gang */ static void ssd_collect_req_in_gang (ssd_t *s, int gang_num, ssd_req ***rd_q, ssd_req ***wr_q, int *rd_total, int *wr_total) { int i; int start; gang_metadata *g; g = &s->gang_meta[gang_num]; // start from the first element of the gang start = gang_num * s->params.elements_per_gang; i = start; *rd_total = 0; *wr_total = 0; do { ssd_element *elem; ioreq_event *req; int tot_rd_reqs; int tot_wr_reqs; int j; elem = &s->elements[i]; ASSERT(ioqueue_get_reqoutstanding(elem->queue) == 0); j = i % s->params.elements_per_gang; // collect the requests tot_rd_reqs = 0; tot_wr_reqs = 0; if ((req = ioqueue_get_next_request(elem->queue)) != NULL) { int found; if (req->flags & READ) { found = ssd_already_present(rd_q[j], tot_rd_reqs, req); } else { found = ssd_already_present(wr_q[j], tot_wr_reqs, req); } if (!found) { // this is a valid request ssd_req *r = malloc(sizeof(ssd_req)); r->blk = req->blkno; r->count = req->bcount; r->is_read = req->flags & READ; r->org_req = req; r->plane_num = -1; // we don't know to which plane this req will be directed at if (req->flags & READ) { rd_q[j][tot_rd_reqs] = r; tot_rd_reqs ++; } else { wr_q[j][tot_wr_reqs] = r; tot_wr_reqs ++; } } else { // throw this request -- it doesn't make sense stat_update (&s->stat.acctimestats, 0); req->time = simtime; req->ssd_elem_num = i; req->ssd_gang_num = gang_num; req->type = DEVICE_ACCESS_COMPLETE; addtointq ((event *)req); } ASSERT((tot_rd_reqs < MAX_REQS) && (tot_wr_reqs < MAX_REQS)) } *rd_total = *rd_total + tot_rd_reqs; *wr_total = *wr_total + tot_wr_reqs; // go to the next element i = ssd_next_elem_in_gang(s, gang_num, i); } while (i != start);
static void ssd_media_access_request_element (ioreq_event *curr) { ssd_t *currdisk = getssd(curr->devno); int blkno = curr->blkno; int count = curr->bcount; //added by tiel int i = 0; double max_threshold = currdisk->params.nelements * currdisk->params.page_size; /* **** CAREFUL ... HIJACKING tempint2 and tempptr2 fields here **** */ curr->tempint2 = count; //while (count != 0) { while (count > 0) { // find the element (package) to direct the request int elem_num = ssd_choose_element(currdisk->user_params, blkno); ssd_element *elem = &currdisk->elements[elem_num]; // create a new sub-request for the element ioreq_event *tmp = (ioreq_event *)getfromextraq(); tmp->devno = curr->devno; tmp->busno = curr->busno; tmp->flags = curr->flags; tmp->blkno = blkno; tmp->bcount = ssd_choose_aligned_count(currdisk->params.page_size, blkno, count); /*if(curr->bcount > max_threshold) tmp->tempint1 = 1;*/ //ASSERT(tmp->bcount == currdisk->params.page_size); tmp->tempptr2 = curr; blkno += tmp->bcount; count -= tmp->bcount; elem->metadata.reqs_waiting ++; // add the request to the corresponding element's queue ioqueue_add_new_request(elem->queue, (ioreq_event *)tmp); // added by tiel // activate request create simtime, type, elem_num { int ch_num; double wtime, ctime; ioreq_event *temp = (ioreq_event *)getfromextraq(); temp->type = SSD_ACTIVATE_ELEM; //Insert Channel/Way delay //Channel Number = Chip number % Number of Channel ch_num = elem_num % currdisk->params.nchannel; wtime = currdisk->CH[ch_num].arrival_time + ssd_data_transfer_cost(currdisk,currdisk->params.page_size); ctime = simtime + (i * currdisk->params.channel_switch_delay); if(currdisk->params.nchannel == currdisk->params.nelements){ temp->time = ctime; currdisk->CH[ch_num].ccount++; }else if(simtime > wtime || currdisk->CH[ch_num].flag == -1){ //channel data setting currdisk->CH[ch_num].arrival_time = ctime; currdisk->CH[ch_num].flag = curr->flags; temp->time = ctime; currdisk->CH[ch_num].ccount++; }else if(currdisk->CH[ch_num].flag ==READ){ if(wtime > ctime){ if(curr->flags == READ){ temp->time = wtime; }else{ temp->time = wtime + currdisk->params.page_read_latency; } currdisk->CH[ch_num].wcount++; }else{ temp->time = ctime; currdisk->CH[ch_num].ccount++; } currdisk->CH[ch_num].arrival_time = temp->time; currdisk->CH[ch_num].flag = curr->flags; }else if(currdisk->CH[ch_num].flag == WRITE){ if(wtime > ctime){ temp->time = wtime; currdisk->CH[ch_num].wcount++; }else{ temp->time = ctime; currdisk->CH[ch_num].ccount++; } currdisk->CH[ch_num].arrival_time = temp->time; currdisk->CH[ch_num].flag = curr->flags; } temp->ssd_elem_num = elem_num; addtointq ((event *)temp); i ++; } } }