static void cachedev_idlework_callback (void *idleworkparam, int idledevno)
{

   struct cache_dev *cache = (struct cache_dev *)idleworkparam;
   struct cache_dev_event *flushdesc;
   ioreq_event *flushreq;
   int blkno, bcount;
   struct ioq *queue;

   ASSERT (idledevno == cache->real_devno);

#ifdef DEBUG_CACHEDEV
   fprintf(outputfile, "*** %f: Entered cachedev::cachedev_idlework_callback\n", simtime );
   fflush(outputfile);
#endif

   queue = (*cache->queuefind)(cache->queuefindparam, cache->real_devno);
   if (ioqueue_get_number_in_queue (queue) != 0) {
      return;
   }

   queue = (*cache->queuefind)(cache->queuefindparam, cache->cache_devno);
   if (ioqueue_get_number_in_queue (queue) != 0) {
      return;
   }

   if (cachedev_find_dirty_cache_blocks (cache, &blkno, &bcount) == 0) {
      return;
   }

   /* Just assume that bufferspace is available */
   cache->bufferspace += bcount;
   if (cache->bufferspace > cache->stat.maxbufferspace) {
      cache->stat.maxbufferspace = cache->bufferspace;
   }

   flushdesc = (struct cache_dev_event *) getfromextraq();
   flushdesc->type = CACHE_EVENT_IDLEFLUSH_READ;
   flushreq = (ioreq_event *) getfromextraq();
   flushreq->buf = flushdesc;
   flushreq->devno = cache->cache_devno;
   flushreq->blkno = blkno;
   flushreq->bcount = bcount;
   flushreq->type = IO_ACCESS_ARRIVE;
   flushreq->flags = READ;
   (*cache->issuefunc)(cache->issueparam, flushreq);
   cache->stat.destagereads++;
   cache->stat.destagereadblocks += bcount;
}
Exemple #2
0
static void ssd_media_access_request_element (ioreq_event *curr)
{
   ssd_t *currdisk = getssd(curr->devno);
   int blkno = curr->blkno;
   int count = curr->bcount;

   /* **** CAREFUL ... HIJACKING tempint2 and tempptr2 fields here **** */
   curr->tempint2 = count;
   while (count != 0) {

       // find the element (package) to direct the request
       int elem_num = currdisk->timing_t->choose_element(currdisk->timing_t, 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);
       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);
       ssd_activate_elem(currdisk, elem_num);
   }
}
Exemple #3
0
ioreq_event * ioreq_copy (ioreq_event *old)
{
   ioreq_event *new_event = (ioreq_event *) getfromextraq();
   memmove ((char *)new_event, (char *)old, sizeof(ioreq_event));
   /* bcopy ((char *)old, (char *)new_event, sizeof (ioreq_event)); */
   return(new_event);
}
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);
}
static void DISKSIM_GLOBAL_STATISTIC_WARM_UP_TIME_loader(int result, double d) { 
if (! ((d >= 0))) { // foo 
 } 
 disksim->warmup_event = (timer_event *) getfromextraq();
 disksim->warmup_event->type = TIMER_EXPIRED;
 disksim->warmup_event->time = d * (double) 1000.0;
 disksim->warmup_event->func = &disksim->timerfunc_disksim;

}
Exemple #6
0
static void logorg_parity_read_old_sync (logorg *currlogorg, ioreq_event *curr, int numreqs)
{
   int i, j;
   depends *depend;
   depends *tmpdep;
   ioreq_event *temp;
   int devno = 1;

   depend = (depends *) getfromextraq();
   depend->blkno = curr->blkno;
   depend->devno = curr->devno;
   depend->deps[0] = ioreq_copy(curr);
   depend->deps[0]->opid = numreqs;
   curr->prev = (ioreq_event *) depend;
   depend->numdeps = numreqs;
   temp = curr->next;
   for (i=1; i<numreqs; i++) {
      if (devno == 0) {
	 depend->cont = (depends *) getfromextraq();
	 depend = depend->cont;
      }
      depend->deps[devno] = ioreq_copy(temp);
      depend->deps[devno]->opid = numreqs;
      devno = logorg_modulus_update(1, devno, 10);
      temp = temp->next;
   }
   temp = curr->next;
   curr->flags |= READ;
   for (i=1; i<numreqs; i++) {
      depend = (depends *) ioreq_copy(curr->prev);
      depend->next = (depends *) curr->prev;
      curr->prev = (ioreq_event *) depend;
      depend->blkno = temp->blkno;
      depend->devno = temp->devno;
      tmpdep = depend->cont;
      for (j=0; j<(numreqs/10); j++) {
	 depend->cont = (depends *) ioreq_copy((ioreq_event *) tmpdep);
	 tmpdep = tmpdep->cont;
	 depend = depend->cont;
      }
      temp->flags |= READ;
      temp = temp->next;
   }
}
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;
   }
}
Exemple #8
0
int logorg_parity_disk (logorg *currlogorg, ioreq_event *curr, int numreqs)
{
   depends *depend;

   if (curr->flags & READ) {
      return(numreqs);
   }
   if ((currlogorg->maptype == STRIPED) && (currlogorg->stripeunit == 0)) {
      curr->next = ioreq_copy(curr);
      curr->next->devno = currlogorg->numdisks;
      return(numreqs+1);
   }
   if (numreqs != 1) {
      fprintf(stderr, "Too many reqs at logorg_parity_disk - %d\n", numreqs);
      exit(1);
   }
   depend = (depends *) getfromextraq();
   depend->blkno = curr->blkno;
   depend->devno = curr->devno;
   depend->numdeps = 2;
   depend->deps[0] = ioreq_copy(curr);
   depend->deps[1] = ioreq_copy(curr);
   depend->deps[0]->opid = 2;
   depend->deps[0]->devno = currlogorg->numdisks;
   depend->next = (depends *) getfromextraq();
   depend->next->next = NULL;
   depend->next->blkno = curr->blkno;
   depend->next->devno = currlogorg->numdisks;
   depend->next->deps[0] = depend->deps[0];
   depend->next->deps[1] = depend->deps[1];
   if (currlogorg->writesync == TRUE) {
      depend->deps[1]->opid = 2;
      depend->next->numdeps = 2;
   } else {
      depend->deps[1]->opid = 1;
      depend->next->numdeps = 1;
   }
   curr->flags |= READ;
   curr->next = ioreq_copy(curr);
   curr->next->devno = currlogorg->numdisks;
   curr->prev = (ioreq_event *) depend;
   return(4);
}
Exemple #9
0
event * io_get_next_external_event (FILE *iotracefile)
{
   ioreq_event *temp;

   ASSERT(io_extq == NULL);

#ifdef DEBUG_IOSIM
   fprintf (outputfile, "Entering: io_get_next_external_event\n");
#endif

   temp = (ioreq_event *) getfromextraq();

   switch (disksim->traceformat) {
      case VALIDATE: io_validate_do_stats1();
		     break;
      case HPL: io_hpl_do_stats1();
                break;
   }

   temp = iotrace_get_ioreq_event(iotracefile, disksim->traceformat, temp);
   if (temp) {
      switch (disksim->traceformat) {
         case VALIDATE: io_validate_do_stats2 (temp);
		        break;
      }
      temp->type = IO_REQUEST_ARRIVE;
      if (constintarrtime > 0.0) {
	 temp->time = last_request_arrive + constintarrtime;
	 last_request_arrive = temp->time;
      }
      temp->time = (temp->time * ioscale) + tracebasetime;
      if ((temp->time < simtime) && (!disksim->closedios)) {
         fprintf(stderr, "Trace event appears out of time order in trace - simtime %f, time %f\n", simtime, temp->time);
	 fprintf(stderr, "ioscale %f, tracebasetime %f\n", ioscale, tracebasetime);
	 fprintf(stderr, "devno %d, blkno %lld, bcount %d, flags %d\n", temp->devno, temp->blkno, temp->bcount, temp->flags);
         exit(1);
      }
      if (tracemappings) {
         io_map_trace_request(temp);
      }
      io_extq = (event *)temp;
      io_extq_type = temp->type;

#ifdef DEBUG_IOSIM
	  fprintf( outputfile, "*** %f: Set io_extq, type %d, devno %d, blkno %lld, bcount %d, flags %d\n", simtime, temp->type, temp->devno, temp->blkno, temp->bcount, temp->flags );
#endif
   }

#ifdef DEBUG_IOSIM
   fprintf (outputfile, "Exiting: io_get_next_external_event\n");
#endif

   return ((event *)temp);
}
Exemple #10
0
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;
}
Exemple #11
0
static void get_device_maxoutstanding (iodriver *curriodriver, device * dev)
{
   ioreq_event *chk = (ioreq_event *) getfromextraq();

   chk->busno = dev->buspath.value;
   chk->slotno = dev->slotpath.value;
   chk->devno = dev->devno;
   chk->type = IO_QLEN_MAXCHECK;
   iodriver_send_event_down_path(chk);
   dev->queuectlr = chk->tempint1;
   dev->maxoutstanding = (chk->tempint1 == -1) ? chk->tempint2 : -1;
   if (chk->tempint1 != -1) {
      curriodriver->ctlrs[chk->tempint1].maxoutstanding = chk->tempint2;
      curriodriver->ctlrs[chk->tempint1].maxreqsize = chk->bcount;
   }
/*
   fprintf (outputfile, "Maxoutstanding: tempint1 %d, tempint2 %d, bcount %d\n", chk->tempint1, chk->tempint2, chk->bcount);
*/
   addtoextraq((event *) chk);
}
Exemple #12
0
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;
}
Exemple #13
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;
  }
}
Exemple #14
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);
}
Exemple #15
0
static void logorg_parity_table_read_old (logorg *currlogorg, ioreq_event *rowhead, ioreq_event **reqlist, int opid)
{
   ioreq_event *temp;
   ioreq_event *newreq;
   ioreq_event *prev = NULL;

   temp = rowhead;
   while (temp) {
      newreq = (ioreq_event *) getfromextraq();
      newreq->blkno = temp->blkno;
      newreq->devno = temp->devno;
      newreq->bcount = temp->bcount;
      newreq->flags = temp->flags | READ;
      newreq->opid = opid;
      logorg_parity_table_insert(&reqlist[newreq->devno], newreq);
      newreq->prev = prev;
      prev = newreq;
	/* only the last write (the parity update) must depend on the reads */
      if (temp->prev == NULL) {
         temp->opid = opid;
      }
      temp = temp->prev;
   }
}
Exemple #16
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);
      }
   }
}
Exemple #17
0
static void logorg_parity_table_recon (logorg *currlogorg, ioreq_event *rowhead, ioreq_event **reqlist, int stripeno, int unitno, int tableadd, int opid)
{
   ioreq_event *temp;
   ioreq_event *newreq;
   int entryno;
   int minblkno;
   int maxblkno;
   int lastentry;
   int i;
   int blkno;
   int offset;

   temp = rowhead;
   if (temp == NULL) {
      fprintf(stderr, "Can't have NULL rowhead at logorg_parity_table_recon\n");
      exit(1);
   }
   lastentry = (stripeno + 1) * currlogorg->partsperstripe + stripeno;
   while (temp->prev) {
      temp = temp->prev;
   }
   temp->opid = opid;
   minblkno = temp->blkno - currlogorg->table[lastentry].blkno - tableadd;
   maxblkno = minblkno + temp->bcount;
   entryno = stripeno * currlogorg->partsperstripe + stripeno;
   for (i = 0; i < unitno; i++) {
      newreq = (ioreq_event *) getfromextraq();
      newreq->devno = currlogorg->table[entryno].devno;
      newreq->blkno = tableadd + minblkno + currlogorg->table[entryno].blkno;
      newreq->bcount = maxblkno - minblkno;
      newreq->flags = rowhead->flags | READ;
      newreq->opid = opid;
      logorg_parity_table_insert(&reqlist[newreq->devno], newreq);
      entryno++;
   }
   temp = rowhead;
   while (temp->prev) {
      blkno = currlogorg->table[entryno].blkno;
      offset = temp->blkno - tableadd - blkno;
      if (offset > minblkno) {
         newreq = (ioreq_event *) getfromextraq();
         newreq->devno = temp->devno;
         newreq->blkno = tableadd + blkno + minblkno;
         newreq->bcount = offset - minblkno;
         newreq->flags = temp->flags | READ;
	 newreq->opid = opid;
         logorg_parity_table_insert(&reqlist[newreq->devno], newreq);
      }
      if ((offset + temp->bcount) < maxblkno) {
         newreq = (ioreq_event *) getfromextraq();
         newreq->devno = temp->devno;
         newreq->blkno = temp->blkno + temp->bcount;
         newreq->bcount = maxblkno - offset - temp->bcount;
         newreq->flags = temp->flags | READ;
	 newreq->opid = opid;
         logorg_parity_table_insert(&reqlist[newreq->devno], newreq);
      }
      entryno++;
      temp = temp->prev;
   }
   for (; entryno < lastentry; entryno++) {
      newreq = (ioreq_event *) getfromextraq();
      newreq->devno = currlogorg->table[entryno].devno;
      newreq->blkno = tableadd + minblkno + currlogorg->table[entryno].blkno;
      newreq->bcount = maxblkno - minblkno;
      newreq->flags = rowhead->flags | READ;
      newreq->opid = opid;
      logorg_parity_table_insert(&reqlist[newreq->devno], newreq);
   }
}
Exemple #18
0
static void logorg_parity_table_dodeps_sync (logorg *currlogorg, ioreq_event *curr, ioreq_event **redunlist, ioreq_event **reqlist)
{
   int i, j;
   depends *depend;
   depends *tmpdep;
   int opid = 0;
   int numdeps = 0;
   ioreq_event *temp;
   ioreq_event *deplist = NULL;
   int devno = 1;

   for (i=0; i<currlogorg->actualnumdisks; i++) {
      temp = redunlist[i];
      while (temp) {
	 temp->opid = curr->opid;
	 opid++;
	 if (temp->next == NULL) {
	    temp->next = curr->next;
	    curr->next = redunlist[i];
	    break;
	 }
	 temp = temp->next;
      }
      temp = reqlist[i];
      while (temp) {
	 numdeps++;
	 if (temp->next == NULL) {
	    temp->next = deplist;
	    deplist = reqlist[i];
	    break;
	 }
	 temp = temp->next;
      }
   }
   if (numdeps <= 0) {
      fprintf(stderr, "Can't have zero requests at logorg_parity_table_dodeps_sync\n");
      exit(1);
   }
   if (opid == 0) {
      curr->prev = NULL;
      curr->next = deplist;
      return;
   }
   depend = (depends *) getfromextraq();
   depend->blkno = curr->next->blkno;
   depend->devno = curr->next->devno;
   depend->numdeps = numdeps;
   curr->prev = (ioreq_event *) depend;
   depend->deps[0] = deplist;
   deplist->opid = opid;
   temp = deplist->next;
   for (i=1; i<numdeps; i++) {
      if (devno == 0) {
	 depend->cont = (depends *) getfromextraq();
	 depend = depend->cont;
      }
      depend->deps[devno] = temp;
      temp->opid = opid;
      devno = logorg_modulus_update(1, devno, 10);
      temp = temp->next;
   }
   temp = curr->next->next;
   for (i=1; i<opid; i++) {
      depend = (depends *) ioreq_copy(curr->prev);
      depend->next = (depends *) curr->prev;
      curr->prev = (ioreq_event *) depend;
      depend->blkno = temp->blkno;
      depend->devno = temp->devno;
      tmpdep = depend->cont;
      for (j=0; j<(numdeps/10); j++) {
	 depend->cont = (depends *) ioreq_copy((ioreq_event *) tmpdep);
	 tmpdep = tmpdep->cont;
	 depend = depend->cont;
      }
      temp = temp->next;
   }
}
Exemple #19
0
static int 
cachedev_get_block (struct cache_if *c, 
		    ioreq_event *req, 
		    void (**donefunc)(void *, ioreq_event *), 
		    void *doneparam)
{
   struct cache_dev *cache = (struct cache_dev *)c;
   struct cache_dev_event *rwdesc = (struct cache_dev_event *) getfromextraq();
   ioreq_event *fillreq;
   int devno;

#ifdef DEBUG_CACHEDEV
   fprintf (outputfile, "*** cachedev::totalreqs = %d\n", disksim->totalreqs);
   fprintf (outputfile, "*** %f: Entered cachedev::cachedev_get_block: rw %d, devno %d, blkno %d, size %d\n", simtime, (req->flags & READ), req->devno, req->blkno, req->bcount);
#endif

   if (req->devno != cache->real_devno) {
      fprintf (stderr, "cachedev_get_block trying to cache blocks for wrong device (%d should be %d)\n", req->devno, cache->real_devno);
      ASSERT(0);
      exit(1);
   }

   /* Ignore request overlap and locking issues for now.  */
   /* Also ignore buffer space limitation issues for now. */
   cache->bufferspace += req->bcount;
   if (cache->bufferspace > cache->stat.maxbufferspace) {
      cache->stat.maxbufferspace = cache->bufferspace;
   }

   rwdesc->type = (req->flags & READ) ? CACHE_EVENT_READ : CACHE_EVENT_WRITE;
   rwdesc->donefunc = donefunc;
   rwdesc->doneparam = doneparam;
   rwdesc->req = req;
   req->next = NULL;
   req->prev = NULL;
   rwdesc->flags = 0;
   cachedev_add_ongoing_request (cache, rwdesc);

   if (req->flags & READ) {
      cache->stat.reads++;
      cache->stat.readblocks += req->bcount;

      /* Send read straight to whichever device has it (preferably cachedev). */
      if (cachedev_isreadhit (cache, req)) {
         devno = cache->cache_devno;
         cache->stat.readhitsfull++;
      } else {
         devno = cache->real_devno;
         cache->stat.readmisses++;
      }
      /* For now, just assume both device's store bits at same LBNs */
      fillreq = ioreq_copy (req);
      fillreq->buf = rwdesc;
      fillreq->type = IO_ACCESS_ARRIVE;
      fillreq->devno = devno;

#ifdef DEBUG_CACHEDEV
      fprintf (outputfile, "*** %f: cachedev::fillreq (inserts into ioqueue?): devno %d, blkno %d, bcount %d, flags %x, buf %p\n", simtime, fillreq->devno, fillreq->blkno, fillreq->bcount, fillreq->flags, fillreq->buf);
#endif

      (*cache->issuefunc)(cache->issueparam, fillreq);
      return (1);

   } else {
      /* Grab buffer space and let the controller fill in data to be written. */
      /* (for now, just assume that there is buffer space available)          */

      (*donefunc)(doneparam, req);
      return (0);
   }
}
Exemple #20
0
static void logorg_parity_table_dodeps_nosync (logorg *currlogorg, ioreq_event *curr, ioreq_event **redunlist, ioreq_event **reqlist)
{
   int i;
   depends *depend;
   depends *tmpdep;
   ioreq_event *temp;
   ioreq_event *del;
   ioreq_event *tmpread;
   ioreq_event *readlist = NULL;
   ioreq_event *deplist = NULL;
   int holddep;

   for (i=0; i<currlogorg->actualnumdisks; i++) {
      temp = redunlist[i];
      while (temp) {
         depend = (depends *) getfromextraq();
         depend->blkno = temp->blkno;
         depend->devno = temp->devno;
         depend->numdeps = 0;
	 depend->next = NULL;
	 temp->prev = (ioreq_event *) depend;
	 if (temp->next == NULL) {
	    temp->next = readlist;
	    readlist = redunlist[i];
	    break;
	 }
	 temp = temp->next;
      }
      temp = reqlist[i];
      while (temp) {
	 del = temp;
	 temp = temp->next;
	 if ((redunlist[i] == NULL) && (del->opid == 0)) {
	    del->next = curr->next;
	    curr->next = del;
	 } else {
	    del->next = deplist;
	    deplist = del;
	 }
      }
   }
   if (readlist == NULL) {
      if (deplist) {
         fprintf(stderr, "Unacceptable condition in logorg_parity_table_dodeps_nosync\n");
         exit(1);
      }
      curr->prev = NULL;
      return;
   }
   temp = deplist;
   while (temp) {
      holddep = temp->opid;
      temp->opid = 0;
      tmpread = readlist;
      while (tmpread) {
	 if ((tmpread->devno == temp->devno) | (holddep & tmpread->opid)) {
            tmpdep = (depends *) tmpread->prev;
            ASSERT (tmpdep != NULL);
            if (tmpdep->numdeps > 0) {
	       for (i=0; i<((tmpdep->numdeps-1)/10); i++) {
	          tmpdep = tmpdep->cont;
	       }
	       if ((tmpdep->numdeps % 10) == 0) {
	          tmpdep->cont = (depends *) getfromextraq();
	          tmpdep = tmpdep->cont;
	       }
            }
            tmpdep->deps[(tmpdep->numdeps % 10)] = temp;
	    tmpdep->numdeps++;
            temp->opid++;
	 }
	 tmpread = tmpread->next;
      }
      temp = temp->next;
   }
   temp = readlist;
   curr->prev = NULL;
   while (temp) {
      depend = (depends *) temp->prev;
      temp->prev = NULL;
      depend->next = (depends *) curr->prev;
      curr->prev = (ioreq_event *) depend;
      if (temp->next == NULL) {
	 temp->next = curr->next;
	 curr->next = readlist;
	 break;
      }
      temp = temp->next;
   }
}
Exemple #21
0
int logorg_parity_table (logorg *currlogorg, ioreq_event *curr, int numreqs)
{
   int i;
   ioreq_event *reqs[MAXDEVICES];
   ioreq_event *redunreqs[MAXDEVICES];
   int reqcnt = 0;
   ioreq_event *lastrow = NULL;
   int stripeunit;
   ioreq_event *temp;
   ioreq_event *newreq;
   int unitno;
   int stripeno;
   int entryno;
   int blkno;
   int blksinpart;
   int reqsize;
   int partsperstripe;
   int rowcnt = 1;
   int firstrow = 0;
   int opid = 0x1;
   int blkscovered;
   tableentry *table;
   int tablestart;
   int preventryno;
/*
fprintf (outputfile, "Entered logorg_parity_table - devno %d, blkno %d, bcount %d, read %d\n", curr->devno, curr->blkno, curr->bcount, (curr->flags & READ));
*/
   if (numreqs != 1) {
      fprintf(stderr, "Multiple numreqs at logorg_parity_table is not acceptable - %d\n", numreqs);
      exit(1);
   }

   stripeunit = currlogorg->stripeunit;
   partsperstripe = currlogorg->partsperstripe;
   table = currlogorg->table;
   if (currlogorg->addrbyparts) {
      curr->blkno += curr->devno * currlogorg->blksperpart;
   }
   for (i=0; i<currlogorg->actualnumdisks; i++) {
      reqs[i] = NULL;
   }
   unitno = curr->blkno / stripeunit;
   stripeno = unitno / partsperstripe;
   tablestart = (stripeno / currlogorg->tablestripes) * currlogorg->tablesize;
   stripeno = stripeno % currlogorg->tablestripes;
   blkno = tablestart + table[(stripeno*(partsperstripe+1))].blkno;
   if (blkno == currlogorg->numfull) {
      stripeunit = currlogorg->actualblksperpart - blkno;
      curr->blkno -= blkno;
      unitno = curr->blkno / stripeunit;
   }
   blksinpart = stripeunit;
   unitno = unitno % partsperstripe;
   curr->blkno = curr->blkno % stripeunit;
   reqsize = curr->bcount;
   entryno = stripeno * partsperstripe + stripeno + unitno;
   blkno = tablestart + table[entryno].blkno;
   blksinpart -= curr->blkno;
   temp = ioreq_copy(curr);
   curr->next = temp;
   temp->blkno = blkno + curr->blkno;
   temp->devno = table[entryno].devno;
   temp->opid = 0;
   blkscovered = curr->bcount;
   curr->blkno = stripeno;
   curr->devno = unitno;
   curr->bcount = tablestart;
   reqs[temp->devno] = curr->next;
   temp->next = NULL;
   temp->prev = NULL;
   if (reqsize > blksinpart) {
      temp->bcount = blksinpart;
      blkscovered = blksinpart;
      reqsize -= blksinpart;
      unitno++;
      if (unitno == partsperstripe) {
	 if (!(curr->flags & READ)) {
	    newreq = (ioreq_event *) getfromextraq();
	    newreq->devno = table[(entryno+1)].devno;
	    newreq->blkno = table[(entryno+1)].blkno;
	    newreq->blkno += tablestart + temp->blkno - blkno;
	    newreq->bcount = blkscovered;
	    newreq->flags = curr->flags;
            newreq->opid = 0;
	    reqs[newreq->devno] = newreq;
	    newreq->next = NULL;
	    temp->prev = newreq;
	    newreq->prev = NULL;
	 }
	 blkscovered = 0;
	 unitno = 0;
	 if (firstrow == 0) {
	    firstrow = 1;
	 }
	 rowcnt = 0;
	 stripeno++;
	 temp = NULL;
	 if (stripeno == currlogorg->tablestripes) {
	    stripeno = 0;
	    tablestart += currlogorg->tablesize;
	 }
      }
      entryno = (stripeno * partsperstripe) + stripeno + unitno;
      blkno = tablestart + table[entryno].blkno;
      blksinpart = (blkno != currlogorg->numfull) ? stripeunit : currlogorg->actualblksperpart - blkno;
      while (reqsize > blksinpart) {
	 rowcnt++;
	 newreq = (ioreq_event *) getfromextraq();
         newreq->blkno = blkno;
	 newreq->devno = table[entryno].devno;
	 newreq->bcount = blksinpart;
	 blkscovered = max(blkscovered, blksinpart);
	 newreq->flags = curr->flags;
         newreq->opid = 0;
	 newreq->prev = NULL;
	 if (temp) {
	    temp->prev = newreq;
	 } else {
	    lastrow = newreq;
	 }
	 temp = newreq;
	 logorg_parity_table_insert(&reqs[temp->devno], temp);
         reqsize -= blksinpart;
         unitno++;
         if (unitno == partsperstripe) {
	    if (!(curr->flags & READ)) {
	       newreq = (ioreq_event *) getfromextraq();
	       newreq->devno = table[(entryno+1)].devno;
	       newreq->blkno = table[(entryno+1)].blkno + tablestart;
	       newreq->bcount = blkscovered;
	       newreq->flags = curr->flags;
               newreq->opid = 0;
               temp->prev = newreq;
	       newreq->prev = NULL;
	       logorg_parity_table_insert(&reqs[newreq->devno], newreq);
	    }
	    blkscovered = 0;
	    unitno = 0;
	    if (firstrow == 0) {
	       firstrow = rowcnt;
	    }
	    rowcnt = 0;
	    temp = NULL;
	    stripeno++;
	    if (stripeno == currlogorg->tablestripes) {
	       stripeno = 0;
	       tablestart += currlogorg->tablesize;
	    }
         }
         entryno = (stripeno * partsperstripe) + stripeno + unitno;
         blkno = tablestart + table[entryno].blkno;
         blksinpart = (blkno != currlogorg->numfull) ? stripeunit : currlogorg->actualblksperpart - blkno;
      }
      newreq = (ioreq_event *) getfromextraq();
      newreq->blkno = blkno;
      newreq->devno = table[entryno].devno;
      newreq->bcount = reqsize;
      rowcnt++;
      blkscovered = max(blkscovered, blksinpart);
      newreq->flags = curr->flags;
      newreq->opid = 0;
      newreq->prev = NULL;
      if (temp) {
	 temp->prev = newreq;
      } else {
	 lastrow = newreq;
      }
      temp = newreq;
      logorg_parity_table_insert(&reqs[newreq->devno], newreq);
   }
   if (curr->flags & READ) {
      curr->next = curr;
      for (i=0; i<currlogorg->actualnumdisks; i++) {
	 reqcnt += logorg_join_seqreqs(reqs[i], curr, LOGORG_PARITY_SEQGIVE);
      }
   } else {
      preventryno = entryno;
      entryno = (stripeno * partsperstripe) + stripeno + partsperstripe;
      newreq = (ioreq_event *) getfromextraq();
      newreq->devno = table[entryno].devno;
      newreq->blkno = table[entryno].blkno + temp->blkno - table[preventryno].blkno;
      newreq->bcount = (rowcnt == 1) ? temp->bcount : blkscovered;
      newreq->flags = curr->flags;
      newreq->opid = 0;
      temp->prev = newreq;
      newreq->prev = NULL;
      logorg_parity_table_insert(&reqs[newreq->devno], newreq);
      if (firstrow == 0) {
	 if ((rowcnt == 2) && ((curr->next->blkno - temp->blkno - temp->bcount) > 0)) {
	    newreq->bcount = temp->bcount;
	    newreq = (ioreq_event *) getfromextraq();
	    newreq->devno = temp->prev->devno;
	    lastrow = temp;
	    temp = curr->next;
	    newreq->blkno = table[entryno].blkno + temp->blkno - table[(preventryno-1)].blkno;
	    newreq->bcount = temp->bcount;
	    newreq->flags = curr->flags;
	    newreq->opid = 0;
	    temp->prev = newreq;
	    newreq->prev = NULL;
            logorg_parity_table_insert(&reqs[newreq->devno], newreq);
	    firstrow = 1;
	    rowcnt = 1;
	 } else {
	    firstrow = rowcnt;
	    rowcnt = 0;
	 }
      }
      for (i=0; i<currlogorg->actualnumdisks; i++) {
	 redunreqs[i] = NULL;
      }
      if (firstrow < partsperstripe) {
	 if (firstrow < currlogorg->rmwpoint) {
	    logorg_parity_table_read_old(currlogorg, curr->next, redunreqs, opid);
	 } else {
	    logorg_parity_table_recon(currlogorg, curr->next, redunreqs, curr->blkno, curr->devno, curr->bcount, opid);
	 }
	 opid = opid << 1;
      }
      if ((rowcnt) && (rowcnt != partsperstripe)) {
	 if (rowcnt < currlogorg->rmwpoint) {
	    logorg_parity_table_read_old(currlogorg, lastrow, redunreqs, opid);
	 } else {
	    logorg_parity_table_recon(currlogorg, lastrow, redunreqs, stripeno, 0, tablestart, opid);
	 }
      }
      for (i=0; i<currlogorg->actualnumdisks; i++) {
	 curr->next = NULL;
	 reqcnt += logorg_join_seqreqs(redunreqs[i], curr, LOGORG_PARITY_SEQGIVE);
	 redunreqs[i] = curr->next;
	 curr->next = NULL;
	 reqcnt += logorg_join_seqreqs(reqs[i], curr, LOGORG_PARITY_SEQGIVE);
	 reqs[i] = curr->next;
      }
      curr->next = curr;
      if (currlogorg->writesync) {
	 logorg_parity_table_dodeps_sync(currlogorg, curr, redunreqs, reqs);
      } else {
	 logorg_parity_table_dodeps_nosync(currlogorg, curr, redunreqs, reqs);
      }
   }
   if (curr->next) {
      temp = curr->next;
      curr->blkno = temp->blkno;
      curr->devno = temp->devno;
      curr->bcount = temp->bcount;
      curr->flags = temp->flags;
      curr->next = temp->next;
      addtoextraq((event *) temp);
   } else {
      fprintf(stderr, "Seem to have no requests when leaving logorg_parity_table\n");
      exit(1);
   }
/*
fprintf (outputfile, "Exiting logorg_parity_table - reqcnt %d\n", reqcnt);
*/
   return(reqcnt);
}
Exemple #22
0
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 ++;
	   }
   }
}