#include "Scheduler.h" #include "main.h" #ifdef ultrix #include <signal.h> void microsleep (unsigned int microseconds); #endif #pragma implementation static int proc_count; Scheduler::Scheduler (){ proc_queue = NULL; tail_pointer = NULL; proc_count = 0; } Scheduler::~Scheduler (){ struct proc_node *temp; while (proc_queue) {delete proc_queue->process; temp = proc_queue->next; delete proc_queue; proc_queue = temp;} } int Scheduler::add_process (int obj_on , Value* mthd_nm , Val_List* actuals, int ticks){ struct proc_node *temp; // Value* tempval; // cout << "Starting method " << *mthd_nm->str << " on object " << obj_on; // if (actuals) // {tempval = actuals->nth(1)->copy(); // cout << " first argument: "; // tempval->print_val(); // tempval->release();} // cout << "\n"; if (db->lookup_var (obj_on, mthd_nm->sym)) {temp = new struct proc_node; if (!tail_pointer) {temp->next = (temp->prev = NULL); tail_pointer = (proc_queue = temp);} else {temp->prev = tail_pointer; temp->next = NULL; tail_pointer->next = temp; tail_pointer = temp;} temp->process = new Process (obj_on , proc_count , mthd_nm, ticks, actuals); return proc_count++;} else return -1; } /** *** this is not particularly efficient, but hopefully a better scheduler *** will magically appear in my hands... **/ int Scheduler::rm_process (int pid){ struct proc_node *temp; for (temp = proc_queue ; temp ; temp = temp->next) if (temp->process->process_id == pid) {if (temp->prev) {if (temp->next) {temp->prev->next = temp->next; temp->next->prev = temp->prev;} else {tail_pointer = temp->prev; temp->prev->next = NULL;}} else {proc_queue = temp->next; if (temp->next) temp->next->prev = NULL; else tail_pointer = NULL;} delete temp->process; delete temp; return 1;} return 0; } #ifdef ultrix // ultrix does not define usleep ... to get a sleep of less than a // second, i had to write it myself. grr. void alarm_handler(int ignored){ } void microsleep (unsigned int microseconds){ struct itimerval time1, time2; signal (SIGALRM , alarm_handler); time1.it_interval.tv_sec = 0; time1.it_interval.tv_usec = microseconds; time1.it_value.tv_sec = 0; time1.it_value.tv_usec = microseconds; time2.it_interval.tv_sec = 0; time2.it_interval.tv_usec = microseconds; time2.it_value.tv_sec = 0; time2.it_value.tv_usec = microseconds; setitimer (ITIMER_REAL , &time1 , &time2); pause(); time1.it_interval.tv_sec = 0; time1.it_interval.tv_usec = 0; time1.it_value.tv_sec = 0; time1.it_value.tv_usec = 0; time2.it_interval.tv_sec = 0; time2.it_interval.tv_usec = 0; time2.it_value.tv_sec = 0; time2.it_value.tv_usec = 0; setitimer (ITIMER_REAL , &time1 , &time2); signal (SIGALRM , SIG_IGN); } #endif void Scheduler::one_cycle (int slice_size){ struct proc_node *temp, *temp2; int retval, allsleeping=1; for (temp=proc_queue ; temp ;) {if (! (retval = temp->process->give_ticks (slice_size))) {temp2 = temp->next; rm_process (temp->process->process_id); temp = temp2;} else {temp = temp->next; if (retval>0) allsleeping=0;}} if (allsleeping) #ifdef ultrix microsleep (NICE_SLEEP); #else usleep (NICE_SLEEP); #endif }