-
Notifications
You must be signed in to change notification settings - Fork 0
/
Kernel.cpp
159 lines (128 loc) · 4.41 KB
/
Kernel.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
* Kernel.cpp
*
* Created on: Jun 1, 2021
* Author: OS1
*/
#include "Kernel.h"
#include "SCHEDULE.H"
#include <dos.h>
#include <iostream.h>
#include "IdleThr.h"
#include "PCB.h"
#include "Thread.h"
#include "KrnlSem.h"
unsigned tss, tsp, tbp;
void tick(); //za testove
volatile PCB * Kernel::runningPCB = 0;
volatile char Kernel::requestedContextChange = 0;
Time Kernel::runningTimeSlice = 2; //? sta ovde
IdleThr* Kernel::idleThread = 0;
volatile char Kernel::lockFlag = 1;
LList<PCB> Kernel::allPCBs;
LList<KernelSem> Kernel::allSems;
volatile char Kernel::currentUnlimited = 0;
IVTEntry * Kernel::ivtEntries[] = { 0 };
pInterrupt oldTimerRoutine;
void interrupt timer(...){
if(!Kernel::requestedContextChange){ //ako nismo eksplicitno zahtevali promenu konteksta
tick(); //tickujemo tajmer - sta tacno radi ? gde cemo da smanjimo trenutnoj niti timeslice ?
for(Kernel::allSems.toHead(); Kernel::allSems.hasCurr(); Kernel::allSems.toNext()){
Kernel::allSems.curr->tt->tickWaitingThreads();
}
if(!Kernel::currentUnlimited){
Kernel::runningTimeSlice--; //smanjujemo trenutnu nit
}
//verovatno treba ovde da probudimo niti koje su sleepovani sa odredjenim time
//to do
//oldTimerRoutine();
}
if(Kernel::requestedContextChange || (Kernel::runningTimeSlice == 0 && !Kernel::currentUnlimited)){
if (Kernel::lockFlag == 1){ //dozvoljen prekid
#ifndef BCC_BLOCK_IGNORE
asm{
mov tss, ss
mov tsp, sp
mov tbp, bp //ne moze mov running->sp, bp pa mora ovako
}
#endif
Kernel::runningPCB->ss = tss; //azuriramo running ss, sp, bp na sistemske ss, sp, bp
Kernel::runningPCB->sp = tsp; //sp ss bp ce se cesto menjati automatski - pa ne mozemo iskontrolisati to i u runningPCBu
Kernel::runningPCB->bp = tbp; //zbog toga, pre promene runningPCBa moramo da azuriramo runningSP SS BP na sveze vrednosti
//&& nije idle nit fali u ifu
if(Kernel::runningPCB != Kernel::idleThread->idlePCB() && (Kernel::runningPCB->status == NEW ||
Kernel::runningPCB->status == READY || Kernel::runningPCB->status == RUNNING)){
Kernel::runningPCB->status = READY;
Scheduler::put((PCB*)Kernel::runningPCB); //ako nije blokirana ili terminated, stavi je u sched
}
Kernel::runningPCB = Scheduler::get(); //neku koja nije vec zavrsena
if(!Kernel::runningPCB)//idle nit koju ne stavljamo u sched
{
Kernel::runningPCB = Kernel::idleThread->idlePCB();
}
if(Kernel::runningPCB->timeSlice == 0) Kernel::currentUnlimited = 1;
else Kernel::currentUnlimited = 0;
Kernel::runningPCB->status = RUNNING; //nova je running
Kernel::runningTimeSlice = Kernel::runningPCB->timeSlice; //restauriramo preostalo vreme i registre
tsp = Kernel::runningPCB->sp;
tss = Kernel::runningPCB->ss;
tbp = Kernel::runningPCB->bp;
#ifndef BCC_BLOCK_IGNORE
asm{
mov ss, tss
mov sp, tsp
mov bp, tbp
}
#endif
Kernel::requestedContextChange = 0; //resen je
}
else { //nije dozvoljen prekid, zapamticemo request svakako
Kernel::requestedContextChange = 1;
}
}
if(!Kernel::requestedContextChange){
oldTimerRoutine();
}
}
void Kernel::dispatch(){
#ifndef BCC_BLOCK_IGNORE
asm cli;
//cout << "U dispatchu " << endl;
requestedContextChange = 1; //oznacimo da jesmo trazili promenu i udjemo u timer prekidnu rutinu
timer();
asm sti;
#endif
}
void Kernel::init(){
#ifndef BCC_BLOCK_IGNORE
asm cli
oldTimerRoutine = getvect(0x8); //stara oldtimerroutine
setvect(0x8, timer); //nova timer
#endif
Kernel::idleThread = new IdleThr();
Kernel::idleThread->start(); //samo joj stavi status na ready
PCB * mainPCB = (new Thread(0x100, 2))->myPCB;
mainPCB->status = RUNNING;
Kernel::runningPCB = mainPCB;
Kernel::runningTimeSlice = 2; //default
//PCB * ppp = idleThread->myPCB;
#ifndef BCC_BLOCK_IGNORE
asm sti
#endif
}
void Kernel::restore(){
#ifndef BCC_BLOCK_IGNORE
asm cli
setvect(0x8, oldTimerRoutine); //restore u 8 ulaz staru
#endif
//obrisi svu memoriju - sve pcbove, idle..
for(allSems.toHead(); allSems.hasCurr(); allSems.toNext()){
delete allSems.getCurr();
}
for(allPCBs.toHead(); allPCBs.hasCurr(); allPCBs.toNext()){
delete allPCBs.getCurr();
}
#ifndef BCC_BLOCK_IGNORE
asm sti
#endif
}