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