linux-bk/kernel/itimer.c
<<
>>
Prefs
   1/*
   2 * linux/kernel/itimer.c
   3 *
   4 * Copyright (C) 1992 Darren Senn
   5 */
   6
   7/* These are all the functions necessary to implement itimers */
   8
   9#include <linux/mm.h>
  10#include <linux/smp_lock.h>
  11#include <linux/interrupt.h>
  12
  13#include <asm/uaccess.h>
  14
  15int do_getitimer(int which, struct itimerval *value)
  16{
  17        register unsigned long val, interval;
  18
  19        switch (which) {
  20        case ITIMER_REAL:
  21                interval = current->it_real_incr;
  22                val = 0;
  23                /* 
  24                 * FIXME! This needs to be atomic, in case the kernel timer happens!
  25                 */
  26                if (timer_pending(&current->real_timer)) {
  27                        val = current->real_timer.expires - jiffies;
  28
  29                        /* look out for negative/zero itimer.. */
  30                        if ((long) val <= 0)
  31                                val = 1;
  32                }
  33                break;
  34        case ITIMER_VIRTUAL:
  35                val = current->it_virt_value;
  36                interval = current->it_virt_incr;
  37                break;
  38        case ITIMER_PROF:
  39                val = current->it_prof_value;
  40                interval = current->it_prof_incr;
  41                break;
  42        default:
  43                return(-EINVAL);
  44        }
  45        jiffies_to_timeval(val, &value->it_value);
  46        jiffies_to_timeval(interval, &value->it_interval);
  47        return 0;
  48}
  49
  50/* SMP: Only we modify our itimer values. */
  51asmlinkage long sys_getitimer(int which, struct itimerval *value)
  52{
  53        int error = -EFAULT;
  54        struct itimerval get_buffer;
  55
  56        if (value) {
  57                error = do_getitimer(which, &get_buffer);
  58                if (!error &&
  59                    copy_to_user(value, &get_buffer, sizeof(get_buffer)))
  60                        error = -EFAULT;
  61        }
  62        return error;
  63}
  64
  65void it_real_fn(unsigned long __data)
  66{
  67        struct task_struct * p = (struct task_struct *) __data;
  68        unsigned long interval;
  69
  70        send_sig(SIGALRM, p, 1);
  71        interval = p->it_real_incr;
  72        if (interval) {
  73                if (interval > (unsigned long) LONG_MAX)
  74                        interval = LONG_MAX;
  75                p->real_timer.expires = jiffies + interval;
  76                add_timer(&p->real_timer);
  77        }
  78}
  79
  80int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
  81{
  82        register unsigned long i, j;
  83        int k;
  84
  85        i = timeval_to_jiffies(&value->it_interval);
  86        j = timeval_to_jiffies(&value->it_value);
  87        if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
  88                return k;
  89        switch (which) {
  90                case ITIMER_REAL:
  91                        del_timer_sync(&current->real_timer);
  92                        current->it_real_value = j;
  93                        current->it_real_incr = i;
  94                        if (!j)
  95                                break;
  96                        if (j > (unsigned long) LONG_MAX)
  97                                j = LONG_MAX;
  98                        i = j + jiffies;
  99                        current->real_timer.expires = i;
 100                        add_timer(&current->real_timer);
 101                        break;
 102                case ITIMER_VIRTUAL:
 103                        if (j)
 104                                j++;
 105                        current->it_virt_value = j;
 106                        current->it_virt_incr = i;
 107                        break;
 108                case ITIMER_PROF:
 109                        if (j)
 110                                j++;
 111                        current->it_prof_value = j;
 112                        current->it_prof_incr = i;
 113                        break;
 114                default:
 115                        return -EINVAL;
 116        }
 117        return 0;
 118}
 119
 120/* SMP: Again, only we play with our itimers, and signals are SMP safe
 121 *      now so that is not an issue at all anymore.
 122 */
 123asmlinkage long sys_setitimer(int which, struct itimerval *value,
 124                              struct itimerval *ovalue)
 125{
 126        struct itimerval set_buffer, get_buffer;
 127        int error;
 128
 129        if (value) {
 130                if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
 131                        return -EFAULT;
 132        } else
 133                memset((char *) &set_buffer, 0, sizeof(set_buffer));
 134
 135        error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
 136        if (error || !ovalue)
 137                return error;
 138
 139        if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
 140                return -EFAULT; 
 141        return 0;
 142}
 143
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.