home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / kernel / sched.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-09  |  19.2 KB  |  775 lines

  1. /*
  2.  *  linux/kernel/sched.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  *
  6.  * This file is subject to the terms and conditions of the GNU General Public
  7.  * License.  See the file README.legal in the main directory of this archive
  8.  * for more details.
  9.  */
  10.  
  11. /*
  12.  * 680x0 support by Hamish Macdonald
  13.  */
  14.  
  15. /*
  16.  * 'sched.c' is the main kernel file. It contains scheduling primitives
  17.  * (sleep_on, wakeup, schedule etc) as well as a number of simple system
  18.  * call functions (type getpid(), which just extracts a field from
  19.  * current-task
  20.  */
  21.  
  22. #include <asm/system.h>
  23. #include <asm/segment.h>
  24.  
  25. #include <linux/config.h>
  26. #include <linux/signal.h>
  27. #include <linux/sched.h>
  28. #include <linux/timer.h>
  29. #include <linux/kernel.h>
  30. #include <linux/traps.h>
  31. #include <linux/sys.h>
  32. #include <linux/fdreg.h>
  33. #include <linux/errno.h>
  34. #include <linux/time.h>
  35. #include <linux/ptrace.h>
  36. #include <linux/delay.h>
  37. #include <linux/interrupt.h>
  38. #include <linux/bootinfo.h>
  39.  
  40. #include <linux/timex.h>
  41.  
  42. /*
  43.  * kernel variables
  44.  */
  45. long tick = 1000000 / HZ;        /* timer interrupt period */
  46. volatile struct timeval xtime;        /* The current time */
  47. int tickadj = 500/HZ;            /* microsecs */
  48.  
  49. /*
  50.  * phase-lock loop variables
  51.  */
  52. int time_status = TIME_BAD;    /* clock synchronization status */
  53. long time_offset = 0;        /* time adjustment (us) */
  54. long time_constant = 0;     /* pll time constant */
  55. long time_tolerance = MAXFREQ;    /* frequency tolerance (ppm) */
  56. long time_precision = 1;    /* clock precision (us) */
  57. long time_maxerror = 0x70000000;/* maximum error */
  58. long time_esterror = 0x70000000;/* estimated error */
  59. long time_phase = 0;        /* phase offset (scaled us) */
  60. long time_freq = 0;        /* frequency offset (scaled ppm) */
  61. long time_adj = 0;        /* tick adjust (scaled 1 / HZ) */
  62. long time_reftime = 0;        /* time at last adjustment (s) */
  63.  
  64. long time_adjust = 0;
  65.  
  66. int need_resched = 0;
  67.  
  68. /*
  69.  * Tell us the machine setup..
  70.  */
  71. int hard_math = 0;        /* set by boot/head.S */
  72. int x86 = 0;            /* set by boot/head.S to 3 or 4 */
  73. int ignore_irq13 = 0;        /* set if exception 16 works */
  74. int wp_works_ok = 0;        /* set if paging hardware honours WP */
  75.  
  76. extern int _setitimer(int, struct itimerval *, struct itimerval *);
  77. unsigned long * prof_buffer = NULL;
  78. unsigned long prof_len = 0;
  79.  
  80. #define _S(nr) (1<<((nr)-1))
  81.  
  82. extern void mem_use(void);
  83.  
  84. extern int timer_interrupt(void);
  85. asmlinkage int system_call(void);
  86.  
  87. static unsigned long init_kernel_stack[1024];
  88. struct task_struct init_task = INIT_TASK;
  89.  
  90. unsigned long volatile jiffies=0;
  91.  
  92. struct task_struct *current = &init_task;
  93. struct task_struct *last_task_used_math = NULL;
  94.  
  95. struct task_struct * task[NR_TASKS] = {&init_task, };
  96.  
  97. long user_stack [ PAGE_SIZE>>2 ] ;
  98.  
  99. struct {
  100.     long * a;
  101.     short b;
  102.     } stack_start = { & user_stack [PAGE_SIZE>>2] , KERNEL_DS };
  103.  
  104. /*
  105.  * int 0x80 entry points.. Moved away from the header file, as
  106.  * iBCS2 may also want to use the '<linux/sys.h>' headers..
  107.  */
  108. #ifdef __cplusplus
  109. extern "C" {
  110. #endif
  111.  
  112. fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
  113. sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
  114. sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
  115. sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
  116. sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
  117. sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
  118. sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
  119. sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
  120. sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
  121. sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
  122. sys_olduname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
  123. sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
  124. sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending,
  125. sys_sethostname, sys_setrlimit, sys_getrlimit, sys_getrusage,
  126. sys_gettimeofday, sys_settimeofday, sys_getgroups, sys_setgroups,
  127. sys_select, sys_symlink, sys_lstat, sys_readlink, sys_uselib,
  128. sys_swapon, sys_reboot, sys_readdir, sys_mmap, sys_munmap, sys_truncate,
  129. sys_ftruncate, sys_fchmod, sys_fchown, sys_getpriority, sys_setpriority,
  130. sys_profil, sys_statfs, sys_fstatfs, sys_unimp /*sys_ioperm*/, sys_socketcall,
  131. sys_syslog, sys_setitimer, sys_getitimer, sys_newstat, sys_newlstat,
  132. sys_newfstat, sys_uname, sys_unimp /*sys_iopl*/, sys_vhangup, sys_idle, sys_unimp /*sys_vm86*/,
  133. sys_wait4, sys_swapoff, sys_sysinfo, sys_ipc, sys_fsync, sys_sigreturn,
  134. sys_clone, sys_setdomainname, sys_newuname, sys_modify_ldt,
  135. sys_adjtimex, sys_mprotect, sys_sigprocmask };
  136.  
  137. /* So we don't have to do any more manual updating.... */
  138. int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
  139.  
  140. #ifdef __cplusplus
  141. }
  142. #endif
  143.  
  144. #ifdef __i386__
  145. /*
  146.  *  'math_state_restore()' saves the current math information in the
  147.  * old math state array, and gets the new ones from the current task
  148.  *
  149.  * Careful.. There are problems with IBM-designed IRQ13 behaviour.
  150.  * Don't touch unless you *really* know how it works.
  151.  */
  152. asmlinkage void math_state_restore(void)
  153. {
  154.     __asm__ __volatile__("clts");
  155.     if (last_task_used_math == current)
  156.         return;
  157.     timer_table[COPRO_TIMER].expires = jiffies+50;
  158.     timer_active |= 1<<COPRO_TIMER;
  159.     if (last_task_used_math)
  160.         __asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
  161.     else
  162.         __asm__("fnclex");
  163.     last_task_used_math=current;
  164.     if (current->used_math) {
  165.         __asm__("frstor %0": :"m" (current->tss.i387));
  166.     } else {
  167.         __asm__("fninit");
  168.         current->used_math=1;
  169.     }
  170.     timer_active &= ~(1<<COPRO_TIMER);
  171. }
  172. #endif
  173.  
  174. #ifndef CONFIG_MATH_EMULATION
  175.  
  176. asmlinkage void math_emulate(long arg)
  177. {
  178.   printk("math-emulation not enabled and no coprocessor found.\n");
  179.   printk("killing %s.\n",current->comm);
  180.   send_sig(SIGFPE,current,1);
  181.   schedule();
  182. }
  183.  
  184. #endif /* CONFIG_MATH_EMULATION */
  185.  
  186. /*
  187.  *  'schedule()' is the scheduler function. It's a very simple and nice
  188.  * scheduler: it's not perfect, but certainly works for most things.
  189.  * The one thing you might take a look at is the signal-handler code here.
  190.  *
  191.  *   NOTE!!  Task 0 is the 'idle' task, which gets called when no other
  192.  * tasks can run. It can not be killed, and it cannot sleep. The 'state'
  193.  * information in task[0] is never used.
  194.  *
  195.  * The "confuse_gcc" goto is used only to get better assembly code..
  196.  * Djikstra probably hates me.
  197.  */
  198.  
  199. asmlinkage void schedule(void)
  200. {
  201.     int c;
  202.     struct task_struct * p;
  203.     struct task_struct * next;
  204.  
  205.     /* check alarm, wake up any interruptible tasks that have got a signal */
  206.  
  207.     need_resched = 0;
  208.     p = &init_task;
  209.     for (;;) {
  210.         if ((p = p->next_task) == &init_task)
  211.             goto confuse_gcc1;
  212.         if (p->state != TASK_INTERRUPTIBLE)
  213.             continue;
  214.         if (p->signal & ~p->blocked) {
  215.             p->state = TASK_RUNNING;
  216.             continue;
  217.         }
  218.         if (p->timeout && p->timeout <= jiffies) {
  219.             p->timeout = 0;
  220.             p->state = TASK_RUNNING;
  221.         }
  222.     }
  223. confuse_gcc1:
  224.  
  225.     /* this is the scheduler proper: */
  226. #if 0
  227.     /* give processes that go to sleep a bit higher priority.. */
  228.     /* This depends on the values for TASK_XXX */
  229.     /* This gives smoother scheduling for some things, but */
  230.     /* can be very unfair under some circumstances, so.. */
  231.     if (TASK_UNINTERRUPTIBLE >= (unsigned) current->state &&
  232.         current->counter < current->priority*2) {
  233.         ++current->counter;
  234.     }
  235. #endif
  236.     c = -1;
  237.     next = p = &init_task;
  238.     for (;;) {
  239.         if ((p = p->next_task) == &init_task)
  240.             goto confuse_gcc2;
  241.         if (p->state == TASK_RUNNING && p->counter > c)
  242.             c = p->counter, next = p;
  243.     }
  244. confuse_gcc2:
  245.     if (!c) {
  246.         for_each_task(p)
  247.             p->counter = (p->counter >> 1) + p->priority;
  248.     }
  249.     switch_to(next);
  250.     /* Now maybe reload the debug registers */
  251. #ifdef __i386__
  252.     if(current->debugreg[7]){
  253.         loaddebug(0);
  254.         loaddebug(1);
  255.         loaddebug(2);
  256.         loaddebug(3);
  257.         loaddebug(6);
  258.     };
  259. #endif
  260. }
  261.  
  262. asmlinkage int sys_pause(void)
  263. {
  264.     current->state = TASK_INTERRUPTIBLE;
  265.     schedule();
  266.     return -ERESTARTNOHAND;
  267. }
  268.  
  269. /*
  270.  * wake_up doesn't wake up stopped processes - they have to be awakened
  271.  * with signals or similar.
  272.  *
  273.  * Note that this doesn't need cli-sti pairs: interrupts may not change
  274.  * the wait-queue structures directly, but only call wake_up() to wake
  275.  * a process. The process itself must remove the queue once it has woken.
  276.  */
  277. void wake_up(struct wait_queue **q)
  278. {
  279.     struct wait_queue *tmp;
  280.     struct task_struct * p;
  281.  
  282.     if (!q || !(tmp = *q))
  283.     return;
  284.     do {
  285.     if ((p = tmp->task) != NULL) {
  286.         if ((p->state == TASK_UNINTERRUPTIBLE) ||
  287.         (p->state == TASK_INTERRUPTIBLE)) {
  288.         p->state = TASK_RUNNING;
  289.         if (p->counter > current->counter)
  290.             need_resched = 1;
  291.         }
  292.     }
  293.     if (!tmp->next) {
  294.         printk("wait_queue is bad (eip = %p)\n",
  295.            __builtin_return_address(1));
  296.         printk("        q = %p\n",q);
  297.         printk("       *q = %p\n",*q);
  298.         printk("      tmp = %p\n",tmp);
  299.         break;
  300.     }
  301.     tmp = tmp->next;
  302.     } while (tmp != *q);
  303. }
  304.  
  305. void wake_up_interruptible(struct wait_queue **q)
  306. {
  307.     struct wait_queue *tmp;
  308.     struct task_struct * p;
  309.  
  310.     if (!q || !(tmp = *q))
  311.     return;
  312.     do {
  313.     if ((p = tmp->task) != NULL) {
  314.         if (p->state == TASK_INTERRUPTIBLE) {
  315.         p->state = TASK_RUNNING;
  316.         if (p->counter > current->counter)
  317.             need_resched = 1;
  318.         }
  319.     }
  320.     if (!tmp->next) {
  321.         printk("wait_queue is bad (eip = %p)\n",
  322.            __builtin_return_address(1));
  323.         printk("        q = %p\n",q);
  324.         printk("       *q = %p\n",*q);
  325.         printk("      tmp = %p\n",tmp);
  326.         break;
  327.     }
  328.     tmp = tmp->next;
  329.     } while (tmp != *q);
  330. }
  331.  
  332. static inline void __sleep_on(struct wait_queue **p, int state)
  333. {
  334.     unsigned long flags;
  335.     struct wait_queue wait = { current, NULL };
  336.  
  337.     if (!p)
  338.         return;
  339.     if (current == task[0])
  340.         panic("task[0] trying to sleep");
  341.     current->state = state;
  342.     add_wait_queue(p, &wait);
  343.     save_flags(flags);
  344.     sti();
  345.     schedule();
  346.     remove_wait_queue(p, &wait);
  347.     restore_flags(flags);
  348. }
  349.  
  350. void interruptible_sleep_on(struct wait_queue **p)
  351. {
  352.     __sleep_on(p,TASK_INTERRUPTIBLE);
  353. }
  354.  
  355. void sleep_on(struct wait_queue **p)
  356. {
  357.     __sleep_on(p,TASK_UNINTERRUPTIBLE);
  358. }
  359.  
  360. static struct timer_list * next_timer = NULL;
  361.  
  362. void add_timer (struct timer_list * timer)
  363. {
  364.     unsigned long flags;
  365.     struct timer_list **p;
  366.  
  367.     if (!timer)
  368.         return;
  369.     timer->next = NULL;
  370.     p = &next_timer;
  371.     save_flags(flags);
  372.     cli();
  373.     while (*p) {
  374.         if ((*p)->expires > timer->expires) {
  375.             (*p)->expires -= timer->expires;
  376.             timer->next = *p;
  377.             break;
  378.         }
  379.         timer->expires -= (*p)->expires;
  380.         p = &(*p)->next;
  381.     }
  382.     *p = timer;
  383.     restore_flags(flags);
  384. }
  385.  
  386. int del_timer(struct timer_list * timer)
  387. {
  388.     unsigned long flags;
  389.     unsigned long expires = 0;
  390.     struct timer_list **p;
  391.  
  392.     p = &next_timer;
  393.     save_flags(flags);
  394.     cli();
  395.     while (*p) {
  396.         if (*p == timer) {
  397.             if ((*p = timer->next) != NULL)
  398.                 (*p)->expires += timer->expires;
  399.             timer->expires += expires;
  400.             restore_flags(flags);
  401.             return 1;
  402.         }
  403.         expires += (*p)->expires;
  404.         p = &(*p)->next;
  405.     }
  406.     restore_flags(flags);
  407.     return 0;
  408. }
  409.  
  410. unsigned long timer_active = 0;
  411. struct timer_struct timer_table[32];
  412.  
  413. /*
  414.  * Hmm.. Changed this, as the GNU make sources (load.c) seems to
  415.  * imply that avenrun[] is the standard name for this kind of thing.
  416.  * Nothing else seems to be standardized: the fractional size etc
  417.  * all seem to differ on different machines.
  418.  */
  419. unsigned long avenrun[3] = { 0,0,0 };
  420.  
  421. /*
  422.  * Nr of active tasks - counted in fixed-point numbers
  423.  */
  424. static unsigned long count_active_tasks(void)
  425. {
  426.     struct task_struct **p;
  427.     unsigned long nr = 0;
  428.  
  429.     for(p = &LAST_TASK; p > &FIRST_TASK; --p)
  430.         if (*p && ((*p)->state == TASK_RUNNING ||
  431.                (*p)->state == TASK_UNINTERRUPTIBLE ||
  432.                (*p)->state == TASK_SWAPPING))
  433.             nr += FIXED_1;
  434.     return nr;
  435. }
  436.  
  437. static inline void calc_load(void)
  438. {
  439.     unsigned long active_tasks; /* fixed-point */
  440.     static int count = LOAD_FREQ;
  441.  
  442.     if (count-- > 0)
  443.         return;
  444.     count = LOAD_FREQ;
  445.     active_tasks = count_active_tasks();
  446.     CALC_LOAD(avenrun[0], EXP_1, active_tasks);
  447.     CALC_LOAD(avenrun[1], EXP_5, active_tasks);
  448.     CALC_LOAD(avenrun[2], EXP_15, active_tasks);
  449. }
  450.  
  451. /*
  452.  * this routine handles the overflow of the microsecond field
  453.  *
  454.  * The tricky bits of code to handle the accurate clock support
  455.  * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
  456.  * They were originally developed for SUN and DEC kernels.
  457.  * All the kudos should go to Dave for this stuff.
  458.  *
  459.  * These were ported to Linux by Philip Gladstone.
  460.  */
  461. static void second_overflow(void)
  462. {
  463.     long ltemp;
  464.     /* last time the cmos clock got updated */
  465.     static long last_rtc_update=0;
  466.     extern int set_rtc_mmss(unsigned long);
  467.  
  468.     /* Bump the maxerror field */
  469.     time_maxerror = (0x70000000-time_maxerror < time_tolerance) ?
  470.       0x70000000 : (time_maxerror + time_tolerance);
  471.  
  472.     /* Run the PLL */
  473.     if (time_offset < 0) {
  474.         ltemp = (-(time_offset+1) >> (SHIFT_KG + time_constant)) + 1;
  475.         time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
  476.         time_offset += (time_adj * HZ) >> (SHIFT_SCALE - SHIFT_UPDATE);
  477.         time_adj = - time_adj;
  478.     } else if (time_offset > 0) {
  479.         ltemp = ((time_offset-1) >> (SHIFT_KG + time_constant)) + 1;
  480.         time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
  481.         time_offset -= (time_adj * HZ) >> (SHIFT_SCALE - SHIFT_UPDATE);
  482.     } else {
  483.         time_adj = 0;
  484.     }
  485.  
  486.     time_adj += (time_freq >> (SHIFT_KF + SHIFT_HZ - SHIFT_SCALE))
  487.         + FINETUNE;
  488.  
  489.     /* Handle the leap second stuff */
  490.     switch (time_status) {
  491.         case TIME_INS:
  492.         /* ugly divide should be replaced */
  493.         if (xtime.tv_sec % 86400 == 0) {
  494.             xtime.tv_sec--; /* !! */
  495.             time_status = TIME_OOP;
  496.             printk("Clock: inserting leap second 23:59:60 GMT\n");
  497.         }
  498.         break;
  499.  
  500.         case TIME_DEL:
  501.         /* ugly divide should be replaced */
  502.         if (xtime.tv_sec % 86400 == 86399) {
  503.             xtime.tv_sec++;
  504.             time_status = TIME_OK;
  505.             printk("Clock: deleting leap second 23:59:59 GMT\n");
  506.         }
  507.         break;
  508.  
  509.         case TIME_OOP:
  510.         time_status = TIME_OK;
  511.         break;
  512.     }
  513.     if (xtime.tv_sec > last_rtc_update + 660)
  514.       if (set_rtc_mmss(xtime.tv_sec) == 0)
  515.         last_rtc_update = xtime.tv_sec;
  516. }
  517.  
  518. static int lost_ticks = 0;
  519.  
  520. /*
  521.  * disregard lost ticks for now.. We don't care enough.
  522.  */
  523. static void timer_bh(void * unused)
  524. {
  525.     cli();
  526.     while (next_timer && next_timer->expires == 0) {
  527.         void (*fn)(unsigned long) = next_timer->function;
  528.         unsigned long data = next_timer->data;
  529.         next_timer = next_timer->next;
  530.         sti();
  531.         fn(data);
  532.         cli();
  533.     }
  534.     sti();
  535. }
  536.  
  537.  
  538. /*
  539.  * This routine is called when the (100Hz) timer interrupt goes off.
  540.  */
  541. static void do_timer(struct intframe *fp, void *data)
  542. {
  543.     unsigned long mask;
  544.     struct timer_struct *tp = timer_table+0;
  545.     struct task_struct * task_p;
  546.     unsigned long flags;
  547.  
  548.     long ltemp;
  549.  
  550.     /* Advance the phase, once it gets to one microsecond, then
  551.      * advance the tick more.
  552.      */
  553.     time_phase += time_adj;
  554.     if (time_phase < -FINEUSEC) {
  555.         ltemp = -time_phase >> SHIFT_SCALE;
  556.         time_phase += ltemp << SHIFT_SCALE;
  557.         xtime.tv_usec += tick - ltemp;
  558.     }
  559.     else if (time_phase > FINEUSEC) {
  560.         ltemp = time_phase >> SHIFT_SCALE;
  561.         time_phase -= ltemp << SHIFT_SCALE;
  562.         xtime.tv_usec += tick + ltemp;
  563.     } else
  564.         xtime.tv_usec += tick;
  565.  
  566.     if (time_adjust)
  567.     {
  568.         /* We are doing an adjtime thing.
  569.          */
  570.  
  571.         /* Limit the amount of the step for *next* tick to be
  572.          * in the range -tickadj .. +tickadj
  573.          */
  574.          if (time_adjust > tickadj)
  575.            ltemp = tickadj;
  576.          else if (time_adjust < -tickadj)
  577.            ltemp = -tickadj;
  578.          else
  579.            ltemp = time_adjust;
  580.  
  581.         /* Reduce the amount of time left by this step */
  582.         time_adjust -= ltemp;
  583.  
  584.         /* Modify the value of the tick for next time.
  585.          * Note that a positive delta means we want the clock
  586.          * to run fast. This means that the tick should be bigger
  587.          */
  588.         tick = 1000000/HZ + ltemp;
  589.     }
  590.     else
  591.         tick = 1000000/HZ;
  592.  
  593.     if (xtime.tv_usec >= 1000000) {
  594.         xtime.tv_usec -= 1000000;
  595.         xtime.tv_sec++;
  596.         second_overflow();
  597.     }
  598.  
  599.     jiffies++;
  600.     calc_load();
  601.     if (fp->sr & PS_S) {
  602.     current->stime++;
  603. #ifdef CONFIG_PROFILE
  604.     if (prof_buffer && current != task[0]) {
  605.         unsigned long pc = fp->pc;
  606.         pc >>= 2;
  607.         if (pc < prof_len)
  608.         prof_buffer[pc]++;
  609.     }
  610.     } else {
  611.     current->utime++;
  612.     /* Update ITIMER_VIRT for current task if not in a system call */
  613.     if (current->it_virt_value && !(--current->it_virt_value)) {
  614.         current->it_virt_value = current->it_virt_incr;
  615.         send_sig(SIGVTALRM,current,1);
  616.     }
  617. #endif
  618.     }
  619.     if (current == task[0] || (--current->counter)<=0) {
  620.     current->counter=0;
  621.     need_resched = 1;
  622.     }
  623.     /* Update ITIMER_REAL for every task */
  624.     for_each_task(task_p) {
  625.         if (!task_p->it_real_value)
  626.             continue;
  627.         if (--task_p->it_real_value)
  628.             continue;
  629.         send_sig(SIGALRM,task_p,1);
  630.         task_p->it_real_value = task_p->it_real_incr;
  631.         need_resched = 1;
  632.     }
  633.     /* Update ITIMER_PROF for the current task */
  634.     if (current->it_prof_value && !(--current->it_prof_value)) {
  635.     current->it_prof_value = current->it_prof_incr;
  636.     send_sig(SIGPROF,current,1);
  637.     }
  638.     for (mask = 1 ; mask ; tp++,mask += mask) {
  639.     if (mask > timer_active)
  640.         break;
  641.     if (!(mask & timer_active))
  642.         continue;
  643.     if (tp->expires > jiffies)
  644.         continue;
  645.     timer_active &= ~mask;
  646.     tp->fn();
  647.     }
  648.     save_flags(flags);
  649.     cli();
  650.     if (next_timer) {
  651.         if (next_timer->expires) {
  652.             next_timer->expires--;
  653.             if (!next_timer->expires)
  654.                 mark_bh(TIMER_BH);
  655.         } else {
  656.             lost_ticks++;
  657.             mark_bh(TIMER_BH);
  658.         }
  659.     }
  660.     restore_flags(flags);
  661. }
  662.  
  663. asmlinkage int sys_alarm(long seconds)
  664. {
  665.     struct itimerval it_new, it_old;
  666.  
  667.     it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
  668.     it_new.it_value.tv_sec = seconds;
  669.     it_new.it_value.tv_usec = 0;
  670.     _setitimer(ITIMER_REAL, &it_new, &it_old);
  671.     return(it_old.it_value.tv_sec + (it_old.it_value.tv_usec / 1000000));
  672. }
  673.  
  674. asmlinkage int sys_getpid(void)
  675. {
  676.     return current->pid;
  677. }
  678.  
  679. asmlinkage int sys_getppid(void)
  680. {
  681.     return current->p_opptr->pid;
  682. }
  683.  
  684. asmlinkage int sys_getuid(void)
  685. {
  686.     return current->uid;
  687. }
  688.  
  689. asmlinkage int sys_geteuid(void)
  690. {
  691.     return current->euid;
  692. }
  693.  
  694. asmlinkage int sys_getgid(void)
  695. {
  696.     return current->gid;
  697. }
  698.  
  699. asmlinkage int sys_getegid(void)
  700. {
  701.     return current->egid;
  702. }
  703.  
  704. asmlinkage int sys_nice(long increment)
  705. {
  706.     int newprio;
  707.  
  708.     if (increment < 0 && !suser())
  709.         return -EPERM;
  710.     newprio = current->priority - increment;
  711.     if (newprio < 1)
  712.         newprio = 1;
  713.     if (newprio > 35)
  714.         newprio = 35;
  715.     current->priority = newprio;
  716.     return 0;
  717. }
  718.  
  719. static void show_task(int nr,struct task_struct * p)
  720. {
  721.     static char * stat_nam[] = { "R", "S", "D", "Z", "T", "W" };
  722.  
  723.     printk("%-8s %3d ", p->comm, (p == current) ? -nr : nr);
  724.     if (((unsigned) p->state) < sizeof(stat_nam)/sizeof(char *))
  725.         printk(stat_nam[p->state]);
  726.     else
  727.         printk(" ");
  728.     /* this prints bogus values for the current process */
  729. #if defined(__i386__)
  730.     printk(" %08lX ", ((unsigned long *)p->tss.esp)[2]);
  731.     printk("%5lu %5d %6d ",
  732.         p->tss.esp - p->kernel_stack_page, p->pid, p->p_pptr->pid);
  733. #elif defined(__mc68000__)
  734.     printk(" %08lX ", ((unsigned long *)p->tss.regs[11])[0]);
  735.     printk("%5lu %5d %6d ",
  736.         p->tss.regs[11] - p->kernel_stack_page, p->pid, p->p_pptr->pid);
  737. #endif
  738.     if (p->p_cptr)
  739.         printk("%5d ", p->p_cptr->pid);
  740.     else
  741.         printk("      ");
  742.     if (p->p_ysptr)
  743.         printk("%7d", p->p_ysptr->pid);
  744.     else
  745.         printk("       ");
  746.     if (p->p_osptr)
  747.         printk(" %5d\n", p->p_osptr->pid);
  748.     else
  749.         printk("\n");
  750. }
  751.  
  752. void show_state(void)
  753. {
  754.     int i;
  755.  
  756.     printk("                         free                        sibling\n");
  757.     printk("  task             PC    stack   pid father child younger older\n");
  758.     for (i=0 ; i<NR_TASKS ; i++)
  759.         if (task[i])
  760.             show_task(i,task[i]);
  761. }
  762.  
  763. void sched_init(void)
  764. {
  765.     bh_base[TIMER_BH].routine = timer_bh;
  766.     if (sizeof(struct sigaction) != 16)
  767.         panic("Struct sigaction MUST be 16 bytes");
  768.  
  769.     if (sizeof(struct task_struct) > PAGE_SIZE)
  770.         panic("struct task_struct cannot be larger than the page size");
  771.  
  772.     /* do machine specific initialization (timer and interrupt) */
  773.     mach_sched_init (do_timer);
  774. }
  775.