-
Notifications
You must be signed in to change notification settings - Fork 0
/
kernsem.cpp
125 lines (106 loc) · 2.57 KB
/
kernsem.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
/*
* kernsem.cpp
*
* Created on: Aug 23, 2018
* Author: OS1
*/
#include "kernsem.h"
#include "symbols.h"
#include "semaphor.h"
#include "thread.h"
#include "PCB.h"
#include "SCHEDULE.H"
volatile KernelSem::KernelSemList* KernelSem::head=NULL;
volatile KernelSem::KernelSemList* KernelSem::tail=NULL;
volatile ID KernelSem::semLastID=0;
void KernelSem::addToKernelSemList() {
//adding THIS object to global KernelSemList
KernelSem::KernelSemList *newElem = new KernelSem::KernelSemList(this);
if (KernelSem::head == NULL) {
KernelSem::head=newElem;
KernelSem::tail=newElem;
} else {
KernelSem::tail->next=newElem;
KernelSem::tail=newElem;
}
}
KernelSem* KernelSem::getKernelSembyID(ID id) {
for (KernelSemList* cur = (KernelSemList*)KernelSem::head; cur != NULL; cur=cur->next) {
if (cur->elem->myID == id) return cur->elem;
}
return NULL;
}
void KernelSem::removeFromKernelSemList() {
KernelSemList *cur=(KernelSemList*)head, *prev=NULL;
while (cur->elem != this) {
prev=cur;
cur=cur->next;
}
if (prev == NULL) {
//deleting at head position
head=head->next;
if (head == NULL) tail = NULL;
cur->elem=NULL;
cur->next=NULL;
delete cur;
} else if (cur->next == NULL) {
//deleting from the end of the list
prev->next=NULL;
tail=prev;
cur->elem=NULL;
cur->next=NULL;
delete cur;
} else {
prev->next=cur->next;
cur->next=NULL;
cur->elem=NULL;
delete cur;
}
}
KernelSem::KernelSem(int init, Semaphore* mySem) {
this->myID=++KernelSem::semLastID;
this->addToKernelSemList();
this->val=init;
this->mySem=mySem;
this->mySem->myKernelSemID = this->myID;
}
int KernelSem::value () {
return this->val;
}
void KernelSem::block() {
System::runningUserThread->state = PCB::BLOCKED;
BlockedThreads.put((PCB*)System::runningUserThread);
System::demanded_context_switch=TRUE;
}
void KernelSem::deblock() {
PCB* readyThread = BlockedThreads.get();
if (readyThread != NULL) {
readyThread->state=PCB::READY;
Scheduler::put(readyThread);
}
}
void KernelSem::signal() {
if (val++ < 0) deblock();
}
int KernelSem::wait(int toBlock) {
//returns 0 if thread ISN'T blocked
//returns -1 if thread IS blocked
int ret=0;
if (!toBlock && val <=0) ret = -1;
else {
if (--val < 0) {
ret=1;
block();
}
}
return ret;
}
KernelSem::~KernelSem() {
//deblocking all blocked threads :)
removeFromKernelSemList();
PCB* cur = BlockedThreads.get();
while (cur != NULL) {
cur->state=PCB::READY;
Scheduler::put(cur);
}
}