diskevent.c 3.6 KB
/*
 * Copyright (C) 1996-1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * 
 * This file is part of the SimOS distribution. 
 * See LICENSE file for terms of the license. 
 *
 */

/* @TITLE "diskevent.c: heap of future events"*/
/* 
 * diskevent - support for disk device, by managing a heap of future events
 *
 * exported functions:
 *   DiskDeviceInit
 *   DiskDeviceDone
 *   DiskDeviceTransfer
 *   DiskDeviceStart
 *   DiskDeviceFinish
 *   DiskDeviceShape
 *
 * David Kotz 1993, Song Bac Toh 1994
 */

/* $Id: diskevent.c,v 1.1.1.1 2002/05/29 01:09:11 blythe Exp $ */

#include "modularize.h"

#include "heap.h"
#include "diskevent.h"

/* trace printing can be turned on/off in the Makefile */
#ifdef DEBUG
#define DEBUG_TRACE(x) {CYCLE_COUNTING_OFF; printf x; CYCLE_COUNTING_ON;}
#define REQUEST_TRACE(x) {CYCLE_COUNTING_OFF; printf x; CYCLE_COUNTING_ON;}
#else
#define DEBUG_TRACE(x) {}
#define REQUEST_TRACE(x) {}
#endif /* DBUG */

int wakeup;		        /* -1 if sleeping, TID if waking up */

/* ======================================================================== */
/*  DDEventInit
 *
 *  Initialize the event heap.
 */
void DDEventInit(void)
{
   extern Heap heap;		
   heap = InitHeap(HEAP_MAX); /* initialize the heap */
}



/*  DDEventRequest
 *
 *  Put an event request into the event heap.
 */
DDEvent *DDEventRequest(REQUESTCODE event, TICS eventTime, int disk)
{
  extern Heap heap;		 /* defined in modularize.h, initialized in
				    InitTime() because WaitTime() needs it. */
  heapdata *hpdat;
    
  REQUEST_TRACE(("\tDDEventRequest for %s @%s\n", 
		 DDhandlers[event].name, time_print(eventTime)));
  INVARIANT3((eventTime < NEVER), "%d: event occuring at NEVER\n", disk);
  
  hpdat = (heapdata *) malloc (sizeof(heapdata));
  if (hpdat == NULL)
    {
      fprintf(stderr, "DDEventRequest: malloc failed\n");
      exit(-1);
    }
  
  hpdat->req_code = event;
  hpdat->eventTime = eventTime;
  hpdat->disk = disk;
  AddHeap(heap, hpdat, (hpdat->eventTime));

#ifndef SOLO
  {
      extern void UpdateEventCallback(TICS);
      UpdateEventCallback(hpdat->eventTime);
  }
#endif

  return(hpdat);
}





/* @SUBTITLE DDEventCancel:  Take a queued request out of the heap" */
/* If the operation is successful, TRUE is return; otherwise, FALSE
   is returned. */
void DDEventCancel(DDEvent *ddevent)
{
  HeapData Hpdat;

  REQUEST_TRACE(("\tDDEventCancel for EndDiskXfer @%s\n", 
		 time_print(GetTime())));
  
  /* cast it to a pointer to heap data */
  Hpdat = (HeapData) ddevent;
  if (Hpdat != NULL)
    Hpdat->req_code = NOP;	/* cancel the event */
}


/* @SUBTITLE DDEventWakeup: Wake up a suspended thread */
void DDEventWakeup(int disk,int stid, TICS when)
{
   extern int wakeup;          /* declared in modularize.h */
   wakeup = stid;
#ifndef SOLO
  thread_wakeup(disk,stid);
#endif 
}


/* ------------------------------------------------------------------------ */
/* @SUBTITLE "Print out the request queue" */
/* There is only 1 request queue so no argument is needed for this
   function */
void DDPrintRequests(void)
{
  extern Heap heap;		/* the global request heap */
  Heap tempHp;			/* temporary storage for heap */
  HeapKey Hpkey;
  HeapData Hpdat;
  
  printf("Events on heap:\n");
  tempHp = InitHeap(HEAP_MAX);
  while (RemHeap(heap, &Hpdat, &Hpkey) != FALSE)
    {
      printf("disk %d;\tevent %20s;\n", Hpdat->disk, 
	     DDhandlers[Hpdat->req_code].name);
      AddHeap(tempHp, Hpdat, Hpdat->eventTime);
    }
  
  FreeHeap(heap);		 /* free the empty old heap */
  heap = tempHp;		 /* restore the recycled heap */
}
/* ------------------------------------------------------------------------ */