-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathfile1.txt
More file actions
executable file
·167 lines (132 loc) · 4.68 KB
/
file1.txt
File metadata and controls
executable file
·167 lines (132 loc) · 4.68 KB
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
160
161
162
163
164
165
/*
A.R.Karthick:
The scheduler for the Thread Implementation.
Gets called at an interval of 100 ms and hence 10 times per second.
*/
#include<stdio.h>
#include "mylist.h"
#include "task.h"
#include "myhash.h"
#include "sched.h"
#include "util.h"
DECLARE_LIST_HEAD(init_run_queue);//declare the run queue for the tasks
#define IS_STACK_START(task) ( (task)->stack_start == (task)->thread_struct.thread_regs.esp )
#define RESTORE_REGS(process,registers,argument) do { \
if(IS_STACK_START(process) ) { \
restore_ret_regs(registers,argument);\
} else { \
restore_regs(registers);\
}\
}while(0)
struct task_struct *current ;
struct task_struct *reaper = NULL; //reaper to be reaped for ZOMBIES
volatile unsigned long jiffies; //nr. of ticks since the start of controlling thread
/*Compute the goodness value of a task */
static int goodness(const struct task_struct *task) {
int points = task->counter; //give the time slice remaining as the goodness value
if(task->rt_priority) {
points = task->counter + 1000; //give a high goodness value to real time threads
goto out;
}
if(task->ticks > JIFFIES_LIMIT )
points = task->counter >> 1 ; //reduce the points
out:
return points;
}
/*The thread scheduler */
volatile void schedule(void) {
struct task_struct *prev_task = current; //defaults to the current thread switched out
struct task_struct *next_task = prev_task; //defaults to the previous task
struct list_head *run_queue = &init_run_queue; //pointer to the run queue of tasks
struct list_head *traverse;
int max = 0;//max goodness
/* First free of ZOMBIES */
if(reaper && reaper->state == TASK_ZOMBIE) {
task_del(reaper); //free the task
reaper = NULL;
}
if(LIST_EMPTY(run_queue) ) { //run queue empty
fprintf(stderr,"Scheduler: Restoring the Main Context..\n");
goto restore_main; //restore the main context
}
if( prev_task && prev_task->state == TASK_ZOMBIE) {
//exiting task
reaper = prev_task; //freeup in the next pass if possible
next_task = prev_task = NULL; //reset the prev_task
}
compute_next_task: //get the next task in the run queue
list_for_each(traverse,run_queue) {
struct task_struct *task = list_entry(traverse,struct task_struct,run_queue);
int points = goodness(task) ; //get the goodness of the task
if(points > max) {
max = points;
next_task = task;
}
}
if(! max) { //all the tasks have equal goodness value of 0
goto recalculate; //compute the goodness again
}
//We are here when we have found the next task
current = next_task; //reset the value of current to the next task
switch_to(prev_task); //switches context to the next task
return ; //we are here when the scheduled out thread starts running
recalculate:
{
struct list_head *run_queue = &init_run_queue;
struct list_head *traverse;
list_for_each(traverse,run_queue) {
struct task_struct *task = list_entry(traverse,struct task_struct,run_queue);
task->counter = (task->counter >> 1) - task->nice_level; //recalculate the counters
}
goto compute_next_task;
}
restore_main:
{ //restore the main context
struct regs *ptr = &main_context.main_thread.thread_regs;
(void)restore_regs(ptr); //restore the main context back
message(1,stderr,"Should never return here.Something wrong with saving the main context:");
}
return ; //should never reach here.
}
void switch_to(struct task_struct *prev_task){
struct regs *reg1 =NULL;
struct regs *reg2 = ¤t->thread_struct.thread_regs;
start_timer(); //setup the Timer before restoring the register
if(prev_task && prev_task == current) {
return ; //no need to save and restore regs
}
if(prev_task)
reg1 = &prev_task->thread_struct.thread_regs;
if(! reg1){
RESTORE_REGS(current,reg2,current->thread_struct.thread_arg);
}else {
if(! save_regs(reg1) ) { //first pass as the thread saved its registers
RESTORE_REGS(current,reg2,current->thread_struct.thread_arg);
}
}
}
void thread_reaper(void) {
if(current) {
release_thread_timer(current->pid); //release the timers for this thread
current->state = TASK_ZOMBIE; //zombie off the process
list_del(¤t->run_queue);
}
schedule(); //call the scheduler to switch in the next thread
}
/* Set the nice level of a thread.
Max = -20
Min = +19
*/
int set_nice_level(int pid,int nice_level) {
struct task_struct *task = task_hash_find(pid); //lookup the hash table
if(! task)
goto out;
if(nice_level > MIN_NICE_LEVEL)
nice_level = MIN_NICE_LEVEL;
if(nice_level < MAX_NICE_LEVEL)
nice_level = MAX_NICE_LEVEL;
task->nice_level = nice_level;
return 0;
out:
return -1;
}