zoukankan      html  css  js  c++  java
  • 方便查看 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 
  • 相关阅读:
    asp.net mvc 两级分类联动方法示例
    动手实践虚拟网络
    KVM 网络虚拟化基础
    LVM 类型的 Storage Pool
    KVM 存储虚拟化
    CPU 和内存虚拟化原理
    远程管理 KVM 虚机
    启动第一个 KVM 虚机
    准备 KVM 实验环境
    虚拟化
  • 原文地址:https://www.cnblogs.com/caesarxu/p/3261226.html
Copyright © 2011-2022 走看看