76 */
77 if (secpolicy_clock_highres(CRED()) != 0) {
78 it->it_arg = NULL;
79 return (EPERM);
80 }
81
82 it->it_arg = kmem_zalloc(sizeof (cyclic_id_t), KM_SLEEP);
83
84 return (0);
85 }
86
87 static void
88 clock_highres_fire(void *arg)
89 {
90 itimer_t *it = (itimer_t *)arg;
91 hrtime_t *addr = &it->it_hrtime;
92 hrtime_t old = *addr, new = gethrtime();
93
94 do {
95 old = *addr;
96 } while (cas64((uint64_t *)addr, old, new) != old);
97
98 timer_fire(it);
99 }
100
101 static int
102 clock_highres_timer_settime(itimer_t *it, int flags,
103 const struct itimerspec *when)
104 {
105 cyclic_id_t cyc, *cycp = it->it_arg;
106 proc_t *p = curproc;
107 kthread_t *t = curthread;
108 cyc_time_t cyctime;
109 cyc_handler_t hdlr;
110 cpu_t *cpu;
111 cpupart_t *cpupart;
112 int pset;
113
114 cyctime.cyt_when = ts2hrt(&when->it_value);
115 cyctime.cyt_interval = ts2hrt(&when->it_interval);
116
218 cyclic_bind(cyc, cpu, pset == PS_NONE ? NULL : cpupart);
219
220 mutex_exit(&cpu_lock);
221
222 return (0);
223 }
224
225 static int
226 clock_highres_timer_gettime(itimer_t *it, struct itimerspec *when)
227 {
228 /*
229 * CLOCK_HIGHRES doesn't update it_itime.
230 */
231 hrtime_t start = ts2hrt(&it->it_itime.it_value);
232 hrtime_t interval = ts2hrt(&it->it_itime.it_interval);
233 hrtime_t diff, now = gethrtime();
234 hrtime_t *addr = &it->it_hrtime;
235 hrtime_t last;
236
237 /*
238 * We're using cas64() here only to assure that we slurp the entire
239 * timestamp atomically.
240 */
241 last = cas64((uint64_t *)addr, 0, 0);
242
243 *when = it->it_itime;
244
245 if (!timerspecisset(&when->it_value))
246 return (0);
247
248 if (start > now) {
249 /*
250 * We haven't gone off yet...
251 */
252 diff = start - now;
253 } else {
254 if (interval == 0) {
255 /*
256 * This is a one-shot which should have already
257 * fired; set it_value to 0.
258 */
259 timerspecclear(&when->it_value);
260 return (0);
261 }
|
76 */
77 if (secpolicy_clock_highres(CRED()) != 0) {
78 it->it_arg = NULL;
79 return (EPERM);
80 }
81
82 it->it_arg = kmem_zalloc(sizeof (cyclic_id_t), KM_SLEEP);
83
84 return (0);
85 }
86
87 static void
88 clock_highres_fire(void *arg)
89 {
90 itimer_t *it = (itimer_t *)arg;
91 hrtime_t *addr = &it->it_hrtime;
92 hrtime_t old = *addr, new = gethrtime();
93
94 do {
95 old = *addr;
96 } while (atomic_cas_64((uint64_t *)addr, old, new) != old);
97
98 timer_fire(it);
99 }
100
101 static int
102 clock_highres_timer_settime(itimer_t *it, int flags,
103 const struct itimerspec *when)
104 {
105 cyclic_id_t cyc, *cycp = it->it_arg;
106 proc_t *p = curproc;
107 kthread_t *t = curthread;
108 cyc_time_t cyctime;
109 cyc_handler_t hdlr;
110 cpu_t *cpu;
111 cpupart_t *cpupart;
112 int pset;
113
114 cyctime.cyt_when = ts2hrt(&when->it_value);
115 cyctime.cyt_interval = ts2hrt(&when->it_interval);
116
218 cyclic_bind(cyc, cpu, pset == PS_NONE ? NULL : cpupart);
219
220 mutex_exit(&cpu_lock);
221
222 return (0);
223 }
224
225 static int
226 clock_highres_timer_gettime(itimer_t *it, struct itimerspec *when)
227 {
228 /*
229 * CLOCK_HIGHRES doesn't update it_itime.
230 */
231 hrtime_t start = ts2hrt(&it->it_itime.it_value);
232 hrtime_t interval = ts2hrt(&it->it_itime.it_interval);
233 hrtime_t diff, now = gethrtime();
234 hrtime_t *addr = &it->it_hrtime;
235 hrtime_t last;
236
237 /*
238 * We're using atomic_cas_64() here only to assure that we slurp the
239 * entire timestamp atomically.
240 */
241 last = atomic_cas_64((uint64_t *)addr, 0, 0);
242
243 *when = it->it_itime;
244
245 if (!timerspecisset(&when->it_value))
246 return (0);
247
248 if (start > now) {
249 /*
250 * We haven't gone off yet...
251 */
252 diff = start - now;
253 } else {
254 if (interval == 0) {
255 /*
256 * This is a one-shot which should have already
257 * fired; set it_value to 0.
258 */
259 timerspecclear(&when->it_value);
260 return (0);
261 }
|