void InterruptHandler::dispatch_interrupt(REGS * _r) {

	/* -- INTERRUPT NUMBER */
	unsigned int int_no = _r->int_no - IRQ_BASE;

	//Console::puts("INTERRUPT DISPATCHER: int_no = ");
	////Console::putui(int_no);
	////Console::puts("\n");

	assert((int_no >= 0) && (int_no < IRQ_TABLE_SIZE));

	/* -- HAS A HANDLER BEEN REGISTERED FOR THIS INTERRUPT NO? */ 
        
	InterruptHandler * handler = handler_table[int_no];
	
	/* This is an interrupt that was raised by the interrupt controller. We need 
       to send and end-of-interrupt (EOI) signal to the controller after the 
       interrupt has been handled. */
	
	// When the timer ticks 20ms, an interrupt happens.
	// Then the interrupt handler will take care of this interrupt and do the following.
	// In dispatch_interrupt function, it looks at the handler table, finds the right handler, and
	// then calls the corresponding handler function.
	// However, this function will not be returned in a short time.
	// If the new thread does not pend from here, it will return from somewhere else and therefore the
	// EOI signal will not be sent to PIC soon. Also, if this is the case, when this thread regains
	// CPU later, it will return from here, causing an unreansonable EOI signal sent.
	// To avoid this case, we must send EOI signal before the handler function (context switch) is called.  

	/* Check if the interrupt was generated by the slave interrupt controller. 
       If so, send an End-of-Interrupt (EOI) message to the slave controller. */

	if (generated_by_slave_PIC(int_no)) {
		outportb(0xA0, 0x20);
	}

	/* Send an EOI message to the master interrupt controller. */
	outportb(0x20, 0x20);

	//Then we call the corresponding handler function
	if (!handler) {
		/* --- NO DEFAULT HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */
		Console::puts("INTERRUPT NO: ");
		Console::puti(int_no);
		Console::puts("\n");
		Console::puts("NO DEFAULT INTERRUPT HANDLER REGISTERED\n");
		//abort();
	}
	else {
		/* -- HANDLE THE INTERRUPT */
		handler->handle_interrupt(_r);
	}

}
Exemplo n.º 2
0
void InterruptHandler::dispatch_interrupt(REGS * _r) {

  /* -- INTERRUPT NUMBER */
  unsigned int int_no = _r->int_no - IRQ_BASE;

  //Console::puts("INTERRUPT DISPATCHER: int_no = ");
  //Console::putui(int_no);
  //Console::puts("\n");

  assert((int_no >= 0) && (int_no < IRQ_TABLE_SIZE));

  /* -- HAS A HANDLER BEEN REGISTERED FOR THIS INTERRUPT NO? */

  InterruptHandler * handler = handler_table[int_no];

  if (!handler) {
    /* --- NO DEFAULT HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */
    Console::puts("INTERRUPT NO: ");
    Console::puti(int_no);
    Console::puts("\n");
    Console::puts("NO DEFAULT INTERRUPT HANDLER REGISTERED\n");
//    abort();
  }
  else {
    /* -- HANDLE THE INTERRUPT */

    /* This is an interrupt that was raised by the interrupt controller. We need
       to send and end-of-interrupt (EOI) signal to the controller after the
       interrupt has been handled. */

    /* Check if the interrupt was generated by the slave interrupt controller.
       If so, send an End-of-Interrupt (EOI) message to the slave controller. */

    if (generated_by_slave_PIC(int_no)) {//modified to inform the control the interupt is being handled before the call to the handler
        outportb(0xA0, 0x20);//this will allow context switch during handler
    }

     /* Send an EOI message to the master interrupt controller. */
    outportb(0x20, 0x20);
    // we send interupt has been handled before calling handle interupt to prevent the interupt from not being acknoledged
    //when a context switch occurs inside of the handler
    // and when the calling thread finally returns from the context switch to not send the interupt handled message
    //because at this point it has already been handled and if the PIC is waiting for a handled message it is a different interupt
    handler->handle_interrupt(_r);

    //dont do anything after handler to prevent interupts not being handled
  }



}
Exemplo n.º 3
0
void InterruptHandler::dispatch_interrupt(REGS * _r) {

  /* -- INTERRUPT NUMBER */
  unsigned int int_no = _r->int_no - IRQ_BASE;

  //Console::puts("INTERRUPT DISPATCHER: int_no = ");
  //Console::putui(int_no);
  //Console::puts("\n");

  assert((int_no >= 0) && (int_no < IRQ_TABLE_SIZE));

  /* -- HAS A HANDLER BEEN REGISTERED FOR THIS INTERRUPT NO? */ 
        
  InterruptHandler * handler = handler_table[int_no];

  if (!handler) {
    /* --- NO DEFAULT HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */
    Console::puts("INTERRUPT NO: ");
    Console::puti(int_no);
    Console::puts("\n");
    Console::puts("NO DEFAULT INTERRUPT HANDLER REGISTERED\n");
//    abort();
  }
  else {
    /* -- HANDLE THE INTERRUPT */
    /* Signal PIC that the interrupt has been handled and then make the call to handle interrupt */
    if(int_no == 0)
	  outportb(0x20, 0x20);
    handler->handle_interrupt(_r);
  }

  /* This is an interrupt that was raised by the interrupt controller. We need 
       to send and end-of-interrupt (EOI) signal to the controller after the 
       interrupt has been handled. */

  /* Check if the interrupt was generated by the slave interrupt controller. 
       If so, send an End-of-Interrupt (EOI) message to the slave controller. */

  if (generated_by_slave_PIC(int_no)) {
       outportb(0xA0, 0x20);
  }
  /* Add additional check to see that we don't send EOI for interrupt 0, since its already done*/

  /* Send an EOI message to the master interrupt controller. */
  outportb(0x20, 0x20);
    
}
Exemplo n.º 4
0
void invoke_task(Task *task, const char *invoker) {

  debugPrintf("'%s': task_invoke('%s','%s') at %f\n", rtsys->blockName, task->name, invoker, rtsys->time);

  if (task->isUserTask()) {
    UserTask *usertask = (UserTask*)task;

    usertask->arrival_hook(usertask);
    if (usertask->nbrInvocations == 0) {
      usertask->arrival = rtsys->time;
      usertask->release = rtsys->time;
      usertask->release_hook(usertask);
      usertask->moveToList(rtsys->readyQs[usertask->affinity]);
      usertask->state = READY;
    } else {
      TaskInvocation *ti = new TaskInvocation();
      ti->timestamp = rtsys->time;
      strncpy(ti->invoker, invoker, MAXCHARS); // not used
      usertask->pending->appendNode(new DataNode(ti, NULL));
    }
    usertask->nbrInvocations++;

  } else {

    InterruptHandler *handler = (InterruptHandler*)task;

    if (handler->nbrInvocations == 0) {
      handler->timestamp = rtsys->time;
      strncpy(handler->invoker, invoker, MAXCHARS);
      handler->moveToList(rtsys->readyQs[handler->affinity]);
      handler->state = READY;
    } else {
      TaskInvocation *ti = new TaskInvocation();
      ti->timestamp = rtsys->time;
      strncpy(ti->invoker, invoker, MAXCHARS);
      handler->pending->appendNode(new DataNode(ti, NULL));
    }
    handler->nbrInvocations++;

  }

}
Exemplo n.º 5
0
bool ttCreatePeriodicTask(char *name, double offset, double period, double priority, double (*codeFcn)(int, void*)) {

  DataNode* dn;
  InterruptHandler* hdl;
  Timer *t;
  
  if (ttCreateTask(name, period, priority, codeFcn)) {

    dn = (DataNode*) rtsys->taskList->getLast(); // last created task

    // Create interrupt handler invoked periodically to create task jobs
    // see codefunctions.cpp for the code function
    hdl = new InterruptHandler("perHandler");
    hdl->codeFcn = rtsys->periodicTaskHandlerCode;

    hdl->handlerID = rtsys->nbrOfHandlers + 1;
    hdl->priority = -1000.0;
    hdl->display = false;
    hdl->data = (UserTask*) dn->data;

    rtsys->handlerList->appendNode(new DataNode(hdl, NULL));
    rtsys->nbrOfHandlers++;

    // Creating periodic timer that triggers the handler
    t = new Timer("perTimer");
    t->time = offset;  // First timer expiry at task offset
    t->period = period;
    t->isPeriodic = true;

    hdl->timer = t;
    hdl->moveToList(rtsys->timeQ);
    hdl->type = TIMER;
    
    ((UserTask*) dn->data)->periodichandler = hdl;
    return true;
  } else {
    return false;
  }
}
Exemplo n.º 6
0
static void mdlOutputs(SimStruct *S, int_T tid)
{
  //printf("mdlOutputs at %g\n", ssGetT(S));
  rtsys = (RTsys*) ssGetUserData(S);

  if (rtsys->init_phase) {
    /* Failure during initialization */
    return;
  }

  real_T *y = ssGetOutputPortRealSignal(S,0);
  real_T *n = ssGetOutputPortRealSignal(S,1);
  real_T *s = ssGetOutputPortRealSignal(S,2);
  real_T *m = ssGetOutputPortRealSignal(S,3);
  real_T *energyConsumption = ssGetOutputPortRealSignal(S,4);
  int i, j, k, detected;
  double dTime; 
 
  DataNode *dn;
  Task* task;
  UserTask* t;
  InterruptHandler* hdl;
  Monitor *mon;

  if (!rtsys->started && ssGetT(S) == 0.0) {
    rtsys->started = true;
    return;
  }

  if (!rtsys->mdlzerocalled) {
    printf("Zero crossing detection must be turned on in order to run TrueTime!\n");
    ssSetErrorStatus(S, "Zero crossing detection must be turned on in order to run TrueTime!");
    return;
  }
  
  /* Storing the time */

  rtsys->time = ssGetT(S) * rtsys->clockDrift + rtsys->clockOffset;
  
  detected = 0;



  /* Check interrupts */
  
  i = 0;
  dn = (DataNode*) rtsys->triggerList->getFirst();
  while (dn != NULL) {
    if (fabs(rtsys->interruptinputs[i]-rtsys->oldinterruptinputs[i]) > 0.1) {
      hdl = (InterruptHandler*) dn->data;
      Trigger* trig = hdl->trigger;
      if (rtsys->time - trig->prevHit > trig->latency) { 
	// Trigger interrupt handler
	if (hdl->myList == rtsys->readyQ) {
	  // handler serving older interrupts
	  hdl->pending++;
	} else {
	  hdl->moveToList(rtsys->readyQ);
	  detected = 1;
	}
 	trig->prevHit = rtsys->time;
      } else { 
	//printf("Call to interrupt handler %s ignored at time %f. Within interrupt latency!\n", hdl->name, rtsys->time);
      }
      rtsys->oldinterruptinputs[i] = rtsys->interruptinputs[i];
    }
    i++;
    dn = (DataNode*) dn->getNext();
  }
  
  /* Check network */
  
  dn = (DataNode*) rtsys->networkList->getFirst();
  while (dn != NULL) {
    hdl = (InterruptHandler*) dn->data;
    Network* network = hdl->network;
    i = network->networkID - 1;
    //printf("mdlOutputs: checking network #%d inp: %d oldinp: %d\n",i,rtsys->networkinputs[i],rtsys->oldnetworkinputs[i]);
    if (fabs(rtsys->networkinputs[i] - rtsys->oldnetworkinputs[i]) > 0.1) {
      hdl->moveToList(rtsys->readyQ);
      detected = 1;
      rtsys->oldnetworkinputs[i] = rtsys->networkinputs[i];
    }
    dn = (DataNode*) dn->getNext();
  }
  
  /* Run kernel? */

  double externTime =  (rtsys->time- rtsys->clockOffset) / rtsys->clockDrift;
  if ((externTime >= rtsys->nextHit) || (detected > 0)) {
    dTime = runKernel(ssGetT(S));
    if (rtsys->error) {
      // Something went wrong executing a code function
      mxArray *bn[1];
      mexCallMATLAB(1, bn, 0, 0, "gcs"); // get current system
      char buf[200];
      mxGetString(bn[0], buf, 200);
      for (unsigned int i=0; i<strlen(buf); i++) if (buf[i]=='\n') buf[i]=' '; 
      printf("In block ==> '%s'\nSimulation aborted!\n", buf); 
      ssSetStopRequested(S, 1);
    } else {
      rtsys->nextHit = (rtsys->time + dTime - rtsys->clockOffset) / rtsys->clockDrift;
    }
  }

  
  /* Outputs */

  for (i=0; i<rtsys->nbrOfOutputs; i++) {
    y[i] = rtsys->outputs[i];
  }
  
  
  /* Network send */

  for (i=0; i<rtsys->nbrOfNetworks; i++) {
    n[i] = rtsys->nwSnd[i];
  }
  
  /* Task schedule */
  
  i = 0;
  j = 0;
  dn = (DataNode*) rtsys->taskList->getFirst();
  while (dn != NULL) {
    t = (UserTask*) dn->data;
    rtsys->taskSched[i] = (double) (j+1);
    if (t->display) j++;
    dn = (DataNode*) dn->getNext();
    i++;
  }
  
  task = (Task*) rtsys->readyQ->getFirst();
  while (task != NULL) {
    if (task->isUserTask()) {
      t = (UserTask*) task;
      rtsys->taskSched[t->taskID - 1] += 0.25;
    }
    task = (Task*) task->getNext();
  }
  
  if ((rtsys->running != NULL) && (rtsys->running->isUserTask())) {
    t = (UserTask*) rtsys->running;
    rtsys->taskSched[t->taskID - 1] += 0.25;
  }    

  i = 0;
  j = 0;
  dn = (DataNode*) rtsys->taskList->getFirst();
  while (dn != NULL) {
    t = (UserTask*) dn->data;
    if (t->display) {
      s[j] = rtsys->taskSched[i];
      j++;
    }
    dn = (DataNode*) dn->getNext();
    i++;
  }
  

  /* Handler schedule */
  
  i = 0;
  j = 0;
  dn = (DataNode*) rtsys->handlerList->getFirst();
  while (dn != NULL) {
    rtsys->handlerSched[i] = (double) (j+rtsys->nbrOfSchedTasks+2);
    if (i==0 && rtsys->contextSwitchTime > EPS) {
      // Context switch schedule, move graph down to task level
      rtsys->handlerSched[i] = rtsys->handlerSched[i] - 1;
    }
    hdl = (InterruptHandler*) dn->data;
    if (hdl->display) j++;
    dn = (DataNode*) dn->getNext();
    i++;
  }

  task = (Task*) rtsys->readyQ->getFirst();
  while (task != NULL) {
    if (!(task->isUserTask())) {
      hdl = (InterruptHandler*) task;
      rtsys->handlerSched[hdl->handlerID - 1] += 0.25;
    }
    task = (Task*) task->getNext();
  }

  if ((rtsys->running != NULL) && (!(rtsys->running->isUserTask()))) {
    hdl = (InterruptHandler*) rtsys->running;
    rtsys->handlerSched[hdl->handlerID - 1] += 0.25;
  }

  i = 0;
  j = 0;
  dn = (DataNode*) rtsys->handlerList->getFirst();
  while (dn != NULL) {
    hdl = (InterruptHandler*) dn->data;
    if (hdl->display) {
      s[j+rtsys->nbrOfSchedTasks] = rtsys->handlerSched[i];
      j++;
    }
    dn = (DataNode*) dn->getNext();
    i++;
  }
  
  /* Monitor graph */
  
  k = 0;
  dn = (DataNode*) rtsys->monitorList->getFirst();
  while (dn != NULL) {
    mon = (Monitor*) dn->data;
    
    for (j=0; j<rtsys->nbrOfTasks; j++)
      rtsys->monitorGraph[j] = (double) (j+1+k*(1+rtsys->nbrOfTasks));
    
    t = (UserTask*) mon->waitingQ->getFirst();
    while (t != NULL) {
      i = t->taskID;
      rtsys->monitorGraph[i-1] += 0.25;
      t = (UserTask*) t->getNext();
    }
    if (mon->heldBy != NULL) {
      i = mon->heldBy->taskID;
      rtsys->monitorGraph[i-1] += 0.5;
    }
    if (mon->display) {
      for (j=0; j<rtsys->nbrOfTasks; j++)
 	m[j+k*rtsys->nbrOfTasks] = rtsys->monitorGraph[j];
      k++;
    }
    dn = (DataNode*) dn->getNext();
  }

  /* Energy consumption */
  energyConsumption[0] = rtsys->energyConsumption;
} 
Exemplo n.º 7
0
double runKernel(double externalTime) {
  
  double nextHit, timeElapsed; 

  Task *task, *temp, *oldrunning, *newrunning;
  UserTask *usertask;
  InterruptHandler *hdl;
  DataNode* dn;

  // If no energy, then we can not run
  if (rtsys->energyLevel <= 0) {
    //printf("Energy is out at time: %f\n", rtsys->time);
    return INF;
  }

  
  timeElapsed = externalTime - rtsys->prevHit; // time since last invocation
  rtsys->prevHit = externalTime;  // update previous invocation time
  nextHit = 0.0;

  //printf("runkernel at %f\n", rtsys->time);

#ifdef KERNEL_MATLAB
    /* Write rtsys pointer to global workspace */
  *((long *)mxGetPr(rtsys->rtsysptr)) = (long)rtsys;
#endif

  while (nextHit < EPS) {

    // Count down execution time for current task (usertask or handler)
    // and check if it has finished its execution 

    task = rtsys->running;
    if (task != NULL) {
      // Count down execution time 
      task->execTime -= timeElapsed * rtsys->cpuScaling;
      if (task->execTime < EPS) {
	// Execute next segment 
	task->segment++;

	if (task->isUserTask()) {
	  usertask = (UserTask*) task;
	  // Update budget and lastStart variable at segment change
	  usertask->budget -= (rtsys->time - usertask->lastStart);
	  usertask->lastStart = rtsys->time;
	}

	// Execute next segment of the code function

#ifndef KERNEL_MATLAB
	task->execTime = task->codeFcn(task->segment, task->data);
	if (rtsys->error) {
	  printf("Error in ==> task '%s', segment %d\n", task->name, task->segment);
	  return 0.0;
	}
#else
	if (task->codeFcnMATLAB == NULL) {
	  task->execTime = task->codeFcn(task->segment, task->data);
	} else {
	  task->execTime = executeCode(task->codeFcnMATLAB, task->segment, task);
	}
	if (rtsys->error) {
	  printf("Error in ==> task '%s', segment %d\n", task->name, task->segment);
	  return 0.0;
	}
#endif

	if (task->execTime < 0.0) { 
	  // Negative execution time = task finished
	  task->execTime = 0.0;
	  task->segment = 0;

	  if (task->myList == rtsys->readyQ) {
	    // Remove task from readyQ
	    task->remove();
	  }
	  
	  if (!(task->isUserTask())) {
	    hdl = (InterruptHandler*) task;

	    if (hdl->type == TIMER) {
	      if (hdl->timer->isPeriodic) {
		// if periodic timer put back in timeQ
		hdl->timer->time += hdl->timer->period;
		hdl->moveToList(rtsys->timeQ);
	      } else {
		// Remove timer and free up handler
		dn = getNode(hdl->timer->name, rtsys->timerList);
		rtsys->timerList->deleteNode(dn);
		delete hdl->timer;
		hdl->timer = NULL;
		hdl->type = UNUSED;
	      }
	    }
	    if (hdl->type == EXTERNAL) {
	      if (hdl->pending > 0) {
		// new external interrupt occured before handler finished
		hdl->pending--;
		hdl->moveToList(rtsys->readyQ);
	      }
	    }

	  } else { // the finished task is a usertask
	    usertask = (UserTask*) task;

	    // Execute finish-hook 
	    usertask->finish_hook(usertask);
	    usertask->state = IDLE;

	    // Release next job if any
	    usertask->nbrJobs--;
	    if (usertask->nbrJobs > 0) {
	      // next pending release
	      dn = (DataNode*) usertask->pending->getFirst();
	      double* release = (double*) dn->data;
	      usertask->release = *release;
	      usertask->absDeadline = *release + usertask->deadline;
	      usertask->moveToList(rtsys->timeQ);
	      usertask->pending->deleteNode(dn);
	      delete release;
	      // Execute release-hook 
	      usertask->release_hook(usertask);
	      usertask->state = SLEEPING;
	    
	    }
	  }
	}
      }
    } // end: counting down execution time of running task


    // Check time queue for possible releases

    task = (Task*) rtsys->timeQ->getFirst();
    while (task != NULL) {
      if ((task->wakeupTime() - rtsys->time) < EPS) {
	
	// Task to be released 
	temp = task;
	task = (Task*) task->getNext();
	temp->moveToList(rtsys->readyQ);
	
	if (temp->isUserTask()) {
	  usertask = (UserTask*) temp;
	  usertask->state = READY;

	}
      } else {
	break;
      }
    } // end: checking timeQ for releases


    // Determine task with highest priority and make it running task

    newrunning = (Task*) rtsys->readyQ->getFirst();
    oldrunning = rtsys->running;

    if (newrunning != NULL) {
      
      // Check for suspend- and resume-hooks
      
      if (oldrunning != NULL) {

	// Is oldrunning being suspended?
	if (oldrunning->isUserTask()) {
	  if (newrunning != oldrunning && ((UserTask*) oldrunning)->state == RUNNING) {
	    usertask = (UserTask*) oldrunning;
	    usertask->state = SUSPENDED;
	    usertask->suspend_hook(usertask);
	  }
	}
      }

      // invocation of hooks may have triggered kernelHandler
      newrunning = (Task*) rtsys->readyQ->getFirst();
      
      // Is newrunning being resumed?
      if (newrunning->isUserTask()) {
	if ( (((UserTask*) newrunning)->state == READY) || 
	     (((UserTask*) newrunning)->state == SUSPENDED) ) {
	  // newrunning is being resumed or started
	  usertask = (UserTask*) newrunning;
	  usertask->state = RUNNING;
	  if (usertask->segment == 0) {
	    usertask->start_hook(usertask);
	  } else {
	    usertask->resume_hook(usertask);
	  }
	}
      }

      // invocation of hooks may have triggered kernelHandler
      rtsys->running = (Task*) rtsys->readyQ->getFirst();
      
    } else { // No tasks in readyQ
      
      rtsys->running = NULL;
      
    } // end: task dispatching
    

    // Determine next invocation of kernel
    nextHit = getNextInvocation();
    timeElapsed = 0.0;
    
  } // end: loop while nextHit < EPS

  return nextHit;
}