This source file includes following definitions.
- show_task
- show_state
- math_state_restore
- schedule
- sys_pause
- wake_up
- __sleep_on
- interruptible_sleep_on
- sleep_on
- ticks_to_floppy_on
- floppy_off
- do_floppy_timer
- add_timer
- do_timer
- sys_alarm
- sys_getpid
- sys_getppid
- sys_getuid
- sys_geteuid
- sys_getgid
- sys_getegid
- sys_nice
- sched_init
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/sched.h>
14 #include <linux/timer.h>
15 #include <linux/kernel.h>
16 #include <linux/sys.h>
17 #include <linux/fdreg.h>
18 #include <asm/system.h>
19 #include <asm/io.h>
20 #include <asm/segment.h>
21
22 #include <signal.h>
23 #include <errno.h>
24
25 #define _S(nr) (1<<((nr)-1))
26 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
27
28 void show_task(int nr,struct task_struct * p)
29 {
30 int i,j = 4096-sizeof(struct task_struct);
31
32 printk("%d: pid=%d, state=%d, father=%d, child=%d, ",nr,p->pid,
33 p->state, p->p_pptr->pid, p->p_cptr ? p->p_cptr->pid : -1);
34 i=0;
35 while (i<j && !((char *)(p+1))[i])
36 i++;
37 printk("%d/%d chars free in kstack\n\r",i,j);
38 printk(" PC=%08X.", *(1019 + (unsigned long *) p));
39 if (p->p_ysptr || p->p_osptr)
40 printk(" Younger sib=%d, older sib=%d\n\r",
41 p->p_ysptr ? p->p_ysptr->pid : -1,
42 p->p_osptr ? p->p_osptr->pid : -1);
43 else
44 printk("\n\r");
45 }
46
47 void show_state(void)
48 {
49 static int lock = 0;
50 int i;
51
52 cli();
53 if (lock) {
54 sti();
55 return;
56 }
57 lock = 1;
58 sti();
59 printk("\rTask-info:\n\r");
60 for (i=0 ; i<NR_TASKS ; i++)
61 if (task[i])
62 show_task(i,task[i]);
63 lock = 0;
64 }
65
66 #define LATCH (1193180/HZ)
67
68 extern void mem_use(void);
69
70 extern int timer_interrupt(void);
71 extern int system_call(void);
72
73 union task_union {
74 struct task_struct task;
75 char stack[PAGE_SIZE];
76 };
77
78 static union task_union init_task = {INIT_TASK,};
79
80 unsigned long volatile jiffies=0;
81 unsigned long startup_time=0;
82 int jiffies_offset = 0;
83
84
85
86
87
88 struct task_struct *current = &(init_task.task);
89 struct task_struct *last_task_used_math = NULL;
90
91 struct task_struct * task[NR_TASKS] = {&(init_task.task), };
92
93 long user_stack [ PAGE_SIZE>>2 ] ;
94
95 struct {
96 long * a;
97 short b;
98 } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
99
100
101
102
103 void math_state_restore()
104 {
105 if (last_task_used_math == current)
106 return;
107 __asm__("fwait");
108 if (last_task_used_math) {
109 __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
110 }
111 last_task_used_math=current;
112 if (current->used_math) {
113 __asm__("frstor %0"::"m" (current->tss.i387));
114 } else {
115 __asm__("fninit"::);
116 current->used_math=1;
117 }
118 }
119
120
121
122
123
124
125
126
127
128
129 void schedule(void)
130 {
131 int i,next,c;
132 struct task_struct ** p;
133
134
135
136 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
137 if (*p) {
138 if ((*p)->timeout && (*p)->timeout < jiffies)
139 if ((*p)->state == TASK_INTERRUPTIBLE) {
140 (*p)->timeout = 0;
141 (*p)->state = TASK_RUNNING;
142 }
143 if ((*p)->alarm && (*p)->alarm < jiffies) {
144 (*p)->signal |= (1<<(SIGALRM-1));
145 (*p)->alarm = 0;
146 }
147 if (((*p)->signal & ~(*p)->blocked) &&
148 (*p)->state==TASK_INTERRUPTIBLE)
149 (*p)->state=TASK_RUNNING;
150 }
151
152
153
154 while (1) {
155 c = -1;
156 next = 0;
157 i = NR_TASKS;
158 p = &task[NR_TASKS];
159 while (--i) {
160 if (!*--p)
161 continue;
162 if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
163 c = (*p)->counter, next = i;
164 }
165 if (c) break;
166 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
167 if (*p)
168 (*p)->counter = ((*p)->counter >> 1) +
169 (*p)->priority;
170 }
171 switch_to(next);
172 }
173
174 int sys_pause(void)
175 {
176 unsigned long old_blocked;
177 unsigned long mask;
178 struct sigaction * sa = current->sigaction;
179
180 old_blocked = current->blocked;
181 for (mask=1 ; mask ; sa++,mask += mask)
182 if (sa->sa_handler == SIG_IGN)
183 current->blocked |= mask;
184 current->state = TASK_INTERRUPTIBLE;
185 schedule();
186 current->blocked = old_blocked;
187 return -EINTR;
188 }
189
190 void wake_up(struct task_struct **p)
191 {
192 struct task_struct * wakeup_ptr, * tmp;
193
194 if (p && *p) {
195 wakeup_ptr = *p;
196 *p = NULL;
197 while (wakeup_ptr && wakeup_ptr != task[0]) {
198 if (wakeup_ptr->state == TASK_STOPPED)
199 printk("wake_up: TASK_STOPPED\n");
200 else if (wakeup_ptr->state == TASK_ZOMBIE)
201 printk("wake_up: TASK_ZOMBIE\n");
202 else
203 wakeup_ptr->state = TASK_RUNNING;
204 tmp = wakeup_ptr->next_wait;
205 wakeup_ptr->next_wait = task[0];
206 wakeup_ptr = tmp;
207 }
208 }
209 }
210
211 static inline void __sleep_on(struct task_struct **p, int state)
212 {
213 unsigned int flags;
214
215 if (!p)
216 return;
217 if (current == task[0])
218 panic("task[0] trying to sleep");
219 __asm__("pushfl ; popl %0":"=r" (flags));
220 current->next_wait = *p;
221 task[0]->next_wait = NULL;
222 *p = current;
223 current->state = state;
224 sti();
225 schedule();
226 if (current->next_wait != task[0])
227 wake_up(p);
228 current->next_wait = NULL;
229 __asm__("pushl %0 ; popfl"::"r" (flags));
230 }
231
232 void interruptible_sleep_on(struct task_struct **p)
233 {
234 __sleep_on(p,TASK_INTERRUPTIBLE);
235 }
236
237 void sleep_on(struct task_struct **p)
238 {
239 __sleep_on(p,TASK_UNINTERRUPTIBLE);
240 }
241
242
243
244
245
246
247 static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
248 static int mon_timer[4]={0,0,0,0};
249 static int moff_timer[4]={0,0,0,0};
250 unsigned char current_DOR = 0x0C;
251
252 int ticks_to_floppy_on(unsigned int nr)
253 {
254 extern unsigned char selected;
255 unsigned char mask = 0x10 << nr;
256
257 if (nr>3)
258 panic("floppy_on: nr>3");
259 moff_timer[nr]=10000;
260 cli();
261 mask |= current_DOR;
262 if (!selected) {
263 mask &= 0xFC;
264 mask |= nr;
265 }
266 if (mask != current_DOR) {
267 outb(mask,FD_DOR);
268 if ((mask ^ current_DOR) & 0xf0)
269 mon_timer[nr] = HZ/2;
270 else if (mon_timer[nr] < 2)
271 mon_timer[nr] = 2;
272 current_DOR = mask;
273 }
274 sti();
275 return mon_timer[nr];
276 }
277
278 void floppy_off(unsigned int nr)
279 {
280 moff_timer[nr]=3*HZ;
281 }
282
283 void do_floppy_timer(void)
284 {
285 int i;
286 unsigned char mask = 0x10;
287
288 for (i=0 ; i<4 ; i++,mask <<= 1) {
289 if (!(mask & current_DOR))
290 continue;
291 if (mon_timer[i]) {
292 if (!--mon_timer[i])
293 wake_up(i+wait_motor);
294 } else if (!moff_timer[i]) {
295 current_DOR &= ~mask;
296 outb(current_DOR,FD_DOR);
297 } else
298 moff_timer[i]--;
299 }
300 }
301
302 #define TIME_REQUESTS 64
303
304 static struct timer_list {
305 long jiffies;
306 void (*fn)();
307 struct timer_list * next;
308 } timer_list[TIME_REQUESTS] = { { 0, NULL, NULL }, };
309
310 static struct timer_list * next_timer = NULL;
311
312 void add_timer(long jiffies, void (*fn)(void))
313 {
314 struct timer_list * p;
315
316 if (!fn)
317 return;
318 cli();
319 if (jiffies <= 0)
320 (fn)();
321 else {
322 for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
323 if (!p->fn)
324 break;
325 if (p >= timer_list + TIME_REQUESTS)
326 panic("No more time requests free");
327 p->fn = fn;
328 p->jiffies = jiffies;
329 p->next = next_timer;
330 next_timer = p;
331 while (p->next && p->next->jiffies < p->jiffies) {
332 p->jiffies -= p->next->jiffies;
333 fn = p->fn;
334 p->fn = p->next->fn;
335 p->next->fn = fn;
336 jiffies = p->jiffies;
337 p->jiffies = p->next->jiffies;
338 p->next->jiffies = jiffies;
339 p = p->next;
340 }
341 }
342 sti();
343 }
344
345 unsigned long timer_active = 0;
346 struct timer_struct timer_table[32];
347
348 void do_timer(long cpl)
349 {
350 unsigned long mask;
351 struct timer_struct *tp = timer_table+0;
352
353 for (mask = 1 ; mask ; tp++,mask += mask) {
354 if (mask > timer_active)
355 break;
356 if (!(mask & timer_active))
357 continue;
358 if (tp->expires > jiffies)
359 continue;
360 timer_active &= ~mask;
361 tp->fn();
362 }
363
364 if (cpl)
365 current->utime++;
366 else
367 current->stime++;
368
369 if (next_timer) {
370 next_timer->jiffies--;
371 while (next_timer && next_timer->jiffies <= 0) {
372 void (*fn)(void);
373
374 fn = next_timer->fn;
375 next_timer->fn = NULL;
376 next_timer = next_timer->next;
377 (fn)();
378 }
379 }
380 if (current_DOR & 0xf0)
381 do_floppy_timer();
382 if ((--current->counter)>0) return;
383 current->counter=0;
384 if (!cpl) return;
385 schedule();
386 }
387
388 int sys_alarm(long seconds)
389 {
390 int old = current->alarm;
391
392 if (old)
393 old = (old - jiffies) / HZ;
394 current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
395 return (old);
396 }
397
398 int sys_getpid(void)
399 {
400 return current->pid;
401 }
402
403 int sys_getppid(void)
404 {
405 return current->p_pptr->pid;
406 }
407
408 int sys_getuid(void)
409 {
410 return current->uid;
411 }
412
413 int sys_geteuid(void)
414 {
415 return current->euid;
416 }
417
418 int sys_getgid(void)
419 {
420 return current->gid;
421 }
422
423 int sys_getegid(void)
424 {
425 return current->egid;
426 }
427
428 int sys_nice(long increment)
429 {
430 if (increment < 0 && !suser())
431 return -EPERM;
432 if (increment > current->priority)
433 increment = current->priority-1;
434 current->priority -= increment;
435 return 0;
436 }
437
438 void sched_init(void)
439 {
440 int i;
441 struct desc_struct * p;
442
443 if (sizeof(struct sigaction) != 16)
444 panic("Struct sigaction MUST be 16 bytes");
445 set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
446 set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
447 p = gdt+2+FIRST_TSS_ENTRY;
448 for(i=1 ; i<NR_TASKS ; i++) {
449 task[i] = NULL;
450 p->a=p->b=0;
451 p++;
452 p->a=p->b=0;
453 p++;
454 }
455
456 __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
457 ltr(0);
458 lldt(0);
459 outb_p(0x36,0x43);
460 outb_p(LATCH & 0xff , 0x40);
461 outb(LATCH >> 8 , 0x40);
462 set_intr_gate(0x20,&timer_interrupt);
463 outb(inb_p(0x21)&~0x01,0x21);
464 set_system_gate(0x80,&system_call);
465 }