Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | pj | 1 | /* Project: OSLib |
2 | * Description: The OS Construction Kit |
||
3 | * Date: 1.6.2000 |
||
4 | * Idea by: Luca Abeni & Gerardo Lamastra |
||
5 | * |
||
6 | * OSLib is an SO project aimed at developing a common, easy-to-use |
||
7 | * low-level infrastructure for developing OS kernels and Embedded |
||
8 | * Applications; it partially derives from the HARTIK project but it |
||
9 | * currently is independently developed. |
||
10 | * |
||
11 | * OSLib is distributed under GPL License, and some of its code has |
||
12 | * been derived from the Linux kernel source; also some important |
||
13 | * ideas come from studying the DJGPP go32 extender. |
||
14 | * |
||
15 | * We acknowledge the Linux Community, Free Software Foundation, |
||
16 | * D.J. Delorie and all the other developers who believe in the |
||
17 | * freedom of software and ideas. |
||
18 | * |
||
19 | * For legalese, check out the included GPL license. |
||
20 | */ |
||
21 | |||
22 | /* Stupid Scheduling Demo */ |
||
23 | |||
24 | #include <ll/i386/cons.h> |
||
25 | #include <ll/i386/tss-ctx.h> |
||
26 | #include <ll/i386/error.h> |
||
27 | #include <ll/sys/ll/ll-instr.h> |
||
28 | #include <ll/sys/ll/ll-func.h> |
||
29 | #include <ll/sys/ll/time.h> |
||
30 | #include <ll/sys/ll/event.h> |
||
31 | #include <ll/stdlib.h> |
||
32 | |||
33 | #define FREE 0 |
||
34 | #define IDLE 1 |
||
35 | |||
36 | struct ctx { |
||
37 | WORD ll; |
||
38 | struct timespec time; |
||
39 | DWORD cputime; |
||
40 | DWORD toexec; |
||
41 | int acc; |
||
42 | DWORD slice; |
||
43 | int state; |
||
44 | }; |
||
45 | |||
46 | struct trkevt { |
||
47 | int thread; |
||
48 | DWORD time; |
||
49 | int value; |
||
50 | }; |
||
51 | |||
52 | struct trkevt track[10000]; |
||
53 | |||
54 | DWORD cpu[] = { 5000, 2000, 10000, 500, 5000, 6000, 20000, 1000, 7000 }; |
||
55 | DWORD p[] = |
||
56 | { 100000, 50000, 100000, 5000, 20000, 30000, 200000, 200000, 35000 }; |
||
57 | |||
58 | #define STACK_SIZE 100000U /* Stack size in bytes */ |
||
59 | #define USE_FPU 0x0001 |
||
60 | |||
61 | WORD th1, thm; |
||
62 | |||
63 | #define T 1000 |
||
64 | |||
65 | #if 1 |
||
66 | #define TO ll_context_to |
||
67 | #define FROM ll_context_from |
||
68 | #else |
||
69 | #define TO ll_context_load |
||
70 | #define FROM ll_context_save |
||
71 | #endif |
||
72 | |||
73 | /* For stack allocation checking */ |
||
74 | BYTE stacks[STACK_SIZE]; |
||
75 | #define N 10 |
||
76 | |||
77 | struct ctx context[N]; |
||
78 | int exec; |
||
79 | |||
80 | |||
81 | |||
82 | void endProg(void *p) |
||
83 | { |
||
84 | int i; |
||
85 | DWORD last[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
||
86 | DWORD lasttime, lastthread; |
||
87 | |||
88 | lasttime = 0; |
||
89 | lastthread = 0; |
||
90 | for (i = 0; i < 120; i++) { |
||
91 | if (last[track[i].thread] != 0) { |
||
92 | if (lastthread == 3) { |
||
93 | message("Thread %d <-- time %lu (after %lu), Thread %lu executed for %lu --- %d\n", |
||
94 | track[i].thread, track[i].time, |
||
95 | track[i].time - last[track[i].thread], lastthread, |
||
96 | track[i].time - lasttime, track[i].value); |
||
97 | } |
||
98 | } |
||
99 | lastthread = track[i].thread; |
||
100 | last[track[i].thread] = track[i].time; |
||
101 | lasttime = track[i].time; |
||
102 | } |
||
103 | |||
104 | ll_abort(110); |
||
105 | } |
||
106 | |||
107 | int schedule(void); |
||
108 | |||
109 | |||
110 | void endBudget(void *p) |
||
111 | { |
||
112 | struct ctx *c = p; |
||
113 | struct timespec time, toexec, xcuted, start; |
||
114 | int newthread; |
||
115 | |||
116 | ll_gettime(TIME_NEW, &time); |
||
117 | NULL_TIMESPEC(&toexec); |
||
118 | ADDNANO2TIMESPEC(c->toexec, &toexec); |
||
119 | SUBTIMESPEC(&(c->time), &toexec, &start); |
||
120 | SUBTIMESPEC(&time, &start, &xcuted); |
||
121 | NULL_TIMESPEC(&toexec); |
||
122 | ADDNANO2TIMESPEC(c->cputime * 1000, &toexec); |
||
123 | SUBTIMESPEC(&xcuted, &toexec, &start); |
||
124 | c->acc += TIMESPEC2NANOSEC(&start); |
||
125 | |||
126 | newthread = schedule(); |
||
127 | TO(context[newthread].ll); |
||
128 | } |
||
129 | |||
130 | int schedule(void) |
||
131 | { |
||
132 | static int k = 0; |
||
133 | int toe; |
||
134 | int done; |
||
135 | |||
136 | done = 0; |
||
137 | while (!done) { |
||
138 | exec = (exec + 1) % N; |
||
139 | while (context[exec].state == FREE) { |
||
140 | exec = (exec + 1) % N; |
||
141 | } |
||
142 | /* |
||
143 | track[k].thread = exec; |
||
144 | track[k].value = context[exec].acc; |
||
145 | track[k].time = ll_gettime(TIME_NEW, &(context[exec].time)); |
||
146 | k++; |
||
147 | */ |
||
148 | ll_gettime(TIME_NEW, &(context[exec].time)); |
||
149 | toe = (context[exec].cputime * 1000 - context[exec].acc); |
||
150 | if (toe <= 0) { |
||
151 | context[exec].acc -= (context[exec].cputime * 1000); |
||
152 | k--; |
||
153 | } else { |
||
154 | done = 1; |
||
155 | } |
||
156 | } |
||
157 | context[exec].toexec = toe; |
||
158 | ADDNANO2TIMESPEC(toe, &(context[exec].time)); |
||
159 | event_post(context[exec].time, endBudget, &(context[exec])); |
||
160 | return exec; |
||
161 | } |
||
162 | |||
163 | void thread(void *p) |
||
164 | { |
||
165 | int i, ii; |
||
166 | int position = 0; |
||
167 | char mark[11]; |
||
168 | int active = 1; |
||
169 | WORD count = 0; |
||
170 | |||
171 | i = *(int *) p; |
||
172 | while (active) { |
||
173 | /* |
||
174 | printf_xy(10, i * 2 + 1, WHITE, "%c", mark); |
||
175 | */ |
||
176 | count++; |
||
177 | position = (position + 1) % 10; |
||
178 | for (ii = 0; ii < 10; ii++) { |
||
179 | mark[ii] = ' '; |
||
180 | } |
||
181 | mark[10] = 0; |
||
182 | mark[position] = 'O'; |
||
183 | printf_xy(10, i * 2 + 1, WHITE, "%s", mark); |
||
184 | printf_xy(25, i * 2 + 1, WHITE, "%d %u", i, count); |
||
185 | for (ii = 0; ii < 10000; ii++); |
||
186 | |||
187 | if (count == 1000) |
||
188 | active = 0; |
||
189 | } |
||
190 | printf_xy(20, i * 2 + 1, WHITE, "Finished %d", i); |
||
191 | } |
||
192 | |||
193 | void killer(void) |
||
194 | { |
||
195 | int th; |
||
196 | |||
197 | cli(); |
||
198 | context[exec].state = FREE; |
||
199 | th = schedule(); |
||
200 | sti(); |
||
201 | TO(context[th].ll); |
||
202 | } |
||
203 | |||
204 | int main(int argc, char *argv[]) |
||
205 | { |
||
206 | DWORD sp1, sp2; |
||
207 | struct ll_initparms parms; |
||
208 | void *mbi; |
||
209 | DWORD t, oldt, secs; |
||
210 | int th; |
||
211 | int i; |
||
212 | int pars[N]; |
||
213 | struct timespec endTime; |
||
214 | |||
215 | sp1 = get_SP(); |
||
216 | cli(); |
||
217 | parms.mode = LL_ONESHOT; |
||
218 | parms.tick = T; |
||
219 | |||
220 | mbi = ll_init(); |
||
221 | event_init(&parms); |
||
222 | |||
223 | if (mbi == NULL) { |
||
224 | message("Error in LowLevel initialization code...\n"); |
||
225 | sti(); |
||
226 | l1_exit(-1); |
||
227 | } |
||
228 | message("LowLevel started...\n"); |
||
229 | for (i = 0; i < N - 1; i++) { |
||
230 | pars[i] = i; |
||
231 | context[i].ll = |
||
232 | ll_context_create(thread, &stacks[STACK_SIZE * (i + 1) / N], |
||
233 | &(pars[i]), killer, 0); |
||
234 | if (context[i].ll == 0) { |
||
235 | error("Unable to create thread"); |
||
236 | ll_abort(100); |
||
237 | } |
||
238 | context[i].state = IDLE; |
||
239 | context[i].cputime = cpu[i]; |
||
240 | context[i].toexec = cpu[i]; |
||
241 | context[i].acc = 0; |
||
242 | context[i].slice = p[i]; |
||
243 | } |
||
244 | |||
245 | context[N - 1].ll = FROM(); |
||
246 | context[N - 1].state = IDLE; |
||
247 | context[N - 1].cputime = 200; |
||
248 | context[N - 1].slice = 20000; |
||
249 | |||
250 | message("All Threads created...\n"); |
||
251 | NULL_TIMESPEC(&endTime); |
||
252 | endTime.tv_sec = 30; |
||
253 | |||
254 | event_post(endTime, endProg, NULL); |
||
255 | sti(); |
||
256 | |||
257 | cli(); |
||
258 | th = schedule(); |
||
259 | sti(); |
||
260 | |||
261 | TO(context[th].ll); |
||
262 | |||
263 | message("Thread MAIN restartin'\n"); |
||
264 | |||
265 | secs = 0; |
||
266 | oldt = 0; |
||
267 | while (secs <= 20) { |
||
268 | cli(); |
||
269 | t = ll_gettime(TIME_NEW, NULL); |
||
270 | sti(); |
||
271 | if (t < oldt) { |
||
272 | message("ARGGGGG! %lu %lu\n", t, oldt); |
||
273 | ll_abort(99); |
||
274 | } |
||
275 | oldt = t; |
||
276 | if ((t / 1000000) > secs) { |
||
277 | secs++; |
||
278 | printf_xy(40, 20, WHITE, "%lu %lu ", secs, t); |
||
279 | } |
||
280 | } |
||
281 | message("\n DONE: Secs = %lu\n", secs); |
||
282 | |||
283 | cli(); |
||
284 | ll_end(); |
||
285 | sp2 = get_SP(); |
||
286 | message("End reached!\n"); |
||
287 | message("Actual stack : %lx - ", sp2); |
||
288 | message("Begin stack : %lx\n", sp1); |
||
289 | message("Check if same : %s\n", sp1 == sp2 ? "Ok :-)" : "No :-("); |
||
290 | return 1; |
||
291 | } |