mems_event.c

来自「disksim是一个非常优秀的磁盘仿真工具」· C语言 代码 · 共 1,946 行 · 第 1/4 页

C
1,946
字号
/* * DiskSim Storage Subsystem Simulation Environment (Version 4.0) * Revision Authors: John Bucy, Greg Ganger * Contributors: John Griffin, Jiri Schindler, Steve Schlosser * * Copyright (c) of Carnegie Mellon University, 2001-2008. * * This software is being provided by the copyright holders under the * following license. By obtaining, using and/or copying this software, * you agree that you have read, understood, and will comply with the * following terms and conditions: * * Permission to reproduce, use, and prepare derivative works of this * software is granted provided the copyright and "No Warranty" statements * are included with all reproductions and derivative works and associated * documentation. This software may also be redistributed without charge * provided that the copyright and "No Warranty" statements are included * in all redistributions. * * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS. * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. * COPYRIGHT HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE * OR DOCUMENTATION. * *//* TODO * * Replace curr->time with simtime?  Is this a problem? * Remove lastreq_lbn? */#include <stdio.h>#include <stdlib.h>#include "mems_global.h"#include "mems_disksim.h"#include "mems_mapping.h"#include "mems_internals.h"#include "mems_buffer.h"#include "disksim_bus.h"#include "disksim_ioqueue.h"// #define VERBOSE_EVENTLOOPunsigned int mems_reqinfo_mallocs = 0;unsigned int mems_reqinfo_frees   = 0;unsigned int mems_extent_mallocs  = 0;unsigned int mems_extent_frees    = 0;/************************************************************************ * Bus stuff ************************************************************************/static voidmems_send_event_up_path (ioreq_event * curr,			 double delay){  /* Acquire the bus (if not already acquired), then use bus_delay   * to send the event up the path.   */  mems_t *dev   = getmems(curr->devno);  int     busno  = mems_get_busno(curr);  int     slotno = mems_get_slotno(curr->devno);  /* Put new request at head of buswait queue */  curr->next     = dev->buswait;  dev->buswait   = curr;  curr->tempint1 = busno;  curr->time     = delay;  if (dev->busowned == -1)    {      /* Must get ownership of bus first */      if (bus_ownership_get(busno, slotno, curr) == FALSE) {	/* FIXME: dev->stat.requestedbus = simtime */      }      else	{	  bus_delay(busno, DEVICE, curr->devno, delay, curr);	}    }  else if (dev->busowned == busno)    {      /* Already own the bus, so send it on up! */      bus_delay(busno, DEVICE, curr->devno, delay, curr);    }  else    {      fprintf(stderr, "Wrong bus owned for transfer desired!\n");      exit(1);    }}voidmems_bus_ownership_grant (int devno,			  ioreq_event *curr,			  int busno,			  double arbdelay){  mems_t *dev = getmems(devno);  ioreq_event *tmp = dev->buswait;  #ifdef VERBOSE_EVENTLOOP  printf("Hi! I'm in mems_bus_ownership_grant: %f\n", simtime);  fflush(stdout);#endif  while ((tmp != NULL) && (tmp != curr)) tmp = tmp->next;  if (!tmp)    {      fprintf(stderr,	      "Bus ownership granted to unknown request -- devno %d, busno %d\n",	      devno, busno);      exit(1);    }  dev->busowned = busno;  /* FIXME: Do we _really_ want to keep this statistic? Is it valid? */  // dev->stat.waitingforbus += simtime - dev->stat.requestedbus;  // dev->stat.numbuswaits++;  bus_delay(busno, DEVICE, dev->devno, tmp->time, curr);}voidmems_bus_delay_complete (int devno,			 ioreq_event *curr,			 int sentbusno){  mems_t *dev = getmems(devno);  intchar slotno;  intchar busno;  int     depth;#ifdef VERBOSE_EVENTLOOP  printf("Hello! I'm in mems_bus_delay_complete: %f\n", simtime);  fflush(stdout);#endif  busno.value  = curr->busno;  slotno.value = curr->slotno;  depth = mems_get_depth(curr->devno);  slotno.byte[depth] = slotno.byte[depth] >> 4;  curr->time = (double)0.0;  if (curr == dev->buswait)    {      dev->buswait = curr->next;    }  else    {      ioreq_event *tmp = dev->buswait;      while ((tmp->next != NULL) && (tmp->next != curr)) tmp = tmp->next;      if (tmp->next != curr)	{	  fprintf(stderr,		  "Bus delay complete for unknown request -- devno %d, busno %d\n",		  devno, busno.value);	  exit(1);	}    }  if (depth == 0)    {      intr_request ((event *)curr);    }  else    {      bus_deliver_event (busno.byte[depth], slotno.byte[depth], curr);    }}/************************************************************************ * Other support functions ************************************************************************/mems_extent_t *mems_get_new_extent(ioreq_event *curr){  mems_extent_t *new_extent = (mems_extent_t *)malloc(sizeof(mems_extent_t));  // mems_extent_t *new_extent = (mems_extent_t *)getfromextraq();  mems_extent_mallocs++;  new_extent->firstblock = curr->blkno;  new_extent->lastblock  = curr->blkno + curr->bcount - 1;  new_extent->completed_block_media = -1;  new_extent->completed_block_bus = -1;  new_extent->bus_done = FALSE;  new_extent->media_done = FALSE;  new_extent->next = NULL;  new_extent->prev = NULL;  new_extent->request = curr;  new_extent->next_block_start = -1;  new_extent->next_block_end = -1;  return new_extent;}voidmems_update_reqinfo(ioreq_event *curr){  mems_reqinfo_t *r = curr->mems_reqinfo;  mems_extent_t *extent_ptr = r->extents;  ioreq_event *event_ptr;  ioreq_event *next_event_ptr;#ifdef VERBOSE_EVENTLOOP  printf("mems_update_reqinfo -- entry\n");#endif  event_ptr = curr;  while(event_ptr)    {      next_event_ptr = event_ptr->batch_next;      free(((mems_reqinfo_t *)event_ptr->mems_reqinfo)->extents);      mems_reqinfo_frees++;      if (event_ptr->mems_reqinfo != r) 	{	  free(event_ptr->mems_reqinfo);	  mems_reqinfo_frees++;	  //addtoextraq(event_ptr->mems_reqinfo);	}      event_ptr = next_event_ptr;    }  r->extents = mems_get_new_extent(curr);  r->num_extents = 1;  r->batch_arrival_time = curr->time;#ifdef VERBOSE_EVENTLOOP  printf("mems_update_reqinfo -- curr->flags = %d\n", curr->flags);#endif  /*  if ((curr->flags & 0x1) == DISKSIM_WRITE)    {#ifdef VERBOSE_EVENTLOOP      printf("mems_update_reqinfo -- this is a write\n");#endif      r->extents->completed_block_bus = r->extents->lastblock;      r->extents->bus_done = TRUE;#ifdef VERBOSE_EVENTLOOP      printf("mems_update_reqinfo -- completed_block_bus = %d\n",	     r->extents->completed_block_bus);#endif    }  */  extent_ptr = r->extents;  event_ptr = curr->batch_next;  while (event_ptr != NULL)    {      extent_ptr->next = mems_get_new_extent(event_ptr);      extent_ptr->next->prev = extent_ptr;      if ((event_ptr->flags & 0x1) == DISKSIM_WRITE)	{#ifdef VERBOSE_EVENTLOOP	  printf("mems_update_reqinfo -- this is a write\n");#endif	  extent_ptr->next->completed_block_bus = extent_ptr->next->lastblock;	  extent_ptr->next->bus_done = TRUE;#ifdef VERBOSE_EVENTLOOP	  printf("mems_update_reqinfo -- completed_block_bus = %d\n",		 extent_ptr->next->completed_block_bus);#endif	}      r->num_extents++;      if (curr->time < r->batch_arrival_time)	{	  r->batch_arrival_time = curr->time;	}      event_ptr->mems_reqinfo = NULL;      event_ptr = event_ptr->batch_next;      extent_ptr = extent_ptr->next;    }}static mems_reqinfo_t *mems_get_new_reqinfo (ioreq_event *curr){  ioreq_event *event_ptr;  mems_extent_t *extent_ptr;  // mems_reqinfo_t *r = (mems_reqinfo_t *)getfromextraq();  mems_reqinfo_t *r = (mems_reqinfo_t *)malloc(sizeof(mems_reqinfo_t));  mems_reqinfo_mallocs++;  extent_ptr = r->extents;  r->extents = mems_get_new_extent(curr);  r->num_extents = 1;  extent_ptr = r->extents;  event_ptr = curr;  // if there are more in the batch  (there shouldn't be)  while (event_ptr->batch_next != NULL)    {      event_ptr = event_ptr->batch_next;      extent_ptr->next = mems_get_new_extent(event_ptr);      r->num_extents++;    }  r->bus_pending = FALSE;  r->bus_done    = FALSE;  r->media_done  = FALSE;  r->bus_extent = NULL;  r->request_energy_uj = 0.0;  r->firstseek            = 1;	/* TRUE: first seek hasn't yet completed */  r->subtrack_access_num  = 0;  r->subtrack_access_tips = 0;  return r;}static struct mems_prefetch_info *mems_get_prefetch_info (ioreq_event *curr){  mems_sled_t    *sled = curr->mems_sled;  mems_reqinfo_t *reqinfo = curr->mems_reqinfo;  struct mems_prefetch_info *p;  if (!sled->prefetch_depth) return NULL;  p = (struct mems_prefetch_info *)getfromextraq();  p->firstblock = reqinfo->lastblock + 1;  p->lastblock  = p->firstblock + sled->prefetch_depth - 1;  p->completed_block  = -1;  p->next_block_start = -1;  p->next_block_end   = -1;  return p;}static voidsend_disconnect (ioreq_event *curr,		 double latency){  ioreq_event *intrp = ioreq_copy(curr);  intrp->type = IO_INTERRUPT_ARRIVE;  intrp->cause = DISCONNECT;  mems_send_event_up_path(intrp, latency);}static voidsend_completion (ioreq_event *curr,		 double latency){  ioreq_event *intrp = ioreq_copy(curr);  intrp->type = IO_INTERRUPT_ARRIVE;  intrp->cause = COMPLETION;  mems_send_event_up_path(intrp, latency);}static voidsend_reconnect (ioreq_event *curr,		double latency){  ioreq_event *intrp = ioreq_copy(curr);  intrp->type = IO_INTERRUPT_ARRIVE;  intrp->cause = RECONNECT;  mems_send_event_up_path(intrp, latency);}static voidmems_request_complete (ioreq_event *curr,		       double latency){  mems_sled_t *sled = curr->mems_sled;  mems_reqinfo_t *reqinfo = curr->mems_reqinfo;  ioreq_event *batch_ptr;  ioreq_event *next_ptr;#ifdef VERBOSE_EVENTLOOP  printf("Entering mems_request_complete() - curr->blkno = %d, time = %f, latency = %f\n",	 curr->blkno, simtime, latency);  fflush(stdout);#endif  {	/* Verify that we're not insane here */    mems_reqinfo_t *r = curr->mems_reqinfo;    // assert ((r->bus_done == TRUE) && (r->media_done == TRUE));  }  if (!ioqueue_physical_access_done(sled->queue, curr))    {      fprintf(stderr, "mems_request_complete: sled ioreq_event not found by ioqueue_physical_access_done call\n");      exit(1);    }  /*    if (!ioqueue_physical_access_done(sled->dev->queue, curr)) {    fprintf(stderr, "mems_request_complete: device ioreq_event not found by ioqueue_physical_access_done call\n");    exit(1);  }  */  send_completion(curr, latency);    if (reqinfo && reqinfo->subtrack_access_num)    {      /* Don't keep statistics for requests that hit entirely in the buffer       * WARNING: If you _want_ to keep these, note that the        * stat.tips_per_access statistic will die with a divide-by-zero       * error unless you do something else here */            stat_update(&sled->dev->stat.request_energy_uj, 		  reqinfo->request_energy_uj);      stat_update(&sled->stat.request_energy_uj, 		  reqinfo->request_energy_uj);            stat_update(&sled->dev->stat.subtrack_accesses, 		  reqinfo->subtrack_access_num);      stat_update(&sled->stat.subtrack_accesses, 		  reqinfo->subtrack_access_num);            stat_update(&sled->dev->stat.tips_per_access,		  reqinfo->subtrack_access_tips / reqinfo->subtrack_access_num);      stat_update(&sled->stat.tips_per_access,		  reqinfo->subtrack_access_tips / reqinfo->subtrack_access_num);     }}voidprint_extent_info(mems_reqinfo_t *reqinfo){  int i;  mems_extent_t *extent_ptr;  extent_ptr = reqinfo->extents;  i = 0;  while(extent_ptr != NULL)    {      printf(" extent %d, firstblock = %d, lastblock = %d\n",	     i, extent_ptr->firstblock, extent_ptr->lastblock);      printf(" next_block_start = %d, next_block_end = %d\n",	     extent_ptr->next_block_start, extent_ptr->next_block_end);      printf(" completed_block_media = %d, completed_block_bus = %d\n",	     extent_ptr->completed_block_media, extent_ptr->completed_block_bus);      printf(" media_done = %d, bus_done = %d\n",	     extent_ptr->media_done, extent_ptr->bus_done);      extent_ptr = extent_ptr->next;      i++;    }}/************************************************************************ * Energy updating functions ************************************************************************/voidmems_energy_update_device_overhead_complete_inactive(mems_sled_t *sled){  double energy_j;    /* Account for both energy consumed during inactive period... */  energy_j =     (sled->inactive_power_mw * (simtime - sled->lastreq_comptime)) /     1000000.0;  sled->dev->stat.total_energy_j += energy_j;  sled->stat.total_energy_j += energy_j;    sled->dev->stat.inactive_energy_j += energy_j;  sled->stat.inactive_energy_j      += energy_j;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?