root/kernel/itimer.c

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

DEFINITIONS

This source file includes following definitions.
  1. tvtojiffies
  2. jiffiestotv
  3. _getitimer
  4. sys_getitimer
  5. it_real_fn
  6. _setitimer
  7. sys_setitimer

   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/signal.h>
  10 #include <linux/sched.h>
  11 #include <linux/string.h>
  12 #include <linux/errno.h>
  13 #include <linux/time.h>
  14 #include <linux/mm.h>
  15 
  16 #include <asm/segment.h>
  17 
  18 /*
  19  * change timeval to jiffies, trying to avoid the 
  20  * most obvious overflows..
  21  *
  22  * The tv_*sec values are signed, but nothing seems to 
  23  * indicate whether we really should use them as signed values
  24  * when doing itimers. POSIX doesn't mention this (but if
  25  * alarm() uses itimers without checking, we have to use unsigned
  26  * arithmetic).
  27  */
  28 static unsigned long tvtojiffies(struct timeval *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  29 {
  30         unsigned long sec = (unsigned) value->tv_sec;
  31         unsigned long usec = (unsigned) value->tv_usec;
  32 
  33         if (sec > (ULONG_MAX / HZ))
  34                 return ULONG_MAX;
  35         usec += 1000000 / HZ - 1;
  36         usec /= 1000000 / HZ;
  37         return HZ*sec+usec;
  38 }
  39 
  40 static void jiffiestotv(unsigned long jiffies, struct timeval *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42         value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
  43         value->tv_sec = jiffies / HZ;
  44         return;
  45 }
  46 
  47 static int _getitimer(int which, struct itimerval *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49         register unsigned long val, interval;
  50 
  51         switch (which) {
  52         case ITIMER_REAL:
  53                 interval = current->it_real_incr;
  54                 val = 0;
  55                 if (del_timer(&current->real_timer)) {
  56                         unsigned long now = jiffies;
  57                         val = current->real_timer.expires;
  58                         add_timer(&current->real_timer);
  59                         /* look out for negative/zero itimer.. */
  60                         if (val <= now)
  61                                 val = now+1;
  62                         val -= now;
  63                 }
  64                 break;
  65         case ITIMER_VIRTUAL:
  66                 val = current->it_virt_value;
  67                 interval = current->it_virt_incr;
  68                 break;
  69         case ITIMER_PROF:
  70                 val = current->it_prof_value;
  71                 interval = current->it_prof_incr;
  72                 break;
  73         default:
  74                 return(-EINVAL);
  75         }
  76         jiffiestotv(val, &value->it_value);
  77         jiffiestotv(interval, &value->it_interval);
  78         return 0;
  79 }
  80 
  81 asmlinkage int sys_getitimer(int which, struct itimerval *value)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         int error;
  84         struct itimerval get_buffer;
  85 
  86         if (!value)
  87                 return -EFAULT;
  88         error = _getitimer(which, &get_buffer);
  89         if (error)
  90                 return error;
  91         error = verify_area(VERIFY_WRITE, value, sizeof(struct itimerval));
  92         if (error)
  93                 return error;
  94         memcpy_tofs(value, &get_buffer, sizeof(get_buffer));
  95         return 0;
  96 }
  97 
  98 void it_real_fn(unsigned long __data)
     /* [previous][next][first][last][top][bottom][index][help] */
  99 {
 100         struct task_struct * p = (struct task_struct *) __data;
 101         unsigned long interval;
 102 
 103         send_sig(SIGALRM, p, 1);
 104         interval = p->it_real_incr;
 105         if (interval) {
 106                 unsigned long timeout = jiffies + interval;
 107                 /* check for overflow */
 108                 if (timeout < interval)
 109                         timeout = ULONG_MAX;
 110                 p->real_timer.expires = timeout;
 111                 add_timer(&p->real_timer);
 112         }
 113 }
 114 
 115 int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         register unsigned long i, j;
 118         int k;
 119 
 120         i = tvtojiffies(&value->it_interval);
 121         j = tvtojiffies(&value->it_value);
 122         if (ovalue && (k = _getitimer(which, ovalue)) < 0)
 123                 return k;
 124         switch (which) {
 125                 case ITIMER_REAL:
 126                         del_timer(&current->real_timer);
 127                         current->it_real_value = j;
 128                         current->it_real_incr = i;
 129                         if (!j)
 130                                 break;
 131                         i = j + jiffies;
 132                         /* check for overflow.. */
 133                         if (i < j)
 134                                 i = ULONG_MAX;
 135                         current->real_timer.expires = i;
 136                         add_timer(&current->real_timer);
 137                         break;
 138                 case ITIMER_VIRTUAL:
 139                         if (j)
 140                                 j++;
 141                         current->it_virt_value = j;
 142                         current->it_virt_incr = i;
 143                         break;
 144                 case ITIMER_PROF:
 145                         if (j)
 146                                 j++;
 147                         current->it_prof_value = j;
 148                         current->it_prof_incr = i;
 149                         break;
 150                 default:
 151                         return -EINVAL;
 152         }
 153         return 0;
 154 }
 155 
 156 asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
     /* [previous][next][first][last][top][bottom][index][help] */
 157 {
 158         int error;
 159         struct itimerval set_buffer, get_buffer;
 160 
 161         if (value) {
 162                 error = verify_area(VERIFY_READ, value, sizeof(*value));
 163                 if (error)
 164                         return error;
 165                 memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
 166         } else
 167                 memset((char *) &set_buffer, 0, sizeof(set_buffer));
 168 
 169         if (ovalue) {
 170                 error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval));
 171                 if (error)
 172                         return error;
 173         }
 174 
 175         error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
 176         if (error || !ovalue)
 177                 return error;
 178 
 179         memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
 180         return error;
 181 }

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