Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | /* * linux/kernel/itimer.c * * Copyright (C) 1992 Darren Senn */ /* These are all the functions necessary to implement itimers */ #include <linux/signal.h> #include <linux/sched.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/time.h> #include <linux/mm.h> #include <asm/segment.h> static unsigned long tvtojiffies(struct timeval *value) { return((unsigned long )value->tv_sec * HZ + (unsigned long )(value->tv_usec + (1000000 / HZ - 1)) / (1000000 / HZ)); } static void jiffiestotv(unsigned long jiffies, struct timeval *value) { value->tv_usec = (jiffies % HZ) * (1000000 / HZ); value->tv_sec = jiffies / HZ; return; } int _getitimer(int which, struct itimerval *value) { register unsigned long val, interval; switch (which) { case ITIMER_REAL: val = current->it_real_value; interval = current->it_real_incr; break; case ITIMER_VIRTUAL: val = current->it_virt_value; interval = current->it_virt_incr; break; case ITIMER_PROF: val = current->it_prof_value; interval = current->it_prof_incr; break; default: return(-EINVAL); } jiffiestotv(val, &value->it_value); jiffiestotv(interval, &value->it_interval); return(0); } asmlinkage int sys_getitimer(int which, struct itimerval *value) { int error; struct itimerval get_buffer; if (!value) return -EFAULT; error = _getitimer(which, &get_buffer); if (error) return error; error = verify_area(VERIFY_WRITE, value, sizeof(struct itimerval)); if (error) return error; memcpy_tofs(value, &get_buffer, sizeof(get_buffer)); return 0; } int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue) { register unsigned long i, j; int k; i = tvtojiffies(&value->it_interval); j = tvtojiffies(&value->it_value); if (ovalue && (k = _getitimer(which, ovalue)) < 0) return k; switch (which) { case ITIMER_REAL: if (j) { j += 1+itimer_ticks; if (j < itimer_next) itimer_next = j; } current->it_real_value = j; current->it_real_incr = i; break; case ITIMER_VIRTUAL: if (j) j++; current->it_virt_value = j; current->it_virt_incr = i; break; case ITIMER_PROF: if (j) j++; current->it_prof_value = j; current->it_prof_incr = i; break; default: return -EINVAL; } return 0; } asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) { int error; struct itimerval set_buffer, get_buffer; if (value) { error = verify_area(VERIFY_READ, value, sizeof(*value)); if (error) return error; memcpy_fromfs(&set_buffer, value, sizeof(set_buffer)); } else memset((char *) &set_buffer, 0, sizeof(set_buffer)); if (ovalue) { error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval)); if (error) return error; } error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0); if (error || !ovalue) return error; memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer)); return error; } |