예제 #1
0
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;
      }
   }
}
예제 #2
0
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);
   }
}
예제 #3
0
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;
   }
}
예제 #4
0
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);
}
예제 #5
0
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);
   }
}
예제 #6
0
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);
    }
}
예제 #7
0
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);
}
예제 #8
0
파일: ssd.c 프로젝트: vishnu89/gijoe
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");
}
예제 #9
0
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);
}
예제 #10
0
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);
      }
   }
}
예제 #11
0
파일: ssd_gang.c 프로젝트: vishnu89/gijoe
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;
}
예제 #12
0
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);
   }
}
예제 #13
0
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");
}
예제 #14
0
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;
   }
}
예제 #15
0
파일: ssd.c 프로젝트: ESOS-Lab/EnergySim
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;
}
예제 #16
0
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;
  }
}
예제 #17
0
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);
   }
}
예제 #18
0
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);
}
예제 #19
0
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);
      }
   }
}
예제 #20
0
파일: ssd.c 프로젝트: vishnu89/gijoe
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;
    }
}
예제 #21
0
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);
}
예제 #22
0
파일: ssd_gang.c 프로젝트: vishnu89/gijoe
/*
 * 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);
예제 #23
0
파일: ssd.c 프로젝트: ESOS-Lab/EnergySim
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 ++;
	   }
   }
}