/*
	Runtime Engine
		By Craig Kadziolka ( Nov 1999 - Dec 2000 )

	Modifications and copying is permitted providing this header
	is retained
*/

#include "context.h"
#include "scheduler.h"
#include "ithreads.h"
#include <assert.h>
#include "Synchronization.h"

///////////////////////////////////////////////////////
//  Function:  SCHEDULE                              //
// ----------------------                            //
// This function is used to decide which thread will //
// next be run.  It does so by moving the appropriate//
// thread to the head of the CPU queue and then calls//
// load context with the specified threads save area //
// as the parameter.                                 //
///////////////////////////////////////////////////////

extern void * current_thread;

void Schedule()
{

  int loopvar = 0, priority_mark = 0;

#ifdef DEBUG
  Invariant();
#endif

  for (loopvar = 0; loopvar < PRIORITY_LEVELS; loopvar++) {

    if (PQH(loopvar) != NULL) {
      priority_mark = loopvar;
      loopvar = PRIORITY_LEVELS; /* Get us out of here */
    }
    
  }

  PQH(priority_mark)->next = PQT(priority_mark);
  PQT(priority_mark)->previous = PQH(priority_mark);
  
  PQH(priority_mark) = PQH(priority_mark)->previous;
  PQT(priority_mark) = PQT(priority_mark)->previous;
 
  /* Break the daisy chain, after head->next */
  PQH(priority_mark)->next = 0;
  PQT(priority_mark)->previous = 0;
  
#ifdef DEBUG  
  Invariant();
#endif  

	current_thread = PQH(priority_mark) -> save_area_base;

  Load_Context(PQH(priority_mark)->save_area_base);
}
