Rev 1123 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1120 | pj | 1 | /* |
2 | * Project: S.Ha.R.K. |
||
3 | * |
||
4 | * Coordinators: |
||
5 | * Giorgio Buttazzo <giorgio@sssup.it> |
||
6 | * Paolo Gai <pj@gandalf.sssup.it> |
||
7 | * |
||
8 | * Authors : |
||
9 | * Paolo Gai <pj@gandalf.sssup.it> |
||
10 | * (see the web pages for full authors list) |
||
11 | * |
||
12 | * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy) |
||
13 | * |
||
14 | * http://www.sssup.it |
||
15 | * http://retis.sssup.it |
||
16 | * http://shark.sssup.it |
||
17 | */ |
||
18 | |||
19 | /* |
||
20 | * Copyright (C) 2000 Giorgio Buttazzo, Paolo Gai, Massimiliano Giorgi |
||
21 | * |
||
22 | * This program is free software; you can redistribute it and/or modify |
||
23 | * it under the terms of the GNU General Public License as published by |
||
24 | * the Free Software Foundation; either version 2 of the License, or |
||
25 | * (at your option) any later version. |
||
26 | * |
||
27 | * This program is distributed in the hope that it will be useful, |
||
28 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
29 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
30 | * GNU General Public License for more details. |
||
31 | * |
||
32 | * You should have received a copy of the GNU General Public License |
||
33 | * along with this program; if not, write to the Free Software |
||
34 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
35 | * |
||
36 | * |
||
1159 | pj | 37 | * CVS : $Id: sched.c,v 1.3 2003-05-01 19:44:07 pj Exp $ |
1120 | pj | 38 | |
39 | This demo is derived from the cbsmouse.c Hartik's example. |
||
40 | |||
41 | It only prints the task scheduling in graphic mode... |
||
42 | |||
43 | There is a parameter to choose the type of scheduling module |
||
44 | to initialize. |
||
45 | |||
46 | to init correctly the module and task bandwidth parameters, set the defines |
||
47 | NUM and DEN in initg.c and testg.c and remember the "s" (soft) parameter!!! |
||
48 | |||
49 | to plot the deadlines assigned by CBS or TBS, compile cbs.c or tbs.c with |
||
50 | the TESTG define |
||
51 | (gray dots over the mouse line are the deadlines, green dots are CBS |
||
52 | shifts) |
||
53 | |||
54 | Note that a lot of times the demo exits with an exception; to avoid |
||
55 | these exception you have to properly tune the task parameters. |
||
56 | |||
57 | On a well configured machine, you will notice the little differences |
||
58 | between different servers when moving the mouse ;-) |
||
59 | |||
60 | */ |
||
61 | |||
62 | #include <kernel/kern.h> |
||
63 | #include <drivers/glib.h> |
||
64 | #include <drivers/keyb.h> |
||
65 | #include <drivers/mouse.h> |
||
66 | #include <semaphore.h> |
||
67 | |||
68 | /*--------------------------------------------------------------*/ |
||
69 | /* TEST ON EDF SCHEDULING */ |
||
70 | /*--------------------------------------------------------------*/ |
||
71 | |||
72 | #define LMOUSE 20 |
||
73 | #define LM 40 /* line of main */ |
||
74 | #define OFFSET 20 /* initial phase */ |
||
75 | #define CHAR_DIM 8 /* Height of chars in pixels */ |
||
76 | |||
77 | #define DX (640/5-1) |
||
78 | |||
79 | int col[3] = {2, 4, 14}; /* colors of timelines */ |
||
80 | int lev[3] = {80, 120, 160}; /* level of timelines */ |
||
81 | int ptime[3] = {10, 20, 25}; /* number of cycles */ |
||
82 | int period[3] = {40, 50,100}; /* tasks' periods */ |
||
83 | int tick = 1; /* system tick */ |
||
84 | int tscale = 1; /* time scale */ |
||
85 | TIME starttime = 0; /* Simulation start time (scaled) */ |
||
86 | |||
87 | char *title; /* used in initg.c */ |
||
88 | |||
89 | /* period[] is scaled with a factor of PERIODSCALE usec */ |
||
90 | #define PERIODSCALE 5000 |
||
91 | |||
92 | // update also isched.c!!! |
||
93 | #define NUM 2000 |
||
94 | #define DEN 64000 |
||
95 | |||
96 | sem_t mutex; /* Semaphore for graphix*/ |
||
97 | |||
98 | //#define IY(y) (480 - y) |
||
99 | #define IY(y) y |
||
100 | |||
101 | /* |
||
102 | * mouse cursor |
||
103 | * |
||
104 | */ |
||
105 | |||
106 | #define W WHITE |
||
107 | #define R RED |
||
108 | #define G GREEN |
||
109 | #define M MAGENTA |
||
110 | |||
111 | /* shape */ |
||
112 | |||
113 | BYTE mycursor[16*16]= { |
||
114 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
||
115 | 0,W,W,W,W,0,0,0,0,0,0,W,W,W,W,0, |
||
116 | 0,W,M,0,0,0,0,0,0,0,0,0,0,M,W,0, |
||
117 | 0,W,0,M,0,0,0,0,0,0,0,0,M,0,W,0, |
||
118 | 0,W,0,0,M,0,0,0,0,0,0,M,0,0,W,0, |
||
119 | 0,0,0,0,0,M,0,0,0,0,M,0,0,0,0,0, |
||
120 | 0,0,0,0,0,0,G,G,G,G,0,0,0,0,0,0, |
||
121 | 0,0,0,0,0,0,G,0,0,G,0,0,0,0,0,0, |
||
122 | 0,0,0,0,0,0,G,0,0,G,0,0,0,0,0,0, |
||
123 | 0,0,0,0,0,0,G,0,0,G,0,0,0,0,0,0, |
||
124 | 0,0,0,0,0,0,G,G,G,G,0,0,0,0,0,0, |
||
125 | 0,0,0,0,0,0,M,M,M,M,0,0,0,0,0,0, |
||
126 | 0,0,0,0,0,0,M,M,M,M,0,0,0,0,0,0, |
||
127 | 0,0,0,0,0,M,M,M,M,M,M,0,0,0,0,0, |
||
128 | 0,0,0,0,M,M,M,M,M,M,M,M,0,0,0,0, |
||
129 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
||
130 | }; |
||
131 | |||
132 | #define F 0xff |
||
133 | #define B 0x00 |
||
134 | |||
135 | /* mask */ |
||
136 | BYTE mybkg[16*16]= { |
||
137 | B,B,B,B,B,B,F,F,F,F,B,B,B,B,B,B, |
||
138 | B,0,0,0,0,B,F,F,F,F,B,0,0,0,0,B, |
||
139 | B,0,0,B,B,F,F,F,F,F,B,B,B,0,0,B, |
||
140 | B,0,B,0,B,F,F,F,F,F,F,B,0,B,0,B, |
||
141 | B,0,B,B,0,B,F,F,F,F,B,0,B,B,0,B, |
||
142 | B,B,B,F,B,0,B,B,B,B,0,B,F,B,B,B, |
||
143 | F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F, |
||
144 | F,F,F,F,F,B,0,B,B,0,B,F,F,F,F,F, |
||
145 | F,F,F,F,F,B,0,B,B,0,B,F,F,F,F,F, |
||
146 | F,F,F,F,F,B,0,B,B,0,B,F,F,F,F,F, |
||
147 | F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F, |
||
148 | F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F, |
||
149 | F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F, |
||
150 | F,F,F,F,B,0,0,0,0,0,0,B,F,F,F,F, |
||
151 | F,F,F,B,0,0,0,0,0,0,0,0,B,F,F,F, |
||
152 | F,F,F,B,B,B,B,B,B,B,B,B,B,F,F,F, |
||
153 | }; |
||
154 | |||
155 | #undef B |
||
156 | #define B 0xff |
||
157 | |||
158 | /* bad mask */ |
||
159 | BYTE mybadbkg[16*16]= { |
||
160 | B,B,B,B,B,B,F,F,F,F,B,B,B,B,B,B, |
||
161 | B,0,0,0,0,B,F,F,F,F,B,0,0,0,0,B, |
||
162 | B,0,0,B,B,F,F,F,F,F,B,B,B,0,0,B, |
||
163 | B,0,B,0,B,F,F,F,F,F,F,B,0,B,0,B, |
||
164 | B,0,B,B,0,B,F,F,F,F,B,0,B,B,0,B, |
||
165 | B,B,B,F,B,0,B,B,B,B,0,B,F,B,B,B, |
||
166 | F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F, |
||
167 | F,F,F,F,F,B,0,B,B,0,B,F,F,F,F,F, |
||
168 | F,F,F,F,F,B,0,B,B,0,B,F,F,F,F,F, |
||
169 | F,F,F,F,F,B,0,B,B,0,B,F,F,F,F,F, |
||
170 | F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F, |
||
171 | F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F, |
||
172 | F,F,F,F,F,B,0,0,0,0,B,F,F,F,F,F, |
||
173 | F,F,F,F,B,0,0,0,0,0,0,B,F,F,F,F, |
||
174 | F,F,F,B,0,0,0,0,0,0,0,0,B,F,F,F, |
||
175 | F,F,F,B,B,B,B,B,B,B,B,B,B,F,F,F, |
||
176 | }; |
||
177 | |||
178 | /* very bad mask */ |
||
179 | BYTE myverybadbkg[16*16]= { |
||
180 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
181 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
182 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
183 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
184 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
185 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
186 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
187 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
188 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
189 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
190 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
191 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
192 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
193 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
194 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
195 | F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F, |
||
196 | }; |
||
197 | |||
198 | |||
199 | /*--------------------------------------------------------------*/ |
||
200 | /* Prints a grid to show task periods during execution */ |
||
201 | /*--------------------------------------------------------------*/ |
||
202 | |||
203 | void print_grid() |
||
204 | { |
||
205 | int i; |
||
206 | int a1, a2, a3; |
||
207 | int temp; |
||
208 | |||
209 | a1 = 0; |
||
210 | a2 = 0; |
||
211 | a3 = 0; |
||
212 | temp = 0; |
||
213 | |||
214 | grx_text(title, 0, 240-10 ,10, 0); |
||
215 | |||
216 | grx_line(OFFSET, lev[0], 639, lev[0], 5); |
||
217 | grx_line(OFFSET, lev[1], 639, lev[1], 5); |
||
218 | grx_line(OFFSET, lev[2], 639, lev[2], 5); |
||
219 | grx_text("T1", 0, lev[0]-8, 9, 0); |
||
220 | grx_text("T2", 0, lev[1]-8, 9, 0); |
||
221 | grx_text("T3", 0, lev[2]-8, 9, 0); |
||
222 | grx_text("MA", 0, LM, 8, 0); |
||
223 | grx_text("MO", 0, LMOUSE, 8, 0); |
||
224 | |||
225 | for (i = OFFSET; i < 640; i++) { |
||
226 | if (temp >= a1) { |
||
227 | grx_line(i, lev[0] - 1, i, lev[0] - 20, 3); |
||
228 | a1 += period[0]; |
||
229 | } |
||
230 | if (temp >= a2) { |
||
231 | grx_line(i, lev[1] - 1, i, lev[1] - 20, 3); |
||
232 | a2 += period[1]; |
||
233 | } |
||
234 | if (temp >= a3) { |
||
235 | grx_line(i, lev[2] - 1, i, lev[2] - 20, 3); |
||
236 | a3 += period[2]; |
||
237 | } |
||
238 | temp += tick/tscale; |
||
239 | } |
||
240 | } |
||
241 | |||
242 | /*--------------------------------------------------------------*/ |
||
243 | /* This function is called at system termination */ |
||
244 | /*--------------------------------------------------------------*/ |
||
245 | |||
246 | void my_end() |
||
247 | { |
||
248 | grx_close(); |
||
249 | } |
||
250 | |||
251 | /*--------------------------------------------------------------*/ |
||
252 | /* GENERIC PERIODIC PROCESS */ |
||
253 | /*--------------------------------------------------------------*/ |
||
254 | |||
255 | TASK color(int k) |
||
256 | { |
||
257 | int i; |
||
258 | DWORD x = OFFSET; |
||
259 | TIME t; |
||
260 | while ( x < 640L) { |
||
261 | for (i = 0; i < ptime[k]; i++) { |
||
262 | |||
263 | t = sys_gettime(NULL) / PERIODSCALE; |
||
264 | x = (t - starttime) + OFFSET; |
||
265 | if (x>=640) break; |
||
266 | sem_wait(&mutex); |
||
267 | grx_plot(x, lev[k] - 4, col[k]); |
||
268 | grx_plot(x, lev[k] - 5, col[k]); |
||
269 | grx_plot(x, lev[k] - 6, col[k]); |
||
270 | grx_plot(x, lev[k] - 7, col[k]); |
||
271 | sem_post(&mutex); |
||
272 | while (sys_gettime(NULL)/PERIODSCALE == t); |
||
273 | } |
||
274 | task_endcycle(); |
||
275 | } |
||
276 | return 0; |
||
277 | } |
||
278 | |||
279 | void my_mouse_handler(MOUSE_EVT *ev) |
||
280 | { |
||
281 | int x; |
||
282 | |||
283 | x = (sys_gettime(NULL)/PERIODSCALE - starttime) + OFFSET; |
||
284 | if (x>=640) return; |
||
285 | sem_wait(&mutex); |
||
286 | grx_plot(x, LMOUSE, 8); |
||
287 | sem_post(&mutex); |
||
288 | } |
||
289 | |||
290 | /*--------------------------------------------------------------*/ |
||
291 | /* MAIN PROCESS */ |
||
292 | /*--------------------------------------------------------------*/ |
||
293 | |||
294 | int main(int argc, char *argv[]) |
||
295 | { |
||
296 | int x = OFFSET; |
||
297 | |||
298 | MOUSE_PARMS mouse = BASE_MOUSE; |
||
299 | HARD_TASK_MODEL mouse_hard; |
||
300 | SOFT_TASK_MODEL mouse_soft; |
||
301 | NRT_TASK_MODEL mouse_nrt; |
||
302 | |||
303 | char c; |
||
304 | KEY_EVT emerg; |
||
305 | |||
306 | HARD_TASK_MODEL m_per; |
||
307 | int modenum; |
||
308 | |||
309 | if (argc>=3) |
||
310 | switch(*argv[2]) { |
||
311 | case 'h': |
||
312 | /* this is not correct, because it don't remember activations */ |
||
313 | hard_task_default_model(mouse_hard); |
||
314 | hard_task_def_mit(mouse_hard,DEN); |
||
315 | hard_task_def_wcet(mouse_hard,NUM); |
||
316 | hard_task_def_system(mouse_hard); |
||
317 | hard_task_def_nokill(mouse_hard); |
||
318 | hard_task_def_aperiodic(mouse_hard); |
||
319 | mouse_def_task(mouse,(TASK_MODEL *)&mouse_hard); |
||
320 | break; |
||
321 | case 's': |
||
322 | soft_task_default_model(mouse_soft); |
||
323 | soft_task_def_wcet(mouse_soft,NUM); |
||
324 | soft_task_def_met(mouse_soft,NUM); |
||
325 | soft_task_def_period(mouse_soft,DEN); |
||
326 | soft_task_def_system(mouse_soft); |
||
327 | soft_task_def_nokill(mouse_soft); |
||
328 | soft_task_def_aperiodic(mouse_soft); |
||
329 | mouse_def_task(mouse,(TASK_MODEL *)&mouse_soft); |
||
330 | break; |
||
331 | case 'n': |
||
332 | /* this is not correct, because it don't remember activations */ |
||
333 | nrt_task_default_model(mouse_nrt); |
||
334 | nrt_task_def_system(mouse_nrt); |
||
335 | nrt_task_def_nokill(mouse_nrt); |
||
336 | mouse_def_task(mouse,(TASK_MODEL *)&mouse_nrt); |
||
337 | break; |
||
338 | default: |
||
339 | argc=0; |
||
340 | break; |
||
341 | } |
||
342 | |||
343 | /* Serial mous on COM3 */ |
||
344 | mouse_def_ms(mouse,2); |
||
345 | |||
346 | if (argc>=4) { |
||
347 | period[0]=atoi(argv[3]); |
||
348 | if (period[0]<ptime[0]) period[0]=ptime[0]+5; |
||
349 | } |
||
350 | if (argc>=5) { |
||
351 | period[1]=atoi(argv[4]); |
||
352 | if (period[1]<ptime[1]) period[1]=ptime[1]+5; |
||
353 | } |
||
354 | if (argc>=6) { |
||
355 | period[2]=atoi(argv[5]); |
||
356 | if (period[2]<ptime[2]) period[2]=ptime[2]+5; |
||
357 | } |
||
358 | |||
359 | if (argc<2) { |
||
360 | cprintf("syntax: x testg <config> <mouse-task> [t1] [t2] [t3]\n"); |
||
361 | cprintf("where <config> can be:\n"); |
||
362 | cprintf("\t0 - EDF + CBS + RR\n"); |
||
363 | cprintf("\t1 - RM + PS ( bkg, U=1/16) + RR, no check Ulub < 0.69\n"); |
||
364 | cprintf("\t2 - RM + PS (nobkg, U=1/16) + RR, no check Ulub < 0.69\n"); |
||
365 | cprintf("\t3 - EDF + PS ( bkg, U=1/16) + RR\n"); |
||
366 | cprintf("\t4 - EDF + PS (nobkg, U=1/16) + RR\n"); |
||
367 | cprintf("\t5 - EDF + TBS( U=1/16) + RR\n"); |
||
368 | cprintf("\t6 - RM + DS ( bkg, U=1/16) + RR, no check Ulub < 0.69\n"); |
||
369 | cprintf("\t7 - RM + DS (nobkg, U=1/16) + RR, no check Ulub < 0.69\n"); |
||
370 | cprintf("\nwhere <mouse-task> can be:\n"); |
||
371 | cprintf("\th - Hard\n"); |
||
372 | cprintf("\ts - Soft (understimated wcet)\n"); |
||
373 | cprintf("\tn - NRT\n"); |
||
374 | sys_end(); |
||
375 | return -1; |
||
376 | } |
||
377 | |||
378 | if (grx_init() == -1) { |
||
1159 | pj | 379 | sys_shutdown_message("Error initing GraphLib!!!\n"); |
1120 | pj | 380 | sys_end(); |
381 | } |
||
382 | modenum = grx_getmode(640, 480, 8); |
||
383 | cprintf("Modenum :%d\n", modenum); |
||
384 | |||
385 | if (grx_setmode(modenum) == -1) { |
||
1159 | pj | 386 | sys_shutdown_message("No SetMode!!!\n"); |
1120 | pj | 387 | sys_end(); |
388 | } |
||
389 | |||
390 | /* this trick can be useful when debugging ... */ |
||
391 | //grx_close(); |
||
392 | |||
393 | |||
394 | |||
395 | print_grid(); |
||
396 | grx_box(DX*0,240,DX*1-1,479,GREEN); |
||
397 | grx_box(DX*1,240,DX*2-1,479,WHITE); |
||
398 | grx_box(DX*2,240,DX*3-1,479,RED); |
||
399 | grx_box(DX*3,240,DX*4-1,479,MAGENTA); |
||
400 | grx_box(DX*4,240,DX*5-1,479,BLACK); |
||
401 | |||
402 | |||
403 | sys_atrunlevel(my_end, NULL, RUNLEVEL_BEFORE_EXIT); |
||
404 | |||
405 | /* mutex */ |
||
406 | sem_init(&mutex,0,1); |
||
407 | |||
408 | /* keyboard */ |
||
409 | emerg.ascii = 'x'; |
||
410 | emerg.scan = KEY_X; |
||
411 | emerg.flag = ALTL_BIT; |
||
412 | keyb_hook(emerg,(void (*)(KEY_EVT *))sys_end); |
||
413 | keyb_getchar(); |
||
414 | |||
415 | /* mouse */ |
||
416 | mouse_init(&mouse); |
||
417 | mouse_limit(XMINLIMIT(640,480), |
||
418 | 240, |
||
419 | XMAXLIMIT(640,480), |
||
420 | YMAXLIMIT(640,480)); |
||
421 | mouse_position(320,280); |
||
422 | mouse_threshold(2); |
||
423 | //grx_setcolor(255,255,255,255); |
||
424 | mouse_grxshape(mycursor,mybkg); |
||
425 | mouse_grxcursor(ENABLE); |
||
426 | mouse_on(); |
||
427 | mouse_hook(my_mouse_handler); |
||
428 | |||
429 | /* hard task creation */ |
||
430 | |||
431 | hard_task_default_model(m_per); |
||
432 | hard_task_def_mit(m_per,period[0]*PERIODSCALE); |
||
433 | hard_task_def_wcet(m_per,ptime[0]*PERIODSCALE); |
||
434 | hard_task_def_group(m_per, 1); |
||
435 | //task_def_wcet(m, ptime[0] * sys_tick); |
||
436 | if (task_create("verde", color, &m_per, NULL) == -1) { |
||
1159 | pj | 437 | sys_shutdown_message("Edf.C(main) Could not create <green>:"); |
1120 | pj | 438 | sys_end(); |
439 | } |
||
440 | hard_task_def_arg(m_per, (void *)1); |
||
441 | hard_task_def_wcet(m_per, ptime[1]*PERIODSCALE); |
||
442 | hard_task_def_mit(m_per,period[1]*PERIODSCALE); |
||
443 | if (task_create("red", color, &m_per, NULL) == -1) { |
||
1159 | pj | 444 | sys_shutdown_message("Edf.C(main) Could not create <red>:"); |
1120 | pj | 445 | sys_end(); |
446 | } |
||
447 | hard_task_def_arg(m_per, (void *)2); |
||
448 | hard_task_def_wcet(m_per, ptime[2]*PERIODSCALE); |
||
449 | hard_task_def_mit(m_per,period[2]*PERIODSCALE); |
||
450 | if (task_create("yellow", color, &m_per, NULL) == -1) { |
||
1159 | pj | 451 | sys_shutdown_message("Edf.C(main) Could not create <yellow>:"); |
1120 | pj | 452 | sys_end(); |
453 | } |
||
454 | starttime = sys_gettime(NULL) / PERIODSCALE; |
||
455 | group_activate(1); |
||
456 | |||
457 | /* main loop */ |
||
458 | while (x < 640L) { |
||
459 | x = (sys_gettime(NULL)/PERIODSCALE - starttime) + OFFSET; |
||
460 | if (x>=640) break; |
||
461 | sem_wait(&mutex); |
||
462 | grx_plot(x, LM, 7); |
||
463 | sem_post(&mutex); |
||
464 | } |
||
465 | |||
466 | c = keyb_getchar(); |
||
467 | |||
468 | sys_end(); |
||
469 | return 0; |
||
470 | } |
||
471 | |||
472 | /*--------------------------------------------------------------*/ |