00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "copyright.h"
00022
#include "scheduler.h"
00023
#include "system.h"
00024
#include "thread.h"
00025
#include <signal.h>
00026
#include <time.h>
00027
#include <unistd.h>
00028
#include <setjmp.h>
00029
00030
00031 sigjmp_buf
schd_jmp;
00032
Thread bogus_th(
"starter");
00033 sigset_t
timer_mask;
00034 timer_t
timer_id;
00035 itimerspec
timer_value;
00036 itimerspec
timer_empty;
00037
00038 bool preempt =
false;
00039
00040
00041
00042
00043
00044
00045 void SetPreemption()
00046 {
00047
preempt =
true;
00048 }
00049
00050
00051
00052
00053
00054
00055 Scheduler::Scheduler()
00056 {
00057 readyList =
new List;
00058 }
00059
00060
00061
00062
00063
00064
00065 Scheduler::~Scheduler()
00066 {
00067
delete readyList;
00068 }
00069
00070 int Scheduler::IsEmpty()
00071 {
00072
return readyList->
IsEmpty();
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 void Scheduler::ReadyToRun (
Thread *thread)
00084 {
00085 thread->
setStatus(
READY);
00086 readyList->
Append((
void *)thread);
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096 Thread*
Scheduler::FindNextToRun ()
00097 {
00098
return (
Thread *)readyList->
Remove();
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108 void Scheduler::Print()
00109 {
00110 printf(
"Ready list contents:\n");
00111 readyList->
Mapcar((
VoidFunctionPtr)
ThreadPrint);
00112 }
00113
00114
00115
00116
00117
00118
00119
00120 void Scheduler::timerIntH(
int sig)
00121 {
00122
static int counter = 0;
00123
00124
if (!
PREEMPTION && !
preempt)
00125
return;
00126
00127
timerCount++;
00128 counter++;
00129
if (counter ==
TICKS_PER_SEC)
00130 {
00131 counter = 0;
00132
secCount++;
00133 }
00134
00135 timer_settime(
timer_id, 0, &
timer_value, 0);
00136
00137
00138
if (
interrupt->
level ==
IntOff ||
scheduler->
IsEmpty())
00139 {
00140
if (
interrupt->
level ==
IntOff)
00141 {
00142
interrupt->
YieldOnReturn();
00143 }
00144
return;
00145 }
00146
00147
if (
currentThread)
00148 {
00149
if (sigsetjmp(
currentThread->
cbuff, 1) == 0)
00150
schedule();
00151 }
00152
else
00153
schedule();
00154
00155
return;
00156 }
00157
00158
00159
00160
00161
00162 void timerInit()
00163 {
00164
struct sigaction tact;
00165
00166
00167 memset(&tact, 0,
sizeof(
struct sigaction));
00168 tact.sa_handler = Scheduler::timerIntH;
00169 tact.sa_flags = 0;
00170 sigemptyset(&tact.sa_mask);
00171
00172 sigemptyset(&
timer_mask);
00173 sigaddset(&
timer_mask, SIGALRM);
00174
00175
if (sigaction(SIGALRM, &tact, NULL) != 0)
00176 printf(
"Failed to set the alarm handler\n");
00177
00178 timer_create(CLOCK_REALTIME, 0, &
timer_id);
00179 memset(&
timer_value, 0,
sizeof(
struct itimerspec));
00180 memset(&
timer_empty, 0,
sizeof(
struct itimerspec));
00181
timer_value.it_value.tv_sec = 0;
00182
timer_value.it_value.tv_nsec =
NSECS_PER_SEC / 15;
00183 timer_settime(
timer_id, 0, &
timer_value, 0);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 void schedule()
00199 {
00200
Thread *nextThread = 0;
00201
00202
00203 timer_settime(
timer_id, 0, &
timer_empty, 0);
00204
00205 nextThread =
scheduler->
FindNextToRun();
00206
00207
if (
threadToBeDestroyed != NULL)
00208 {
00209
currentThread = 0;
00210
DEBUG(
't',
"Purge Thread \"%s\"\n",
threadToBeDestroyed->
getName());
00211
delete threadToBeDestroyed;
00212
threadToBeDestroyed = NULL;
00213 }
00214
00215
if (nextThread != NULL)
00216 {
00217
if (
currentThread)
00218
scheduler->
ReadyToRun(
currentThread);
00219
00220
currentThread = nextThread;
00221
00222
if (!
currentThread->
started)
00223 {
00224
currentThread->
started = 1;
00225
currentThread->
setStatus(
RUNNING);
00226
DEBUG(
't',
"^Create^ \"%s\"\n",
currentThread->
getName());
00227
interrupt->
Enable();
00228 timer_settime(
timer_id, 0, &
timer_value, 0);
00229
00230
00231
SWITCH(&
bogus_th,
currentThread);
00232 }
00233
else
00234 {
00235
DEBUG(
't',
"Sched \"%s\"\n",
currentThread->
getName());
00236
currentThread->
setStatus(
RUNNING);
00237
interrupt->
Enable();
00238 timer_settime(
timer_id, 0, &
timer_value, 0);
00239 siglongjmp(
currentThread->
cbuff, 1);
00240 }
00241 }
00242
else if (
currentThread)
00243 {
00244
DEBUG(
't',
"Only Thread \"%s\"\n",
currentThread->
getName());
00245
currentThread->
setStatus(
RUNNING);
00246
interrupt->
Enable();
00247 timer_settime(
timer_id, 0, &
timer_value, 0);
00248 sigprocmask(SIG_UNBLOCK, &
timer_mask, 0);
00249 siglongjmp(
currentThread->
cbuff, 1);
00250 }
00251
else
00252 {
00253
00254
interrupt->
Enable();
00255 timer_settime(
timer_id, 0, &
timer_value, 0);
00256 }
00257 }
00258