linux-old/include/linux/sched.h
<<
>>
Prefs
   1#ifndef _LINUX_SCHED_H
   2#define _LINUX_SCHED_H
   3
   4#include <asm/param.h>  /* for HZ */
   5
   6extern unsigned long event;
   7
   8#include <linux/binfmts.h>
   9#include <linux/personality.h>
  10#include <linux/tasks.h>
  11#include <linux/kernel.h>
  12#include <linux/types.h>
  13#include <linux/times.h>
  14#include <linux/timex.h>
  15
  16#include <asm/system.h>
  17#include <asm/semaphore.h>
  18#include <asm/page.h>
  19
  20#include <linux/smp.h>
  21#include <linux/tty.h>
  22#include <linux/sem.h>
  23#include <linux/signal.h>
  24#include <linux/securebits.h>
  25
  26/*
  27 * cloning flags:
  28 */
  29#define CSIGNAL         0x000000ff      /* signal mask to be sent at exit */
  30#define CLONE_VM        0x00000100      /* set if VM shared between processes */
  31#define CLONE_FS        0x00000200      /* set if fs info shared between processes */
  32#define CLONE_FILES     0x00000400      /* set if open files shared between processes */
  33#define CLONE_SIGHAND   0x00000800      /* set if signal handlers shared */
  34#define CLONE_PID       0x00001000      /* set if pid shared */
  35#define CLONE_PTRACE    0x00002000      /* set if we want to let tracing continue on the child too */
  36#define CLONE_VFORK     0x00004000      /* set if the parent wants the child to wake it up on mm_release */
  37
  38/*
  39 * These are the constant used to fake the fixed-point load-average
  40 * counting. Some notes:
  41 *  - 11 bit fractions expand to 22 bits by the multiplies: this gives
  42 *    a load-average precision of 10 bits integer + 11 bits fractional
  43 *  - if you want to count load-averages more often, you need more
  44 *    precision, or rounding will get you. With 2-second counting freq,
  45 *    the EXP_n values would be 1981, 2034 and 2043 if still using only
  46 *    11 bit fractions.
  47 */
  48extern unsigned long avenrun[];         /* Load averages */
  49
  50#define FSHIFT          11              /* nr of bits of precision */
  51#define FIXED_1         (1<<FSHIFT)     /* 1.0 as fixed-point */
  52#define LOAD_FREQ       (5*HZ)          /* 5 sec intervals */
  53#define EXP_1           1884            /* 1/exp(5sec/1min) as fixed-point */
  54#define EXP_5           2014            /* 1/exp(5sec/5min) */
  55#define EXP_15          2037            /* 1/exp(5sec/15min) */
  56
  57#define CALC_LOAD(load,exp,n) \
  58        load *= exp; \
  59        load += n*(FIXED_1-exp); \
  60        load >>= FSHIFT;
  61
  62#define CT_TO_SECS(x)   ((x) / HZ)
  63#define CT_TO_USECS(x)  (((x) % HZ) * 1000000/HZ)
  64
  65extern int nr_running, nr_tasks;
  66extern int last_pid;
  67
  68#include <linux/fs.h>
  69#include <linux/time.h>
  70#include <linux/param.h>
  71#include <linux/resource.h>
  72#include <linux/timer.h>
  73
  74#include <asm/processor.h>
  75
  76#define TASK_RUNNING            0
  77#define TASK_INTERRUPTIBLE      1
  78#define TASK_UNINTERRUPTIBLE    2
  79#define TASK_ZOMBIE             4
  80#define TASK_STOPPED            8
  81#define TASK_SWAPPING           16
  82
  83/*
  84 * Scheduling policies
  85 */
  86#define SCHED_OTHER             0
  87#define SCHED_FIFO              1
  88#define SCHED_RR                2
  89
  90/*
  91 * This is an additional bit set when we want to
  92 * yield the CPU for one re-schedule..
  93 */
  94#define SCHED_YIELD             0x10
  95
  96struct sched_param {
  97        int sched_priority;
  98};
  99
 100#ifndef NULL
 101#define NULL ((void *) 0)
 102#endif
 103
 104#ifdef __KERNEL__
 105
 106#include <asm/spinlock.h>
 107
 108/*
 109 * This serializes "schedule()" and also protects
 110 * the run-queue from deletions/modifications (but
 111 * _adding_ to the beginning of the run-queue has
 112 * a separate lock).
 113 */
 114extern rwlock_t tasklist_lock;
 115extern spinlock_t scheduler_lock;
 116extern spinlock_t runqueue_lock;
 117
 118extern void sched_init(void);
 119extern void show_state(void);
 120extern void trap_init(void);
 121
 122#define MAX_SCHEDULE_TIMEOUT    LONG_MAX
 123extern signed long FASTCALL(schedule_timeout(signed long timeout));
 124asmlinkage void schedule(void);
 125
 126/*
 127 * Open file table structure
 128 */
 129struct files_struct {
 130        atomic_t count;
 131        int max_fds;
 132        struct file ** fd;      /* current fd array */
 133        fd_set close_on_exec;
 134        fd_set open_fds;
 135};
 136
 137#define INIT_FILES { \
 138        ATOMIC_INIT(1), \
 139        NR_OPEN, \
 140        &init_fd_array[0], \
 141        { { 0, } }, \
 142        { { 0, } } \
 143}
 144
 145struct fs_struct {
 146        atomic_t count;
 147        int umask;
 148        struct dentry * root, * pwd;
 149};
 150
 151#define INIT_FS { \
 152        ATOMIC_INIT(1), \
 153        0022, \
 154        NULL, NULL \
 155}
 156
 157/* Maximum number of active map areas.. This is a random (large) number */
 158#define MAX_MAP_COUNT   (65536)
 159
 160/* Number of map areas at which the AVL tree is activated. This is arbitrary. */
 161#define AVL_MIN_MAP_COUNT       32
 162
 163struct mm_struct {
 164        struct vm_area_struct *mmap;            /* list of VMAs */
 165        struct vm_area_struct *mmap_avl;        /* tree of VMAs */
 166        struct vm_area_struct *mmap_cache;      /* last find_vma result */
 167        pgd_t * pgd;
 168        atomic_t count;
 169        int map_count;                          /* number of VMAs */
 170        struct semaphore mmap_sem;
 171        unsigned long context;
 172        unsigned long start_code, end_code, start_data, end_data;
 173        unsigned long start_brk, brk, start_stack;
 174        unsigned long arg_start, arg_end, env_start, env_end;
 175        unsigned long rss, total_vm, locked_vm;
 176        unsigned long def_flags;
 177        unsigned long cpu_vm_mask;
 178        unsigned long swap_cnt; /* number of pages to swap on next pass */
 179        unsigned long swap_address;
 180        /*
 181         * This is an architecture-specific pointer: the portable
 182         * part of Linux does not know about any segments.
 183         */
 184        void * segments;
 185};
 186
 187#define INIT_MM {                                       \
 188                &init_mmap, NULL, NULL,                 \
 189                swapper_pg_dir,                         \
 190                ATOMIC_INIT(1), 1,                      \
 191                MUTEX,                                  \
 192                0,                                      \
 193                0, 0, 0, 0,                             \
 194                0, 0, 0,                                \
 195                0, 0, 0, 0,                             \
 196                0, 0, 0,                                \
 197                0, 0, 0, 0, NULL }
 198
 199struct signal_struct {
 200        atomic_t                count;
 201        struct k_sigaction      action[_NSIG];
 202        spinlock_t              siglock;
 203};
 204
 205
 206#define INIT_SIGNALS { \
 207                ATOMIC_INIT(1), \
 208                { {{0,}}, }, \
 209                SPIN_LOCK_UNLOCKED }
 210
 211/*
 212 * Some day this will be a full-fledged user tracking system..
 213 * Right now it is only used to track how many processes a
 214 * user has, but it has the potential to track memory usage etc.
 215 */
 216struct user_struct;
 217
 218struct task_struct {
 219/* these are hardcoded - don't touch */
 220        volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
 221        unsigned long flags;    /* per process flags, defined below */
 222        int sigpending;
 223        mm_segment_t addr_limit;        /* thread address space:
 224                                                0-0xBFFFFFFF for user-thead
 225                                                0-0xFFFFFFFF for kernel-thread
 226                                         */
 227        struct exec_domain *exec_domain;
 228        long need_resched;
 229
 230/* various fields */
 231        long counter;
 232        long priority;
 233        cycles_t avg_slice;
 234/* SMP and runqueue state */
 235        int has_cpu;
 236        int processor;
 237        int last_processor;
 238        int lock_depth;         /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */  
 239        struct task_struct *next_task, *prev_task;
 240        struct task_struct *next_run,  *prev_run;
 241
 242/* task state */
 243        struct linux_binfmt *binfmt;
 244        int exit_code, exit_signal;
 245        int pdeath_signal;  /*  The signal sent when the parent dies  */
 246        /* ??? */
 247        unsigned long personality;
 248        int dumpable:1;
 249        int did_exec:1;
 250        pid_t pid;
 251        pid_t pgrp;
 252        pid_t tty_old_pgrp;
 253        pid_t session;
 254        /* boolean value for session group leader */
 255        int leader;
 256        /* 
 257         * pointers to (original) parent process, youngest child, younger sibling,
 258         * older sibling, respectively.  (p->father can be replaced with 
 259         * p->p_pptr->pid)
 260         */
 261        struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
 262
 263        /* PID hash table linkage. */
 264        struct task_struct *pidhash_next;
 265        struct task_struct **pidhash_pprev;
 266
 267        /* Pointer to task[] array linkage. */
 268        struct task_struct **tarray_ptr;
 269
 270        struct wait_queue *wait_chldexit;       /* for wait4() */
 271        struct semaphore *vfork_sem;            /* for vfork() */
 272        unsigned long policy, rt_priority;
 273        unsigned long it_real_value, it_prof_value, it_virt_value;
 274        unsigned long it_real_incr, it_prof_incr, it_virt_incr;
 275        struct timer_list real_timer;
 276        struct tms times;
 277        unsigned long start_time;
 278        long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
 279/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
 280        unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
 281        int swappable:1;
 282/* process credentials */
 283        uid_t uid,euid,suid,fsuid;
 284        gid_t gid,egid,sgid,fsgid;
 285        int ngroups;
 286        gid_t   groups[NGROUPS];
 287        kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
 288        struct user_struct *user;
 289/* limits */
 290        struct rlimit rlim[RLIM_NLIMITS];
 291        unsigned short used_math;
 292        char comm[16];
 293/* file system info */
 294        int link_count;
 295        struct tty_struct *tty; /* NULL if no tty */
 296/* ipc stuff */
 297        struct sem_undo *semundo;
 298        struct sem_queue *semsleeping;
 299/* tss for this task */
 300        struct thread_struct tss;
 301/* filesystem information */
 302        struct fs_struct *fs;
 303/* open file information */
 304        struct files_struct *files;
 305/* memory management info */
 306        struct mm_struct *mm;
 307
 308/* signal handlers */
 309        spinlock_t sigmask_lock;        /* Protects signal and blocked */
 310        struct signal_struct *sig;
 311        sigset_t signal, blocked;
 312        struct signal_queue *sigqueue, **sigqueue_tail;
 313        unsigned long sas_ss_sp;
 314        size_t sas_ss_size;
 315};
 316
 317/*
 318 * Per process flags
 319 */
 320#define PF_ALIGNWARN    0x00000001      /* Print alignment warning msgs */
 321                                        /* Not implemented yet, only for 486*/
 322#define PF_STARTING     0x00000002      /* being created */
 323#define PF_EXITING      0x00000004      /* getting shut down */
 324#define PF_PTRACED      0x00000010      /* set if ptrace (0) has been called */
 325#define PF_TRACESYS     0x00000020      /* tracing system calls */
 326#define PF_FORKNOEXEC   0x00000040      /* forked but didn't exec */
 327#define PF_SUPERPRIV    0x00000100      /* used super-user privileges */
 328#define PF_DUMPCORE     0x00000200      /* dumped core */
 329#define PF_SIGNALED     0x00000400      /* killed by a signal */
 330#define PF_MEMALLOC     0x00000800      /* Allocating memory */
 331#define PF_VFORK        0x00001000      /* Wake up parent in mm_release */
 332
 333#define PF_USEDFPU      0x00100000      /* task used FPU this quantum (SMP) */
 334#define PF_DTRACE       0x00200000      /* delayed trace (used on m68k, i386) */
 335
 336/*
 337 * Limit the stack by to some sane default: root can always
 338 * increase this limit if needed..  8MB seems reasonable.
 339 */
 340#define _STK_LIM        (8*1024*1024)
 341
 342#define DEF_PRIORITY    (20*HZ/100)     /* 210 ms time slices */
 343
 344/*
 345 *  INIT_TASK is used to set up the first task table, touch at
 346 * your own risk!. Base=0, limit=0x1fffff (=2MB)
 347 */
 348#define INIT_TASK \
 349/* state etc */ { 0,0,0,KERNEL_DS,&default_exec_domain,0, \
 350/* counter */   DEF_PRIORITY,DEF_PRIORITY,0, \
 351/* SMP */       0,0,0,-1, \
 352/* schedlink */ &init_task,&init_task, &init_task, &init_task, \
 353/* binfmt */    NULL, \
 354/* ec,brk... */ 0,0,0,0,0,0, \
 355/* pid etc.. */ 0,0,0,0,0, \
 356/* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \
 357/* pidhash */   NULL, NULL, \
 358/* tarray */    &task[0], \
 359/* chld wait */ NULL, NULL, \
 360/* timeout */   SCHED_OTHER,0,0,0,0,0,0,0, \
 361/* timer */     { NULL, NULL, 0, 0, it_real_fn }, \
 362/* utime */     {0,0,0,0},0, \
 363/* per CPU times */ {0, }, {0, }, \
 364/* flt */       0,0,0,0,0,0, \
 365/* swp */       0, \
 366/* process credentials */                                       \
 367/* uid etc */   0,0,0,0,0,0,0,0,                                \
 368/* suppl grps*/ 0, {0,},                                        \
 369/* caps */      CAP_INIT_EFF_SET,CAP_INIT_INH_SET,CAP_FULL_SET, \
 370/* user */      NULL,                                           \
 371/* rlimits */   INIT_RLIMITS, \
 372/* math */      0, \
 373/* comm */      "swapper", \
 374/* fs info */   0,NULL, \
 375/* ipc */       NULL, NULL, \
 376/* tss */       INIT_TSS, \
 377/* fs */        &init_fs, \
 378/* files */     &init_files, \
 379/* mm */        &init_mm, \
 380/* signals */   SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \
 381}
 382
 383union task_union {
 384        struct task_struct task;
 385        unsigned long stack[2048];
 386};
 387
 388extern union task_union init_task_union;
 389
 390extern struct   mm_struct init_mm;
 391extern struct task_struct *task[NR_TASKS];
 392
 393extern struct task_struct **tarray_freelist;
 394extern spinlock_t taskslot_lock;
 395
 396extern __inline__ void add_free_taskslot(struct task_struct **t)
 397{
 398        spin_lock(&taskslot_lock);
 399        *t = (struct task_struct *) tarray_freelist;
 400        tarray_freelist = t;
 401        spin_unlock(&taskslot_lock);
 402}
 403
 404extern __inline__ struct task_struct **get_free_taskslot(void)
 405{
 406        struct task_struct **tslot;
 407
 408        spin_lock(&taskslot_lock);
 409        if((tslot = tarray_freelist) != NULL)
 410                tarray_freelist = (struct task_struct **) *tslot;
 411        spin_unlock(&taskslot_lock);
 412
 413        return tslot;
 414}
 415
 416/* PID hashing. */
 417#define PIDHASH_SZ (NR_TASKS >> 2)
 418extern struct task_struct *pidhash[PIDHASH_SZ];
 419
 420#define pid_hashfn(x)   ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
 421
 422extern __inline__ void hash_pid(struct task_struct *p)
 423{
 424        struct task_struct **htable = &pidhash[pid_hashfn(p->pid)];
 425
 426        if((p->pidhash_next = *htable) != NULL)
 427                (*htable)->pidhash_pprev = &p->pidhash_next;
 428        *htable = p;
 429        p->pidhash_pprev = htable;
 430}
 431
 432extern __inline__ void unhash_pid(struct task_struct *p)
 433{
 434        if(p->pidhash_next)
 435                p->pidhash_next->pidhash_pprev = p->pidhash_pprev;
 436        *p->pidhash_pprev = p->pidhash_next;
 437}
 438
 439extern __inline__ struct task_struct *find_task_by_pid(int pid)
 440{
 441        struct task_struct *p, **htable = &pidhash[pid_hashfn(pid)];
 442
 443        for(p = *htable; p && p->pid != pid; p = p->pidhash_next)
 444                ;
 445
 446        return p;
 447}
 448
 449/* per-UID process charging. */
 450extern int alloc_uid(struct task_struct *p);
 451void free_uid(struct task_struct *p);
 452
 453#include <asm/current.h>
 454
 455extern unsigned long volatile jiffies;
 456extern unsigned long itimer_ticks;
 457extern unsigned long itimer_next;
 458extern struct timeval xtime;
 459extern void do_timer(struct pt_regs *);
 460
 461extern unsigned int * prof_buffer;
 462extern unsigned long prof_len;
 463extern unsigned long prof_shift;
 464
 465#define CURRENT_TIME (xtime.tv_sec)
 466
 467extern void FASTCALL(__wake_up(struct wait_queue ** p, unsigned int mode));
 468extern void FASTCALL(sleep_on(struct wait_queue ** p));
 469extern long FASTCALL(sleep_on_timeout(struct wait_queue ** p,
 470                                      signed long timeout));
 471extern void FASTCALL(interruptible_sleep_on(struct wait_queue ** p));
 472extern long FASTCALL(interruptible_sleep_on_timeout(struct wait_queue ** p,
 473                                                    signed long timeout));
 474extern void FASTCALL(wake_up_process(struct task_struct * tsk));
 475
 476#define wake_up(x)                      __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
 477#define wake_up_interruptible(x)        __wake_up((x),TASK_INTERRUPTIBLE)
 478
 479extern int in_group_p(gid_t grp);
 480
 481extern void flush_signals(struct task_struct *);
 482extern void flush_signal_handlers(struct task_struct *);
 483extern int dequeue_signal(sigset_t *block, siginfo_t *);
 484extern int send_sig_info(int, struct siginfo *info, struct task_struct *);
 485extern int force_sig_info(int, struct siginfo *info, struct task_struct *);
 486extern int kill_pg_info(int, struct siginfo *info, pid_t);
 487extern int kill_sl_info(int, struct siginfo *info, pid_t);
 488extern int kill_proc_info(int, struct siginfo *info, pid_t);
 489extern int kill_something_info(int, struct siginfo *info, int);
 490extern void notify_parent(struct task_struct * tsk, int);
 491extern void force_sig(int sig, struct task_struct * p);
 492extern int send_sig(int sig, struct task_struct * p, int priv);
 493extern int kill_pg(pid_t, int, int);
 494extern int kill_sl(pid_t, int, int);
 495extern int kill_proc(pid_t, int, int);
 496extern int do_sigaction(int sig, const struct k_sigaction *act,
 497                        struct k_sigaction *oact);
 498extern int do_sigaltstack(const stack_t *ss, stack_t *oss, unsigned long sp);
 499
 500extern inline int signal_pending(struct task_struct *p)
 501{
 502        return (p->sigpending != 0);
 503}
 504
 505/* Reevaluate whether the task has signals pending delivery.
 506   This is required every time the blocked sigset_t changes.
 507   All callers should have t->sigmask_lock.  */
 508
 509static inline void recalc_sigpending(struct task_struct *t)
 510{
 511        unsigned long ready;
 512        long i;
 513
 514        switch (_NSIG_WORDS) {
 515        default:
 516                for (i = _NSIG_WORDS, ready = 0; --i >= 0 ;)
 517                        ready |= t->signal.sig[i] &~ t->blocked.sig[i];
 518                break;
 519
 520        case 4: ready  = t->signal.sig[3] &~ t->blocked.sig[3];
 521                ready |= t->signal.sig[2] &~ t->blocked.sig[2];
 522                ready |= t->signal.sig[1] &~ t->blocked.sig[1];
 523                ready |= t->signal.sig[0] &~ t->blocked.sig[0];
 524                break;
 525
 526        case 2: ready  = t->signal.sig[1] &~ t->blocked.sig[1];
 527                ready |= t->signal.sig[0] &~ t->blocked.sig[0];
 528                break;
 529
 530        case 1: ready  = t->signal.sig[0] &~ t->blocked.sig[0];
 531        }
 532
 533        t->sigpending = (ready != 0);
 534}
 535
 536/* True if we are on the alternate signal stack.  */
 537
 538static inline int on_sig_stack(unsigned long sp)
 539{
 540        return (sp >= current->sas_ss_sp
 541                && sp < current->sas_ss_sp + current->sas_ss_size);
 542}
 543
 544static inline int sas_ss_flags(unsigned long sp)
 545{
 546        return (current->sas_ss_size == 0 ? SS_DISABLE
 547                : on_sig_stack(sp) ? SS_ONSTACK : 0);
 548}
 549
 550extern int request_irq(unsigned int irq,
 551                       void (*handler)(int, void *, struct pt_regs *),
 552                       unsigned long flags, 
 553                       const char *device,
 554                       void *dev_id);
 555extern void free_irq(unsigned int irq, void *dev_id);
 556
 557/*
 558 * This has now become a routine instead of a macro, it sets a flag if
 559 * it returns true (to do BSD-style accounting where the process is flagged
 560 * if it uses root privs). The implication of this is that you should do
 561 * normal permissions checks first, and check suser() last.
 562 *
 563 * [Dec 1997 -- Chris Evans]
 564 * For correctness, the above considerations need to be extended to
 565 * fsuser(). This is done, along with moving fsuser() checks to be
 566 * last.
 567 *
 568 * These will be removed, but in the mean time, when the SECURE_NOROOT 
 569 * flag is set, uids don't grant privilege.
 570 */
 571extern inline int suser(void)
 572{
 573        if (!issecure(SECURE_NOROOT) && current->euid == 0) { 
 574                current->flags |= PF_SUPERPRIV;
 575                return 1;
 576        }
 577        return 0;
 578}
 579
 580extern inline int fsuser(void)
 581{
 582        if (!issecure(SECURE_NOROOT) && current->fsuid == 0) {
 583                current->flags |= PF_SUPERPRIV;
 584                return 1;
 585        }
 586        return 0;
 587}
 588
 589/*
 590 * capable() checks for a particular capability.  
 591 * New privilege checks should use this interface, rather than suser() or
 592 * fsuser(). See include/linux/capability.h for defined capabilities.
 593 */
 594
 595extern inline int capable(int cap)
 596{
 597#if 1 /* ok now */
 598        if (cap_raised(current->cap_effective, cap))
 599#else
 600        if (cap_is_fs_cap(cap) ? current->fsuid == 0 : current->euid == 0)
 601#endif
 602        {
 603                current->flags |= PF_SUPERPRIV;
 604                return 1;
 605        }
 606        return 0;
 607}
 608
 609/*
 610 * Routines for handling mm_structs
 611 */
 612extern struct mm_struct * mm_alloc(void);
 613static inline void mmget(struct mm_struct * mm)
 614{
 615        atomic_inc(&mm->count);
 616}
 617extern void mmput(struct mm_struct *);
 618/* Remove the current tasks stale references to the old mm_struct */
 619extern void mm_release(void);
 620
 621extern int  copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
 622extern void flush_thread(void);
 623extern void exit_thread(void);
 624
 625extern void exit_mm(struct task_struct *);
 626extern void exit_fs(struct task_struct *);
 627extern void exit_files(struct task_struct *);
 628extern void exit_sighand(struct task_struct *);
 629
 630extern int do_execve(char *, char **, char **, struct pt_regs *);
 631extern int do_fork(unsigned long, unsigned long, struct pt_regs *);
 632
 633/*
 634 * The wait-queues are circular lists, and you have to be *very* sure
 635 * to keep them correct. Use only these two functions to add/remove
 636 * entries in the queues.
 637 */
 638extern inline void __add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
 639{
 640        wait->next = *p ? : WAIT_QUEUE_HEAD(p);
 641        *p = wait;
 642}
 643
 644extern rwlock_t waitqueue_lock;
 645
 646extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
 647{
 648        unsigned long flags;
 649
 650        write_lock_irqsave(&waitqueue_lock, flags);
 651        __add_wait_queue(p, wait);
 652        write_unlock_irqrestore(&waitqueue_lock, flags);
 653}
 654
 655extern inline void __remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
 656{
 657        struct wait_queue * next = wait->next;
 658        struct wait_queue * head = next;
 659        struct wait_queue * tmp;
 660
 661        while ((tmp = head->next) != wait) {
 662                head = tmp;
 663        }
 664        head->next = next;
 665}
 666
 667extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
 668{
 669        unsigned long flags;
 670
 671        write_lock_irqsave(&waitqueue_lock, flags);
 672        __remove_wait_queue(p, wait);
 673        write_unlock_irqrestore(&waitqueue_lock, flags); 
 674}
 675
 676#define __wait_event(wq, condition)                                     \
 677do {                                                                    \
 678        struct wait_queue __wait;                                       \
 679                                                                        \
 680        __wait.task = current;                                          \
 681        add_wait_queue(&wq, &__wait);                                   \
 682        for (;;) {                                                      \
 683                current->state = TASK_UNINTERRUPTIBLE;                  \
 684                if (condition)                                          \
 685                        break;                                          \
 686                schedule();                                             \
 687        }                                                               \
 688        current->state = TASK_RUNNING;                                  \
 689        remove_wait_queue(&wq, &__wait);                                \
 690} while (0)
 691
 692#define wait_event(wq, condition)                                       \
 693do {                                                                    \
 694        if (condition)                                                  \
 695                break;                                                  \
 696        __wait_event(wq, condition);                                    \
 697} while (0)
 698
 699#define __wait_event_interruptible(wq, condition, ret)                  \
 700do {                                                                    \
 701        struct wait_queue __wait;                                       \
 702                                                                        \
 703        __wait.task = current;                                          \
 704        add_wait_queue(&wq, &__wait);                                   \
 705        for (;;) {                                                      \
 706                current->state = TASK_INTERRUPTIBLE;                    \
 707                if (condition)                                          \
 708                        break;                                          \
 709                if (!signal_pending(current)) {                         \
 710                        schedule();                                     \
 711                        continue;                                       \
 712                }                                                       \
 713                ret = -ERESTARTSYS;                                     \
 714                break;                                                  \
 715        }                                                               \
 716        current->state = TASK_RUNNING;                                  \
 717        remove_wait_queue(&wq, &__wait);                                \
 718} while (0)
 719        
 720#define wait_event_interruptible(wq, condition)                         \
 721({                                                                      \
 722        int __ret = 0;                                                  \
 723        if (!(condition))                                               \
 724                __wait_event_interruptible(wq, condition, __ret);       \
 725        __ret;                                                          \
 726})
 727
 728#define REMOVE_LINKS(p) do { \
 729        (p)->next_task->prev_task = (p)->prev_task; \
 730        (p)->prev_task->next_task = (p)->next_task; \
 731        if ((p)->p_osptr) \
 732                (p)->p_osptr->p_ysptr = (p)->p_ysptr; \
 733        if ((p)->p_ysptr) \
 734                (p)->p_ysptr->p_osptr = (p)->p_osptr; \
 735        else \
 736                (p)->p_pptr->p_cptr = (p)->p_osptr; \
 737        } while (0)
 738
 739#define SET_LINKS(p) do { \
 740        (p)->next_task = &init_task; \
 741        (p)->prev_task = init_task.prev_task; \
 742        init_task.prev_task->next_task = (p); \
 743        init_task.prev_task = (p); \
 744        (p)->p_ysptr = NULL; \
 745        if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \
 746                (p)->p_osptr->p_ysptr = p; \
 747        (p)->p_pptr->p_cptr = p; \
 748        } while (0)
 749
 750#define for_each_task(p) \
 751        for (p = &init_task ; (p = p->next_task) != &init_task ; )
 752
 753#endif /* __KERNEL__ */
 754
 755#endif
 756
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.