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(¤t->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(¤t->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(¤t->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 }
Сайт управляется системой
uCoz