方便查看 linux/kernel/sched.c

  1 /*
  2  *  linux/kernel/sched.c
  3  *
  4  *  (C) 1991  Linus Torvalds
  5  */
  6 
  7 /*
  8  * 'sched.c' is the main kernel file. It contains scheduling primitives
  9  * (sleep_on, wakeup, schedule etc) as well as a number of simple system
 10  * call functions (type getpid(), which just extracts a field from
 11  * current-task
 12  */
 13 #include <linux/sched.h>
 14 #include <linux/kernel.h>
 15 #include <linux/sys.h>
 16 #include <linux/fdreg.h>
 17 #include <asm/system.h>
 18 #include <asm/io.h>
 19 #include <asm/segment.h>
 20 
 21 #include <signal.h>
 22 
 23 #define _S(nr) (1<<((nr)-1))
 24 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 25 
 26 void show_task(int nr,struct task_struct * p)
 27 {
 28         int i,j = 4096-sizeof(struct task_struct);
 29 
 30         printk("%d: pid=%d, state=%d, ",nr,p->pid,p->state);
 31         i=0;
 32         while (i<j && !((char *)(p+1))[i])
 33                 i++;
 34         printk("%d (of %d) chars free in kernel stack

",i,j);
 35 }
 36 
 37 void show_stat(void)
 38 {
 39         int i;
 40 
 41         for (i=0;i<NR_TASKS;i++)
 42                 if (task[i])
 43                         show_task(i,task[i]);
 44 }
 45 
 46 #define LATCH (1193180/HZ)
 47 
 48 extern void mem_use(void);
 49 
 50 extern int timer_interrupt(void);
 51 extern int system_call(void);
 52 
 53 union task_union {
 54         struct task_struct task;
 55         char stack[PAGE_SIZE];
 56 };
 57 
 58 static union task_union init_task = {INIT_TASK,};
 59 
 60 long volatile jiffies=0;
 61 long startup_time=0;
 62 struct task_struct *current = &(init_task.task);
 63 struct task_struct *last_task_used_math = NULL;
 64 
 65 struct task_struct * task[NR_TASKS] = {&(init_task.task), };
 66 
 67 long user_stack [ PAGE_SIZE>>2 ] ;
 68 
 69 struct {
 70         long * a;
 71         short b;
 72         } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
 73 /*
 74  *  'math_state_restore()' saves the current math information in the
 75  * old math state array, and gets the new ones from the current task
 76  */
 77 void math_state_restore()
 78 {
 79         if (last_task_used_math == current)
 80                 return;
 81         __asm__("fwait");
 82         if (last_task_used_math) {
 83                 __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
 84         }
 85         last_task_used_math=current;
 86         if (current->used_math) {
 87                 __asm__("frstor %0"::"m" (current->tss.i387));
 88         } else {
 89                 __asm__("fninit"::);
 90                 current->used_math=1;
 91         }
 92 }
 93 
 94 /*
 95  *  'schedule()' is the scheduler function. This is GOOD CODE! There
 96  * probably won't be any reason to change this, as it should work well
 97  * in all circumstances (ie gives IO-bound processes good response etc).
 98  * The one thing you might take a look at is the signal-handler code here.
 99  *
100  *   NOTE!!  Task 0 is the 'idle' task, which gets called when no other
101  * tasks can run. It can not be killed, and it cannot sleep. The 'state'
102  * information in task[0] is never used.
103  */
104 void schedule(void)
105 {
106         int i,next,c;
107         struct task_struct ** p;
108 
109 /* check alarm, wake up any interruptible tasks that have got a signal */
110 
111         for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
112                 if (*p) {
113                         if ((*p)->alarm && (*p)->alarm < jiffies) {
114                                         (*p)->signal |= (1<<(SIGALRM-1));
115                                         (*p)->alarm = 0;
116                                 }
117                         if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
118                         (*p)->state==TASK_INTERRUPTIBLE)
119                                 (*p)->state=TASK_RUNNING;
120                 }
121 
122 /* this is the scheduler proper: */
123 
124         while (1) {
125                 c = -1;
126                 next = 0;
127                 i = NR_TASKS;
128                 p = &task[NR_TASKS];
129                 while (--i) {
130                         if (!*--p)
131                                 continue;
132                         if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
133                                 c = (*p)->counter, next = i;
134                 }
135                 if (c) break;
136                 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
137                         if (*p)
138                                 (*p)->counter = ((*p)->counter >> 1) +
139                                                 (*p)->priority;
140         }
141         switch_to(next);
142 }
143 
144 int sys_pause(void)
145 {
146         current->state = TASK_INTERRUPTIBLE;
147         schedule();
148         return 0;
149 }
150 
151 void sleep_on(struct task_struct **p)
152 {
153         struct task_struct *tmp;
154 
155         if (!p)
156                 return;
157         if (current == &(init_task.task))
158                 panic("task[0] trying to sleep");
159         tmp = *p;
160         *p = current;
161         current->state = TASK_UNINTERRUPTIBLE;
162         schedule();
163         if (tmp)
164                 tmp->state=0;
165 }
166 
167 void interruptible_sleep_on(struct task_struct **p)
168 {
169         struct task_struct *tmp;
170 
171         if (!p)
172                 return;
173         if (current == &(init_task.task))
174                 panic("task[0] trying to sleep");
175         tmp=*p;
176         *p=current;
177 repeat: current->state = TASK_INTERRUPTIBLE;
178         schedule();
179         if (*p && *p != current) {
180                 (**p).state=0;
181                 goto repeat;
182         }
183         *p=NULL;
184         if (tmp)
185                 tmp->state=0;
186 }
187 
188 void wake_up(struct task_struct **p)
189 {
190         if (p && *p) {
191                 (**p).state=0;
192                 *p=NULL;
193         }
194 }
195 
196 /*
197  * OK, here are some floppy things that shouldn't be in the kernel
198  * proper. They are here because the floppy needs a timer, and this
199  * was the easiest way of doing it.
200  */
201 static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
202 static int  mon_timer[4]={0,0,0,0};
203 static int moff_timer[4]={0,0,0,0};
204 unsigned char current_DOR = 0x0C;
205 
206 int ticks_to_floppy_on(unsigned int nr)
207 {
208         extern unsigned char selected;
209         unsigned char mask = 0x10 << nr;
210 
211         if (nr>3)
212                 panic("floppy_on: nr>3");
213         moff_timer[nr]=10000;           /* 100 s = very big :-) */
214         cli();                          /* use floppy_off to turn it off */
215         mask |= current_DOR;
216         if (!selected) {
217                 mask &= 0xFC;
218                 mask |= nr;
219         }
220         if (mask != current_DOR) {
221                 outb(mask,FD_DOR);
222                 if ((mask ^ current_DOR) & 0xf0)
223                         mon_timer[nr] = HZ/2;
224                 else if (mon_timer[nr] < 2)
225                         mon_timer[nr] = 2;
226                 current_DOR = mask;
227         }
228         sti();
229         return mon_timer[nr];
230 }
231 
232 void floppy_on(unsigned int nr)
233 {
234         cli();
235         while (ticks_to_floppy_on(nr))
236                 sleep_on(nr+wait_motor);
237         sti();
238 }
239 
240 void floppy_off(unsigned int nr)
241 {
242         moff_timer[nr]=3*HZ;
243 }
244 
245 void do_floppy_timer(void)
246 {
247         int i;
248         unsigned char mask = 0x10;
249 
250         for (i=0 ; i<4 ; i++,mask <<= 1) {
251                 if (!(mask & current_DOR))
252                         continue;
253                 if (mon_timer[i]) {
254                         if (!--mon_timer[i])
255                                 wake_up(i+wait_motor);
256                 } else if (!moff_timer[i]) {
257                         current_DOR &= ~mask;
258                         outb(current_DOR,FD_DOR);
259                 } else
260                         moff_timer[i]--;
261         }
262 }
263 
264 #define TIME_REQUESTS 64
265 
266 static struct timer_list {
267         long jiffies;
268         void (*fn)();
269         struct timer_list * next;
270 } timer_list[TIME_REQUESTS], * next_timer = NULL;
271 
272 void add_timer(long jiffies, void (*fn)(void))
273 {
274         struct timer_list * p;
275 
276         if (!fn)
277                 return;
278         cli();
279         if (jiffies <= 0)
280                 (fn)();
281         else {
282                 for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
283                         if (!p->fn)
284                                 break;
285                 if (p >= timer_list + TIME_REQUESTS)
286                         panic("No more time requests free");
287                 p->fn = fn;
288                 p->jiffies = jiffies;
289                 p->next = next_timer;
290                 next_timer = p;
291                 while (p->next && p->next->jiffies < p->jiffies) {
292                         p->jiffies -= p->next->jiffies;
293                         fn = p->fn;
294                         p->fn = p->next->fn;
295                         p->next->fn = fn;
296                         jiffies = p->jiffies;
297                         p->jiffies = p->next->jiffies;
298                         p->next->jiffies = jiffies;
299                         p = p->next;
300                 }
301         }
302         sti();
303 }
304 
305 void do_timer(long cpl)
306 {
307         extern int beepcount;
308         extern void sysbeepstop(void);
309 
310         if (beepcount)
311                 if (!--beepcount)
312                         sysbeepstop();
313 
314         if (cpl)
315                 current->utime++;
316         else
317                 current->stime++;
318 
319         if (next_timer) {
320                 next_timer->jiffies--;
321                 while (next_timer && next_timer->jiffies <= 0) {
322                         void (*fn)(void);
323                         
324                         fn = next_timer->fn;
325                         next_timer->fn = NULL;
326                         next_timer = next_timer->next;
327                         (fn)();
328                 }
329         }
330         if (current_DOR & 0xf0)
331                 do_floppy_timer();
332         if ((--current->counter)>0) return;
333         current->counter=0;
334         if (!cpl) return;
335         schedule();
336 }
337 
338 int sys_alarm(long seconds)
339 {
340         int old = current->alarm;
341 
342         if (old)
343                 old = (old - jiffies) / HZ;
344         current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
345         return (old);
346 }
347 
348 int sys_getpid(void)
349 {
350         return current->pid;
351 }
352 
353 int sys_getppid(void)
354 {
355         return current->father;
356 }
357 
358 int sys_getuid(void)
359 {
360         return current->uid;
361 }
362 
363 int sys_geteuid(void)
364 {
365         return current->euid;
366 }
367 
368 int sys_getgid(void)
369 {
370         return current->gid;
371 }
372 
373 int sys_getegid(void)
374 {
375         return current->egid;
376 }
377 
378 int sys_nice(long increment)
379 {
380         if (current->priority-increment>0)
381                 current->priority -= increment;
382         return 0;
383 }
384 
385 void sched_init(void)
386 {
387         int i;
388         struct desc_struct * p;
389 
390         if (sizeof(struct sigaction) != 16)
391                 panic("Struct sigaction MUST be 16 bytes");
392         set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
393         set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
394         p = gdt+2+FIRST_TSS_ENTRY;
395         for(i=1;i<NR_TASKS;i++) {
396                 task[i] = NULL;
397                 p->a=p->b=0;
398                 p++;
399                 p->a=p->b=0;
400                 p++;
401         }
402 /* Clear NT, so that we won't have troubles with that later on */
403         __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
404         ltr(0);
405         lldt(0);
406         outb_p(0x36,0x43);              /* binary, mode 3, LSB/MSB, ch 0 */
407         outb_p(LATCH & 0xff , 0x40);    /* LSB */
408         outb(LATCH >> 8 , 0x40);        /* MSB */
409         set_intr_gate(0x20,&timer_interrupt);
410         outb(inb_p(0x21)&~0x01,0x21);
411         set_system_gate(0x80,&system_call);
412 }
413 
原文地址:https://www.cnblogs.com/caesarxu/p/3261226.html