netlib.narod.ru< Назад | Оглавление | Далее >

kernel/itimer.c

24165 /*
24166  * linux/kernel/itimer.c
24167  *
24168  * Copyright (C) 1992 Darren Senn
24169  */
24170 
24171 /* These are all the functions necessary to implement
24172  * itimers */
24173 
24174 #include <linux/mm.h>
24175 #include <linux/smp_lock.h>
24176 #include <linux/interrupt.h>
24177 
24178 #include <asm/uaccess.h>
24179 
24180 /* change timeval to jiffies, trying to avoid the most
24181  * obvious overflows..
24182  *
24183  * The tv_*sec values are signed, but nothing seems to
24184  * indicate whether we really should use them as signed
24185  * values when doing itimers. POSIX doesn't mention this
24186  * (but if alarm() uses itimers without checking, we have
24187  * to use unsigned arithmetic).  */
24188 static unsigned long tvtojiffies(struct timeval *value)
24189 {
24190   unsigned long sec = (unsigned) value->tv_sec;
24191   unsigned long usec = (unsigned) value->tv_usec;
24192 
24193   if (sec > (ULONG_MAX / HZ))
24194     return ULONG_MAX;
24195   usec += 1000000 / HZ - 1;
24196   usec /= 1000000 / HZ;
24197   return HZ*sec+usec;
24198 }
24199 
24200 static void jiffiestotv(unsigned long jiffies,
24201                         struct timeval *value)
24202 {
24203   value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
24204   value->tv_sec = jiffies / HZ;
24205 }
24206 
24207 int do_getitimer(int which, struct itimerval *value)
24208 {
24209   register unsigned long val, interval;
24210 
24211   switch (which) {
24212   case ITIMER_REAL:
24213     interval = current->it_real_incr;
24214     val = 0;
24215     start_bh_atomic();
24216     if (timer_pending(&current->real_timer)) {
24217       val = current->real_timer.expires - jiffies;
24218 
24219       /* look out for negative/zero itimer.. */
24220       if ((long) val <= 0)
24221         val = 1;
24222     }
24223     end_bh_atomic();
24224     break;
24225   case ITIMER_VIRTUAL:
24226     val = current->it_virt_value;
24227     interval = current->it_virt_incr;
24228     break;
24229   case ITIMER_PROF:
24230     val = current->it_prof_value;
24231     interval = current->it_prof_incr;
24232     break;
24233   default:
24234     return(-EINVAL);
24235   }
24236   jiffiestotv(val, &value->it_value);
24237   jiffiestotv(interval, &value->it_interval);
24238   return 0;
24239 }
24240 
24241 /* SMP: Only we modify our itimer values. */
24242 asmlinkage int sys_getitimer(int which,
24243                              struct itimerval *value)
24244 {
24245   int error = -EFAULT;
24246   struct itimerval get_buffer;
24247 
24248   if (value) {
24249     error = do_getitimer(which, &get_buffer);
24250     if (!error &&
24251         copy_to_user(value, &get_buffer,
24252                      sizeof(get_buffer)))
24253       error = -EFAULT;
24254   }
24255   return error;
24256 }
24257 
24258 void it_real_fn(unsigned long __data)
24259 {
24260   struct task_struct * p = (struct task_struct *) __data;
24261   unsigned long interval;
24262 
24263   send_sig(SIGALRM, p, 1);
24264   interval = p->it_real_incr;
24265   if (interval) {
24266     if (interval > (unsigned long) LONG_MAX)
24267       interval = LONG_MAX;
24268     p->real_timer.expires = jiffies + interval;
24269     add_timer(&p->real_timer);
24270   }
24271 }
24272 
24273 int do_setitimer(int which, struct itimerval *value,
24274                  struct itimerval *ovalue)
24275 {
24276   register unsigned long i, j;
24277   int k;
24278 
24279   i = tvtojiffies(&value->it_interval);
24280   j = tvtojiffies(&value->it_value);
24281   if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
24282     return k;
24283   switch (which) {
24284     case ITIMER_REAL:
24285       start_bh_atomic();
24286       del_timer(&current->real_timer);
24287       end_bh_atomic();
24288       current->it_real_value = j;
24289       current->it_real_incr = i;
24290       if (!j)
24291         break;
24292       if (j > (unsigned long) LONG_MAX)
24293         j = LONG_MAX;
24294       i = j + jiffies;
24295       current->real_timer.expires = i;
24296       add_timer(&current->real_timer);
24297       break;
24298     case ITIMER_VIRTUAL:
24299       if (j)
24300         j++;
24301       current->it_virt_value = j;
24302       current->it_virt_incr = i;
24303       break;
24304     case ITIMER_PROF:
24305       if (j)
24306         j++;
24307       current->it_prof_value = j;
24308       current->it_prof_incr = i;
24309       break;
24310     default:
24311       return -EINVAL;
24312   }
24313   return 0;
24314 }
24315 
24316 /* SMP: Again, only we play with our itimers, and signals
24317  *      are SMP safe now so that is not an issue at all
24318  *      anymore.  */
24319 asmlinkage int sys_setitimer(int which,
24320   struct itimerval *value, struct itimerval *ovalue)
24321 {
24322   struct itimerval set_buffer, get_buffer;
24323   int error;
24324 
24325   if (value) {
24326     if (verify_area(VERIFY_READ, value, sizeof(*value)))
24327       return -EFAULT;
24328     if (copy_from_user(&set_buffer, value,
24329                        sizeof(set_buffer)))
24330       return -EFAULT;
24331   } else
24332     memset((char *) &set_buffer, 0, sizeof(set_buffer));
24333 
24334   error = do_setitimer(which, &set_buffer,
24335                        ovalue ? &get_buffer : 0);
24336   if (error || !ovalue)
24337     return error;
24338 
24339   if (copy_to_user(ovalue, &get_buffer,
24340                    sizeof(get_buffer)))
24341     return -EFAULT;
24342   return 0;
24343 }

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz