Ядро Linux в комментариях

       

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 }



Содержание раздела