itimer.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/kernel/itimer.c
  3.  *
  4.  * Copyright (C) 1992 Darren Senn
  5.  */
  6. /* These are all the functions necessary to implement itimers */
  7. #include <linux/mm.h>
  8. #include <linux/smp_lock.h>
  9. #include <linux/interrupt.h>
  10. #include <asm/uaccess.h>
  11. /*
  12.  * change timeval to jiffies, trying to avoid the 
  13.  * most obvious overflows..
  14.  *
  15.  * The tv_*sec values are signed, but nothing seems to 
  16.  * indicate whether we really should use them as signed values
  17.  * when doing itimers. POSIX doesn't mention this (but if
  18.  * alarm() uses itimers without checking, we have to use unsigned
  19.  * arithmetic).
  20.  */
  21. static unsigned long tvtojiffies(struct timeval *value)
  22. {
  23. unsigned long sec = (unsigned) value->tv_sec;
  24. unsigned long usec = (unsigned) value->tv_usec;
  25. if (sec > (ULONG_MAX / HZ))
  26. return ULONG_MAX;
  27. usec += 1000000 / HZ - 1;
  28. usec /= 1000000 / HZ;
  29. return HZ*sec+usec;
  30. }
  31. static void jiffiestotv(unsigned long jiffies, struct timeval *value)
  32. {
  33. value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
  34. value->tv_sec = jiffies / HZ;
  35. }
  36. int do_getitimer(int which, struct itimerval *value)
  37. {
  38. register unsigned long val, interval;
  39. switch (which) {
  40. case ITIMER_REAL:
  41. interval = current->it_real_incr;
  42. val = 0;
  43. /* 
  44.  * FIXME! This needs to be atomic, in case the kernel timer happens!
  45.  */
  46. if (timer_pending(&current->real_timer)) {
  47. val = current->real_timer.expires - jiffies;
  48. /* look out for negative/zero itimer.. */
  49. if ((long) val <= 0)
  50. val = 1;
  51. }
  52. break;
  53. case ITIMER_VIRTUAL:
  54. val = current->it_virt_value;
  55. interval = current->it_virt_incr;
  56. break;
  57. case ITIMER_PROF:
  58. val = current->it_prof_value;
  59. interval = current->it_prof_incr;
  60. break;
  61. default:
  62. return(-EINVAL);
  63. }
  64. jiffiestotv(val, &value->it_value);
  65. jiffiestotv(interval, &value->it_interval);
  66. return 0;
  67. }
  68. /* SMP: Only we modify our itimer values. */
  69. asmlinkage long sys_getitimer(int which, struct itimerval *value)
  70. {
  71. int error = -EFAULT;
  72. struct itimerval get_buffer;
  73. if (value) {
  74. error = do_getitimer(which, &get_buffer);
  75. if (!error &&
  76.     copy_to_user(value, &get_buffer, sizeof(get_buffer)))
  77. error = -EFAULT;
  78. }
  79. return error;
  80. }
  81. void it_real_fn(unsigned long __data)
  82. {
  83. struct task_struct * p = (struct task_struct *) __data;
  84. unsigned long interval;
  85. send_sig(SIGALRM, p, 1);
  86. interval = p->it_real_incr;
  87. if (interval) {
  88. if (interval > (unsigned long) LONG_MAX)
  89. interval = LONG_MAX;
  90. p->real_timer.expires = jiffies + interval;
  91. add_timer(&p->real_timer);
  92. }
  93. }
  94. int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
  95. {
  96. register unsigned long i, j;
  97. int k;
  98. i = tvtojiffies(&value->it_interval);
  99. j = tvtojiffies(&value->it_value);
  100. if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
  101. return k;
  102. switch (which) {
  103. case ITIMER_REAL:
  104. del_timer_sync(&current->real_timer);
  105. current->it_real_value = j;
  106. current->it_real_incr = i;
  107. if (!j)
  108. break;
  109. if (j > (unsigned long) LONG_MAX)
  110. j = LONG_MAX;
  111. i = j + jiffies;
  112. current->real_timer.expires = i;
  113. add_timer(&current->real_timer);
  114. break;
  115. case ITIMER_VIRTUAL:
  116. if (j)
  117. j++;
  118. current->it_virt_value = j;
  119. current->it_virt_incr = i;
  120. break;
  121. case ITIMER_PROF:
  122. if (j)
  123. j++;
  124. current->it_prof_value = j;
  125. current->it_prof_incr = i;
  126. break;
  127. default:
  128. return -EINVAL;
  129. }
  130. return 0;
  131. }
  132. /* SMP: Again, only we play with our itimers, and signals are SMP safe
  133.  *      now so that is not an issue at all anymore.
  134.  */
  135. asmlinkage long sys_setitimer(int which, struct itimerval *value,
  136.       struct itimerval *ovalue)
  137. {
  138. struct itimerval set_buffer, get_buffer;
  139. int error;
  140. if (value) {
  141. if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
  142. return -EFAULT;
  143. } else
  144. memset((char *) &set_buffer, 0, sizeof(set_buffer));
  145. error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
  146. if (error || !ovalue)
  147. return error;
  148. if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
  149. return -EFAULT; 
  150. return 0;
  151. }