root/include/linux/sched.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. add_wait_queue
  2. remove_wait_queue
  3. select_wait
  4. down
  5. up
  6. _get_base
  7. get_limit

   1 #ifndef _LINUX_SCHED_H
   2 #define _LINUX_SCHED_H
   3 
   4 #define NEW_SWAP
   5 
   6 /*
   7  * define DEBUG if you want the wait-queues to have some extra
   8  * debugging code. It's not normally used, but might catch some
   9  * wait-queue coding errors.
  10  *
  11  *  #define DEBUG
  12  */
  13 
  14 #define HZ 100
  15 
  16 /*
  17  * System setup flags..
  18  */
  19 extern int hard_math;
  20 extern int x86;
  21 extern int ignore_irq13;
  22 extern int wp_works_ok;
  23 
  24 extern unsigned long intr_count;
  25 
  26 #define start_bh_atomic() \
  27 __asm__ __volatile__("incl _intr_count")
  28 
  29 #define end_bh_atomic() \
  30 __asm__ __volatile__("decl _intr_count")
  31 
  32 /*
  33  * Bus types (default is ISA, but people can check others with these..)
  34  * MCA_bus hardcoded to 0 for now.
  35  */
  36 extern int EISA_bus;
  37 #define MCA_bus 0
  38 
  39 #include <linux/tasks.h>
  40 #include <asm/system.h>
  41 
  42 /*
  43  * User space process size: 3GB. This is hardcoded into a few places,
  44  * so don't change it unless you know what you are doing.
  45  */
  46 #define TASK_SIZE       0xc0000000
  47 
  48 /*
  49  * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
  50  */
  51 #define IO_BITMAP_SIZE  32
  52 
  53 /*
  54  * These are the constant used to fake the fixed-point load-average
  55  * counting. Some notes:
  56  *  - 11 bit fractions expand to 22 bits by the multiplies: this gives
  57  *    a load-average precision of 10 bits integer + 11 bits fractional
  58  *  - if you want to count load-averages more often, you need more
  59  *    precision, or rounding will get you. With 2-second counting freq,
  60  *    the EXP_n values would be 1981, 2034 and 2043 if still using only
  61  *    11 bit fractions.
  62  */
  63 extern unsigned long avenrun[];         /* Load averages */
  64 
  65 #define FSHIFT          11              /* nr of bits of precision */
  66 #define FIXED_1         (1<<FSHIFT)     /* 1.0 as fixed-point */
  67 #define LOAD_FREQ       (5*HZ)          /* 5 sec intervals */
  68 #define EXP_1           1884            /* 1/exp(5sec/1min) as fixed-point */
  69 #define EXP_5           2014            /* 1/exp(5sec/5min) */
  70 #define EXP_15          2037            /* 1/exp(5sec/15min) */
  71 
  72 #define CALC_LOAD(load,exp,n) \
  73         load *= exp; \
  74         load += n*(FIXED_1-exp); \
  75         load >>= FSHIFT;
  76 
  77 #define CT_TO_SECS(x)   ((x) / HZ)
  78 #define CT_TO_USECS(x)  (((x) % HZ) * 1000000/HZ)
  79 
  80 #define FIRST_TASK task[0]
  81 #define LAST_TASK task[NR_TASKS-1]
  82 
  83 #include <linux/head.h>
  84 #include <linux/fs.h>
  85 #include <linux/mm.h>
  86 #include <linux/signal.h>
  87 #include <linux/time.h>
  88 #include <linux/param.h>
  89 #include <linux/resource.h>
  90 #include <linux/vm86.h>
  91 #include <linux/math_emu.h>
  92 
  93 #define TASK_RUNNING            0
  94 #define TASK_INTERRUPTIBLE      1
  95 #define TASK_UNINTERRUPTIBLE    2
  96 #define TASK_ZOMBIE             3
  97 #define TASK_STOPPED            4
  98 #define TASK_SWAPPING           5
  99 
 100 #ifndef NULL
 101 #define NULL ((void *) 0)
 102 #endif
 103 
 104 #ifdef __KERNEL__
 105 
 106 extern void sched_init(void);
 107 extern void show_state(void);
 108 extern void trap_init(void);
 109 
 110 asmlinkage void schedule(void);
 111 
 112 #endif /* __KERNEL__ */
 113 
 114 struct i387_hard_struct {
 115         long    cwd;
 116         long    swd;
 117         long    twd;
 118         long    fip;
 119         long    fcs;
 120         long    foo;
 121         long    fos;
 122         long    st_space[20];   /* 8*10 bytes for each FP-reg = 80 bytes */
 123 };
 124 
 125 struct i387_soft_struct {
 126         long    cwd;
 127         long    swd;
 128         long    twd;
 129         long    fip;
 130         long    fcs;
 131         long    foo;
 132         long    fos;
 133         long    top;
 134         struct fpu_reg  regs[8];        /* 8*16 bytes for each FP-reg = 128 bytes */
 135         unsigned char   lookahead;
 136         struct info     *info;
 137         unsigned long   entry_eip;
 138 };
 139 
 140 union i387_union {
 141         struct i387_hard_struct hard;
 142         struct i387_soft_struct soft;
 143 };
 144 
 145 struct tss_struct {
 146         unsigned short  back_link,__blh;
 147         unsigned long   esp0;
 148         unsigned short  ss0,__ss0h;
 149         unsigned long   esp1;
 150         unsigned short  ss1,__ss1h;
 151         unsigned long   esp2;
 152         unsigned short  ss2,__ss2h;
 153         unsigned long   cr3;
 154         unsigned long   eip;
 155         unsigned long   eflags;
 156         unsigned long   eax,ecx,edx,ebx;
 157         unsigned long   esp;
 158         unsigned long   ebp;
 159         unsigned long   esi;
 160         unsigned long   edi;
 161         unsigned short  es, __esh;
 162         unsigned short  cs, __csh;
 163         unsigned short  ss, __ssh;
 164         unsigned short  ds, __dsh;
 165         unsigned short  fs, __fsh;
 166         unsigned short  gs, __gsh;
 167         unsigned short  ldt, __ldth;
 168         unsigned short  trace, bitmap;
 169         unsigned long   io_bitmap[IO_BITMAP_SIZE+1];
 170         unsigned long   tr;
 171         unsigned long   cr2, trap_no, error_code;
 172         union i387_union i387;
 173 };
 174 
 175 struct task_struct {
 176 /* these are hardcoded - don't touch */
 177         volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
 178         long counter;
 179         long priority;
 180         unsigned long signal;
 181         unsigned long blocked;  /* bitmap of masked signals */
 182         unsigned long flags;    /* per process flags, defined below */
 183         int errno;
 184         int debugreg[8];  /* Hardware debugging registers */
 185 /* various fields */
 186         struct task_struct *next_task, *prev_task;
 187         struct sigaction sigaction[32];
 188         unsigned long saved_kernel_stack;
 189         unsigned long kernel_stack_page;
 190         int exit_code, exit_signal;
 191         int elf_executable:1;
 192         int dumpable:1;
 193         int swappable:1;
 194         int did_exec:1;
 195         unsigned long start_code,end_code,end_data,start_brk,brk,start_stack,start_mmap;
 196         unsigned long arg_start, arg_end, env_start, env_end;
 197         int pid,pgrp,session,leader;
 198         int     groups[NGROUPS];
 199         /* 
 200          * pointers to (original) parent process, youngest child, younger sibling,
 201          * older sibling, respectively.  (p->father can be replaced with 
 202          * p->p_pptr->pid)
 203          */
 204         struct task_struct *p_opptr,*p_pptr, *p_cptr, *p_ysptr, *p_osptr;
 205         struct wait_queue *wait_chldexit;       /* for wait4() */
 206         /*
 207          * For ease of programming... Normal sleeps don't need to
 208          * keep track of a wait-queue: every task has an entry of its own
 209          */
 210         unsigned short uid,euid,suid;
 211         unsigned short gid,egid,sgid;
 212         unsigned long timeout;
 213         unsigned long it_real_value, it_prof_value, it_virt_value;
 214         unsigned long it_real_incr, it_prof_incr, it_virt_incr;
 215         long utime,stime,cutime,cstime,start_time;
 216         unsigned long min_flt, maj_flt;
 217         unsigned long cmin_flt, cmaj_flt;
 218         struct rlimit rlim[RLIM_NLIMITS]; 
 219         unsigned short used_math;
 220         unsigned short rss;     /* number of resident pages */
 221         char comm[16];
 222 /* virtual 86 mode stuff */
 223         struct vm86_struct * vm86_info;
 224         unsigned long screen_bitmap;
 225         unsigned long v86flags, v86mask, v86mode;
 226 /* file system info */
 227         int link_count;
 228         int tty;                /* -1 if no tty, so it must be signed */
 229         unsigned short umask;
 230         struct inode * pwd;
 231         struct inode * root;
 232         struct inode * executable;
 233         struct vm_area_struct * mmap;
 234         struct shm_desc *shm;
 235         struct sem_undo *semun;
 236         struct file * filp[NR_OPEN];
 237         fd_set close_on_exec;
 238 /* ldt for this task - used by Wine.  If NULL, default_ldt is used */
 239         struct desc_struct *ldt;
 240 /* tss for this task */
 241         struct tss_struct tss;
 242 #ifdef NEW_SWAP
 243         unsigned long old_maj_flt;      /* old value of maj_flt */
 244         unsigned long dec_flt;          /* page fault count of the last time */
 245         unsigned long swap_cnt;         /* number of pages to swap on next pass */
 246         short swap_table;               /* current page table */
 247         short swap_page;                /* current page */
 248 #endif NEW_SWAP
 249         struct vm_area_struct *stk_vma;
 250 };
 251 
 252 /*
 253  * Per process flags
 254  */
 255 #define PF_ALIGNWARN    0x00000001      /* Print alignment warning msgs */
 256                                         /* Not implemented yet, only for 486*/
 257 #define PF_PTRACED      0x00000010      /* set if ptrace (0) has been called. */
 258 #define PF_TRACESYS     0x00000020      /* tracing system calls */
 259 
 260 /*
 261  * cloning flags:
 262  */
 263 #define CSIGNAL         0x000000ff      /* signal mask to be sent at exit */
 264 #define COPYVM          0x00000100      /* set if VM copy desired (like normal fork()) */
 265 #define COPYFD          0x00000200      /* set if fd's should be copied, not shared (NI) */
 266 
 267 /*
 268  *  INIT_TASK is used to set up the first task table, touch at
 269  * your own risk!. Base=0, limit=0x1fffff (=2MB)
 270  */
 271 #define INIT_TASK \
 272 /* state etc */ { 0,15,15,0,0,0,0, \
 273 /* debugregs */ { 0, },            \
 274 /* schedlink */ &init_task,&init_task, \
 275 /* signals */   {{ 0, },}, \
 276 /* stack */     0,(unsigned long) &init_kernel_stack, \
 277 /* ec,brk... */ 0,0,0,0,0,0,0,0,0,0,0,0,0, \
 278 /* argv.. */    0,0,0,0, \
 279 /* pid etc.. */ 0,0,0,0, \
 280 /* suppl grps*/ {NOGROUP,}, \
 281 /* proc links*/ &init_task,&init_task,NULL,NULL,NULL,NULL, \
 282 /* uid etc */   0,0,0,0,0,0, \
 283 /* timeout */   0,0,0,0,0,0,0,0,0,0,0,0, \
 284 /* min_flt */   0,0,0,0, \
 285 /* rlimits */   { {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},  \
 286                   {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},  \
 287                   {       0, LONG_MAX}, {LONG_MAX, LONG_MAX}}, \
 288 /* math */      0, \
 289 /* rss */       2, \
 290 /* comm */      "swapper", \
 291 /* vm86_info */ NULL, 0, 0, 0, 0, \
 292 /* fs info */   0,-1,0022,NULL,NULL,NULL,NULL, \
 293 /* ipc */       NULL, NULL, \
 294 /* filp */      {NULL,}, \
 295 /* cloe */      {{ 0, }}, \
 296 /* ldt */       NULL, \
 297 /*tss*/ {0,0, \
 298          sizeof(init_kernel_stack) + (long) &init_kernel_stack, KERNEL_DS, 0, \
 299          0,0,0,0,0,0, \
 300          (long) &swapper_pg_dir, \
 301          0,0,0,0,0,0,0,0,0,0, \
 302          USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0,USER_DS,0, \
 303          _LDT(0),0, \
 304          0, 0x8000, \
 305 /* ioperm */    {~0, }, \
 306          _TSS(0), 0, 0,0, \
 307 /* 387 state */ { { 0, }, } \
 308         } \
 309 }
 310 
 311 extern struct task_struct init_task;
 312 extern struct task_struct *task[NR_TASKS];
 313 extern struct task_struct *last_task_used_math;
 314 extern struct task_struct *current;
 315 extern unsigned long volatile jiffies;
 316 extern unsigned long itimer_ticks;
 317 extern unsigned long itimer_next;
 318 extern struct timeval xtime;
 319 extern int need_resched;
 320 
 321 #define CURRENT_TIME (xtime.tv_sec)
 322 
 323 extern void sleep_on(struct wait_queue ** p);
 324 extern void interruptible_sleep_on(struct wait_queue ** p);
 325 extern void wake_up(struct wait_queue ** p);
 326 extern void wake_up_interruptible(struct wait_queue ** p);
 327 
 328 extern void notify_parent(struct task_struct * tsk);
 329 extern int send_sig(unsigned long sig,struct task_struct * p,int priv);
 330 extern int in_group_p(gid_t grp);
 331 
 332 extern int request_irq(unsigned int irq,void (*handler)(int));
 333 extern void free_irq(unsigned int irq);
 334 extern int irqaction(unsigned int irq,struct sigaction * sa);
 335 
 336 /*
 337  * Entry into gdt where to find first TSS. GDT layout:
 338  *   0 - nul
 339  *   1 - kernel code segment
 340  *   2 - kernel data segment
 341  *   3 - user code segment
 342  *   4 - user data segment
 343  * ...
 344  *   8 - TSS #0
 345  *   9 - LDT #0
 346  *  10 - TSS #1
 347  *  11 - LDT #1
 348  */
 349 #define FIRST_TSS_ENTRY 8
 350 #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
 351 #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
 352 #define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
 353 #define load_TR(n) __asm__("ltr %%ax": /* no output */ :"a" (_TSS(n)))
 354 #define load_ldt(n) __asm__("lldt %%ax": /* no output */ :"a" (_LDT(n)))
 355 #define store_TR(n) \
 356 __asm__("str %%ax\n\t" \
 357         "subl %2,%%eax\n\t" \
 358         "shrl $4,%%eax" \
 359         :"=a" (n) \
 360         :"0" (0),"i" (FIRST_TSS_ENTRY<<3))
 361 /*
 362  *      switch_to(n) should switch tasks to task nr n, first
 363  * checking that n isn't the current task, in which case it does nothing.
 364  * This also clears the TS-flag if the task we switched to has used
 365  * tha math co-processor latest.
 366  */
 367 #define switch_to(tsk) \
 368 __asm__("cli\n\t" \
 369         "xchgl %%ecx,_current\n\t" \
 370         "ljmp %0\n\t" \
 371         "sti\n\t" \
 372         "cmpl %%ecx,_last_task_used_math\n\t" \
 373         "jne 1f\n\t" \
 374         "clts\n" \
 375         "1:" \
 376         : /* no output */ \
 377         :"m" (*(((char *)&tsk->tss.tr)-4)), \
 378          "c" (tsk) \
 379         :"cx")
 380 
 381 #define _set_base(addr,base) \
 382 __asm__("movw %%dx,%0\n\t" \
 383         "rorl $16,%%edx\n\t" \
 384         "movb %%dl,%1\n\t" \
 385         "movb %%dh,%2" \
 386         : /* no output */ \
 387         :"m" (*((addr)+2)), \
 388          "m" (*((addr)+4)), \
 389          "m" (*((addr)+7)), \
 390          "d" (base) \
 391         :"dx")
 392 
 393 #define _set_limit(addr,limit) \
 394 __asm__("movw %%dx,%0\n\t" \
 395         "rorl $16,%%edx\n\t" \
 396         "movb %1,%%dh\n\t" \
 397         "andb $0xf0,%%dh\n\t" \
 398         "orb %%dh,%%dl\n\t" \
 399         "movb %%dl,%1" \
 400         : /* no output */ \
 401         :"m" (*(addr)), \
 402          "m" (*((addr)+6)), \
 403          "d" (limit) \
 404         :"dx")
 405 
 406 #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
 407 #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
 408 
 409 /*
 410  * The wait-queues are circular lists, and you have to be *very* sure
 411  * to keep them correct. Use only these two functions to add/remove
 412  * entries in the queues.
 413  */
 414 extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 415 {
 416         unsigned long flags;
 417 
 418 #ifdef DEBUG
 419         if (wait->next) {
 420                 unsigned long pc;
 421                 __asm__ __volatile__("call 1f\n"
 422                         "1:\tpopl %0":"=r" (pc));
 423                 printk("add_wait_queue (%08x): wait->next = %08x\n",pc,(unsigned long) wait->next);
 424         }
 425 #endif
 426         save_flags(flags);
 427         cli();
 428         if (!*p) {
 429                 wait->next = wait;
 430                 *p = wait;
 431         } else {
 432                 wait->next = (*p)->next;
 433                 (*p)->next = wait;
 434         }
 435         restore_flags(flags);
 436 }
 437 
 438 extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 439 {
 440         unsigned long flags;
 441         struct wait_queue * tmp;
 442 #ifdef DEBUG
 443         unsigned long ok = 0;
 444 #endif
 445 
 446         save_flags(flags);
 447         cli();
 448         if ((*p == wait) &&
 449 #ifdef DEBUG
 450             (ok = 1) &&
 451 #endif
 452             ((*p = wait->next) == wait)) {
 453                 *p = NULL;
 454         } else {
 455                 tmp = wait;
 456                 while (tmp->next != wait) {
 457                         tmp = tmp->next;
 458 #ifdef DEBUG
 459                         if (tmp == *p)
 460                                 ok = 1;
 461 #endif
 462                 }
 463                 tmp->next = wait->next;
 464         }
 465         wait->next = NULL;
 466         restore_flags(flags);
 467 #ifdef DEBUG
 468         if (!ok) {
 469                 printk("removed wait_queue not on list.\n");
 470                 printk("list = %08x, queue = %08x\n",(unsigned long) p, (unsigned long) wait);
 471                 __asm__("call 1f\n1:\tpopl %0":"=r" (ok));
 472                 printk("eip = %08x\n",ok);
 473         }
 474 #endif
 475 }
 476 
 477 extern inline void select_wait(struct wait_queue ** wait_address, select_table * p)
     /* [previous][next][first][last][top][bottom][index][help] */
 478 {
 479         struct select_table_entry * entry;
 480 
 481         if (!p || !wait_address)
 482                 return;
 483         if (p->nr >= __MAX_SELECT_TABLE_ENTRIES)
 484                 return;
 485         entry = p->entry + p->nr;
 486         entry->wait_address = wait_address;
 487         entry->wait.task = current;
 488         entry->wait.next = NULL;
 489         add_wait_queue(wait_address,&entry->wait);
 490         p->nr++;
 491 }
 492 
 493 extern void __down(struct semaphore * sem);
 494 
 495 /*
 496  * These are not yet interrupt-safe
 497  */
 498 extern inline void down(struct semaphore * sem)
     /* [previous][next][first][last][top][bottom][index][help] */
 499 {
 500         if (sem->count <= 0)
 501                 __down(sem);
 502         sem->count--;
 503 }
 504 
 505 extern inline void up(struct semaphore * sem)
     /* [previous][next][first][last][top][bottom][index][help] */
 506 {
 507         sem->count++;
 508         wake_up(&sem->wait);
 509 }       
 510 
 511 static inline unsigned long _get_base(char * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 512 {
 513         unsigned long __base;
 514         __asm__("movb %3,%%dh\n\t"
 515                 "movb %2,%%dl\n\t"
 516                 "shll $16,%%edx\n\t"
 517                 "movw %1,%%dx"
 518                 :"=&d" (__base)
 519                 :"m" (*((addr)+2)),
 520                  "m" (*((addr)+4)),
 521                  "m" (*((addr)+7)));
 522         return __base;
 523 }
 524 
 525 #define get_base(ldt) _get_base( ((char *)&(ldt)) )
 526 
 527 static inline unsigned long get_limit(unsigned long segment)
     /* [previous][next][first][last][top][bottom][index][help] */
 528 {
 529         unsigned long __limit;
 530         __asm__("lsll %1,%0"
 531                 :"=r" (__limit):"r" (segment));
 532         return __limit+1;
 533 }
 534 
 535 #define REMOVE_LINKS(p) do { unsigned long flags; \
 536         save_flags(flags) ; cli(); \
 537         (p)->next_task->prev_task = (p)->prev_task; \
 538         (p)->prev_task->next_task = (p)->next_task; \
 539         restore_flags(flags); \
 540         if ((p)->p_osptr) \
 541                 (p)->p_osptr->p_ysptr = (p)->p_ysptr; \
 542         if ((p)->p_ysptr) \
 543                 (p)->p_ysptr->p_osptr = (p)->p_osptr; \
 544         else \
 545                 (p)->p_pptr->p_cptr = (p)->p_osptr; \
 546         } while (0)
 547 
 548 #define SET_LINKS(p) do { unsigned long flags; \
 549         save_flags(flags); cli(); \
 550         (p)->next_task = &init_task; \
 551         (p)->prev_task = init_task.prev_task; \
 552         init_task.prev_task->next_task = (p); \
 553         init_task.prev_task = (p); \
 554         restore_flags(flags); \
 555         (p)->p_ysptr = NULL; \
 556         if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \
 557                 (p)->p_osptr->p_ysptr = p; \
 558         (p)->p_pptr->p_cptr = p; \
 559         } while (0)
 560 
 561 #define for_each_task(p) \
 562         for (p = &init_task ; (p = p->next_task) != &init_task ; )
 563 
 564 /*
 565  * This is the ldt that every process will get unless we need
 566  * something other than this.
 567  */
 568 extern struct desc_struct default_ldt;
 569 
 570 /* This special macro can be used to load a debugging register */
 571 
 572 #define loaddebug(register) \
 573                 __asm__("movl %0,%%edx\n\t" \
 574                         "movl %%edx,%%db" #register "\n\t" \
 575                         : /* no output */ \
 576                         :"m" (current->debugreg[register]) \
 577                         :"dx");
 578 
 579 #endif

/* [previous][next][first][last][top][bottom][index][help] */