source: rtems-libbsd/freebsd/sys/kern/kern_time.c @ 2017a6d

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 2017a6d was 2017a6d, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/16 at 07:48:12

Directly use <sys/time.h> provided by Newlib

  • Property mode set to 100644
File size: 38.4 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * Copyright (c) 1982, 1986, 1989, 1993
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 4. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *      @(#)kern_time.c 8.1 (Berkeley) 6/10/93
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD$");
36
37#include <rtems/bsd/sys/param.h>
38#include <sys/systm.h>
39#include <sys/limits.h>
40#include <sys/clock.h>
41#include <rtems/bsd/sys/lock.h>
42#include <sys/mutex.h>
43#include <sys/sysproto.h>
44#include <sys/eventhandler.h>
45#include <sys/resourcevar.h>
46#include <sys/signalvar.h>
47#include <sys/kernel.h>
48#include <sys/syscallsubr.h>
49#include <sys/sysctl.h>
50#include <sys/sysent.h>
51#include <sys/priv.h>
52#include <sys/proc.h>
53#include <sys/posix4.h>
54#include <sys/time.h>
55#include <sys/timers.h>
56#include <sys/timetc.h>
57#include <sys/vnode.h>
58
59#include <vm/vm.h>
60#include <vm/vm_extern.h>
61
62#define MAX_CLOCKS      (CLOCK_MONOTONIC+1)
63#define CPUCLOCK_BIT            0x80000000
64#define CPUCLOCK_PROCESS_BIT    0x40000000
65#define CPUCLOCK_ID_MASK        (~(CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT))
66#define MAKE_THREAD_CPUCLOCK(tid)       (CPUCLOCK_BIT|(tid))
67#define MAKE_PROCESS_CPUCLOCK(pid)      \
68        (CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT|(pid))
69
70#ifndef __rtems__
71static struct kclock    posix_clocks[MAX_CLOCKS];
72static uma_zone_t       itimer_zone = NULL;
73
74/*
75 * Time of day and interval timer support.
76 *
77 * These routines provide the kernel entry points to get and set
78 * the time-of-day and per-process interval timers.  Subroutines
79 * here provide support for adding and subtracting timeval structures
80 * and decrementing interval timers, optionally reloading the interval
81 * timers when they expire.
82 */
83
84static int      settime(struct thread *, struct timeval *);
85#endif /* __rtems__ */
86static void     timevalfix(struct timeval *);
87
88#ifndef __rtems__
89static void     itimer_start(void);
90static int      itimer_init(void *, int, int);
91static void     itimer_fini(void *, int);
92static void     itimer_enter(struct itimer *);
93static void     itimer_leave(struct itimer *);
94static struct itimer *itimer_find(struct proc *, int);
95static void     itimers_alloc(struct proc *);
96static void     itimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp);
97static void     itimers_event_hook_exit(void *arg, struct proc *p);
98static int      realtimer_create(struct itimer *);
99static int      realtimer_gettime(struct itimer *, struct itimerspec *);
100static int      realtimer_settime(struct itimer *, int,
101                        struct itimerspec *, struct itimerspec *);
102static int      realtimer_delete(struct itimer *);
103static void     realtimer_clocktime(clockid_t, struct timespec *);
104static void     realtimer_expire(void *);
105
106int             register_posix_clock(int, struct kclock *);
107void            itimer_fire(struct itimer *it);
108int             itimespecfix(struct timespec *ts);
109
110#define CLOCK_CALL(clock, call, arglist)                \
111        ((*posix_clocks[clock].call) arglist)
112
113SYSINIT(posix_timer, SI_SUB_P1003_1B, SI_ORDER_FIRST+4, itimer_start, NULL);
114
115
116static int
117settime(struct thread *td, struct timeval *tv)
118{
119        struct timeval delta, tv1, tv2;
120        static struct timeval maxtime, laststep;
121        struct timespec ts;
122        int s;
123
124        s = splclock();
125        microtime(&tv1);
126        delta = *tv;
127        timevalsub(&delta, &tv1);
128
129        /*
130         * If the system is secure, we do not allow the time to be
131         * set to a value earlier than 1 second less than the highest
132         * time we have yet seen. The worst a miscreant can do in
133         * this circumstance is "freeze" time. He couldn't go
134         * back to the past.
135         *
136         * We similarly do not allow the clock to be stepped more
137         * than one second, nor more than once per second. This allows
138         * a miscreant to make the clock march double-time, but no worse.
139         */
140        if (securelevel_gt(td->td_ucred, 1) != 0) {
141                if (delta.tv_sec < 0 || delta.tv_usec < 0) {
142                        /*
143                         * Update maxtime to latest time we've seen.
144                         */
145                        if (tv1.tv_sec > maxtime.tv_sec)
146                                maxtime = tv1;
147                        tv2 = *tv;
148                        timevalsub(&tv2, &maxtime);
149                        if (tv2.tv_sec < -1) {
150                                tv->tv_sec = maxtime.tv_sec - 1;
151                                printf("Time adjustment clamped to -1 second\n");
152                        }
153                } else {
154                        if (tv1.tv_sec == laststep.tv_sec) {
155                                splx(s);
156                                return (EPERM);
157                        }
158                        if (delta.tv_sec > 1) {
159                                tv->tv_sec = tv1.tv_sec + 1;
160                                printf("Time adjustment clamped to +1 second\n");
161                        }
162                        laststep = *tv;
163                }
164        }
165
166        ts.tv_sec = tv->tv_sec;
167        ts.tv_nsec = tv->tv_usec * 1000;
168        mtx_lock(&Giant);
169        tc_setclock(&ts);
170        resettodr();
171        mtx_unlock(&Giant);
172        return (0);
173}
174
175#ifndef _SYS_SYSPROTO_H_
176struct clock_getcpuclockid2_args {
177        id_t id;
178        int which,
179        clockid_t *clock_id;
180};
181#endif
182/* ARGSUSED */
183int
184sys_clock_getcpuclockid2(struct thread *td, struct clock_getcpuclockid2_args *uap)
185{
186        clockid_t clk_id;
187        int error;
188
189        error = kern_clock_getcpuclockid2(td, uap->id, uap->which, &clk_id);
190        if (error == 0)
191                error = copyout(&clk_id, uap->clock_id, sizeof(clockid_t));
192        return (error);
193}
194
195int
196kern_clock_getcpuclockid2(struct thread *td, id_t id, int which,
197    clockid_t *clk_id)
198{
199        struct proc *p;
200        pid_t pid;
201        lwpid_t tid;
202        int error;
203
204        switch (which) {
205        case CPUCLOCK_WHICH_PID:
206                if (id != 0) {
207                        error = pget(id, PGET_CANSEE | PGET_NOTID, &p);
208                        if (error != 0)
209                                return (error);
210                        PROC_UNLOCK(p);
211                        pid = id;
212                } else {
213                        pid = td->td_proc->p_pid;
214                }
215                *clk_id = MAKE_PROCESS_CPUCLOCK(pid);
216                return (0);
217        case CPUCLOCK_WHICH_TID:
218                tid = id == 0 ? td->td_tid : id;
219                *clk_id = MAKE_THREAD_CPUCLOCK(tid);
220                return (0);
221        default:
222                return (EINVAL);
223        }
224}
225
226#ifndef _SYS_SYSPROTO_H_
227struct clock_gettime_args {
228        clockid_t clock_id;
229        struct  timespec *tp;
230};
231#endif
232#ifndef __rtems__
233/* ARGSUSED */
234int
235sys_clock_gettime(struct thread *td, struct clock_gettime_args *uap)
236{
237        struct timespec ats;
238        int error;
239
240        error = kern_clock_gettime(td, uap->clock_id, &ats);
241        if (error == 0)
242                error = copyout(&ats, uap->tp, sizeof(ats));
243
244        return (error);
245}
246#endif
247
248#ifndef __rtems__
249static inline void
250cputick2timespec(uint64_t runtime, struct timespec *ats)
251{
252        runtime = cputick2usec(runtime);
253        ats->tv_sec = runtime / 1000000;
254        ats->tv_nsec = runtime % 1000000 * 1000;
255}
256
257static void
258get_thread_cputime(struct thread *targettd, struct timespec *ats)
259{
260        uint64_t runtime, curtime, switchtime;
261
262        if (targettd == NULL) { /* current thread */
263                critical_enter();
264                switchtime = PCPU_GET(switchtime);
265                curtime = cpu_ticks();
266                runtime = curthread->td_runtime;
267                critical_exit();
268                runtime += curtime - switchtime;
269        } else {
270                thread_lock(targettd);
271                runtime = targettd->td_runtime;
272                thread_unlock(targettd);
273        }
274        cputick2timespec(runtime, ats);
275}
276
277static void
278get_process_cputime(struct proc *targetp, struct timespec *ats)
279{
280        uint64_t runtime;
281        struct rusage ru;
282
283        PROC_SLOCK(targetp);
284        rufetch(targetp, &ru);
285        runtime = targetp->p_rux.rux_runtime;
286        PROC_SUNLOCK(targetp);
287        cputick2timespec(runtime, ats);
288}
289
290static int
291get_cputime(struct thread *td, clockid_t clock_id, struct timespec *ats)
292{
293        struct proc *p, *p2;
294        struct thread *td2;
295        lwpid_t tid;
296        pid_t pid;
297        int error;
298
299        p = td->td_proc;
300        if ((clock_id & CPUCLOCK_PROCESS_BIT) == 0) {
301                tid = clock_id & CPUCLOCK_ID_MASK;
302                td2 = tdfind(tid, p->p_pid);
303                if (td2 == NULL)
304                        return (EINVAL);
305                get_thread_cputime(td2, ats);
306                PROC_UNLOCK(td2->td_proc);
307        } else {
308                pid = clock_id & CPUCLOCK_ID_MASK;
309                error = pget(pid, PGET_CANSEE, &p2);
310                if (error != 0)
311                        return (EINVAL);
312                get_process_cputime(p2, ats);
313                PROC_UNLOCK(p2);
314        }
315        return (0);
316}
317
318int
319kern_clock_gettime(struct thread *td, clockid_t clock_id, struct timespec *ats)
320{
321        struct timeval sys, user;
322        struct proc *p;
323
324        p = td->td_proc;
325        switch (clock_id) {
326        case CLOCK_REALTIME:            /* Default to precise. */
327        case CLOCK_REALTIME_PRECISE:
328                nanotime(ats);
329                break;
330        case CLOCK_REALTIME_FAST:
331                getnanotime(ats);
332                break;
333        case CLOCK_VIRTUAL:
334                PROC_LOCK(p);
335                PROC_SLOCK(p);
336                calcru(p, &user, &sys);
337                PROC_SUNLOCK(p);
338                PROC_UNLOCK(p);
339                TIMEVAL_TO_TIMESPEC(&user, ats);
340                break;
341        case CLOCK_PROF:
342                PROC_LOCK(p);
343                PROC_SLOCK(p);
344                calcru(p, &user, &sys);
345                PROC_SUNLOCK(p);
346                PROC_UNLOCK(p);
347                timevaladd(&user, &sys);
348                TIMEVAL_TO_TIMESPEC(&user, ats);
349                break;
350        case CLOCK_MONOTONIC:           /* Default to precise. */
351        case CLOCK_MONOTONIC_PRECISE:
352        case CLOCK_UPTIME:
353        case CLOCK_UPTIME_PRECISE:
354                nanouptime(ats);
355                break;
356        case CLOCK_UPTIME_FAST:
357        case CLOCK_MONOTONIC_FAST:
358                getnanouptime(ats);
359                break;
360        case CLOCK_SECOND:
361                ats->tv_sec = time_second;
362                ats->tv_nsec = 0;
363                break;
364        case CLOCK_THREAD_CPUTIME_ID:
365                get_thread_cputime(NULL, ats);
366                break;
367        case CLOCK_PROCESS_CPUTIME_ID:
368                PROC_LOCK(p);
369                get_process_cputime(p, ats);
370                PROC_UNLOCK(p);
371                break;
372        default:
373                if ((int)clock_id >= 0)
374                        return (EINVAL);
375                return (get_cputime(td, clock_id, ats));
376        }
377        return (0);
378}
379#endif
380
381#ifndef _SYS_SYSPROTO_H_
382struct clock_settime_args {
383        clockid_t clock_id;
384        const struct    timespec *tp;
385};
386#endif
387#ifndef __rtems__
388/* ARGSUSED */
389int
390sys_clock_settime(struct thread *td, struct clock_settime_args *uap)
391{
392        struct timespec ats;
393        int error;
394
395        if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0)
396                return (error);
397        return (kern_clock_settime(td, uap->clock_id, &ats));
398}
399
400int
401kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats)
402{
403        struct timeval atv;
404        int error;
405
406        if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0)
407                return (error);
408        if (clock_id != CLOCK_REALTIME)
409                return (EINVAL);
410        if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000)
411                return (EINVAL);
412        /* XXX Don't convert nsec->usec and back */
413        TIMESPEC_TO_TIMEVAL(&atv, ats);
414        error = settime(td, &atv);
415        return (error);
416}
417#endif
418
419#ifndef _SYS_SYSPROTO_H_
420struct clock_getres_args {
421        clockid_t clock_id;
422        struct  timespec *tp;
423};
424#endif
425#ifndef __rtems__
426int
427sys_clock_getres(struct thread *td, struct clock_getres_args *uap)
428{
429        struct timespec ts;
430        int error;
431
432        if (uap->tp == NULL)
433                return (0);
434
435        error = kern_clock_getres(td, uap->clock_id, &ts);
436        if (error == 0)
437                error = copyout(&ts, uap->tp, sizeof(ts));
438        return (error);
439}
440
441int
442kern_clock_getres(struct thread *td, clockid_t clock_id, struct timespec *ts)
443{
444
445        ts->tv_sec = 0;
446        switch (clock_id) {
447        case CLOCK_REALTIME:
448        case CLOCK_REALTIME_FAST:
449        case CLOCK_REALTIME_PRECISE:
450        case CLOCK_MONOTONIC:
451        case CLOCK_MONOTONIC_FAST:
452        case CLOCK_MONOTONIC_PRECISE:
453        case CLOCK_UPTIME:
454        case CLOCK_UPTIME_FAST:
455        case CLOCK_UPTIME_PRECISE:
456                /*
457                 * Round up the result of the division cheaply by adding 1.
458                 * Rounding up is especially important if rounding down
459                 * would give 0.  Perfect rounding is unimportant.
460                 */
461                ts->tv_nsec = 1000000000 / tc_getfrequency() + 1;
462                break;
463        case CLOCK_VIRTUAL:
464        case CLOCK_PROF:
465                /* Accurately round up here because we can do so cheaply. */
466                ts->tv_nsec = (1000000000 + hz - 1) / hz;
467                break;
468        case CLOCK_SECOND:
469                ts->tv_sec = 1;
470                ts->tv_nsec = 0;
471                break;
472        case CLOCK_THREAD_CPUTIME_ID:
473        case CLOCK_PROCESS_CPUTIME_ID:
474        cputime:
475                /* sync with cputick2usec */
476                ts->tv_nsec = 1000000 / cpu_tickrate();
477                if (ts->tv_nsec == 0)
478                        ts->tv_nsec = 1000;
479                break;
480        default:
481                if ((int)clock_id < 0)
482                        goto cputime;
483                return (EINVAL);
484        }
485        return (0);
486}
487#endif
488
489static int nanowait;
490
491int
492kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt)
493{
494        struct timespec ts, ts2, ts3;
495        struct timeval tv;
496        int error;
497
498        if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
499                return (EINVAL);
500        if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0))
501                return (0);
502        getnanouptime(&ts);
503        timespecadd(&ts, rqt);
504        TIMESPEC_TO_TIMEVAL(&tv, rqt);
505        for (;;) {
506                error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp",
507                    tvtohz(&tv));
508                getnanouptime(&ts2);
509                if (error != EWOULDBLOCK) {
510                        if (error == ERESTART)
511                                error = EINTR;
512                        if (rmt != NULL) {
513                                timespecsub(&ts, &ts2);
514                                if (ts.tv_sec < 0)
515                                        timespecclear(&ts);
516                                *rmt = ts;
517                        }
518                        return (error);
519                }
520                if (timespeccmp(&ts2, &ts, >=))
521                        return (0);
522                ts3 = ts;
523                timespecsub(&ts3, &ts2);
524                TIMESPEC_TO_TIMEVAL(&tv, &ts3);
525        }
526}
527
528#ifndef _SYS_SYSPROTO_H_
529struct nanosleep_args {
530        struct  timespec *rqtp;
531        struct  timespec *rmtp;
532};
533#endif
534/* ARGSUSED */
535int
536sys_nanosleep(struct thread *td, struct nanosleep_args *uap)
537{
538        struct timespec rmt, rqt;
539        int error;
540
541        error = copyin(uap->rqtp, &rqt, sizeof(rqt));
542        if (error)
543                return (error);
544
545        if (uap->rmtp &&
546            !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
547                        return (EFAULT);
548        error = kern_nanosleep(td, &rqt, &rmt);
549        if (error && uap->rmtp) {
550                int error2;
551
552                error2 = copyout(&rmt, uap->rmtp, sizeof(rmt));
553                if (error2)
554                        error = error2;
555        }
556        return (error);
557}
558
559#ifndef _SYS_SYSPROTO_H_
560struct gettimeofday_args {
561        struct  timeval *tp;
562        struct  timezone *tzp;
563};
564#endif
565/* ARGSUSED */
566int
567sys_gettimeofday(struct thread *td, struct gettimeofday_args *uap)
568{
569        struct timeval atv;
570        struct timezone rtz;
571        int error = 0;
572
573        if (uap->tp) {
574                microtime(&atv);
575                error = copyout(&atv, uap->tp, sizeof (atv));
576        }
577        if (error == 0 && uap->tzp != NULL) {
578                rtz.tz_minuteswest = tz_minuteswest;
579                rtz.tz_dsttime = tz_dsttime;
580                error = copyout(&rtz, uap->tzp, sizeof (rtz));
581        }
582        return (error);
583}
584
585#ifndef _SYS_SYSPROTO_H_
586struct settimeofday_args {
587        struct  timeval *tv;
588        struct  timezone *tzp;
589};
590#endif
591/* ARGSUSED */
592int
593sys_settimeofday(struct thread *td, struct settimeofday_args *uap)
594{
595        struct timeval atv, *tvp;
596        struct timezone atz, *tzp;
597        int error;
598
599        if (uap->tv) {
600                error = copyin(uap->tv, &atv, sizeof(atv));
601                if (error)
602                        return (error);
603                tvp = &atv;
604        } else
605                tvp = NULL;
606        if (uap->tzp) {
607                error = copyin(uap->tzp, &atz, sizeof(atz));
608                if (error)
609                        return (error);
610                tzp = &atz;
611        } else
612                tzp = NULL;
613        return (kern_settimeofday(td, tvp, tzp));
614}
615
616int
617kern_settimeofday(struct thread *td, struct timeval *tv, struct timezone *tzp)
618{
619        int error;
620
621        error = priv_check(td, PRIV_SETTIMEOFDAY);
622        if (error)
623                return (error);
624        /* Verify all parameters before changing time. */
625        if (tv) {
626                if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
627                        return (EINVAL);
628                error = settime(td, tv);
629        }
630        if (tzp && error == 0) {
631                tz_minuteswest = tzp->tz_minuteswest;
632                tz_dsttime = tzp->tz_dsttime;
633        }
634        return (error);
635}
636
637/*
638 * Get value of an interval timer.  The process virtual and profiling virtual
639 * time timers are kept in the p_stats area, since they can be swapped out.
640 * These are kept internally in the way they are specified externally: in
641 * time until they expire.
642 *
643 * The real time interval timer is kept in the process table slot for the
644 * process, and its value (it_value) is kept as an absolute time rather than
645 * as a delta, so that it is easy to keep periodic real-time signals from
646 * drifting.
647 *
648 * Virtual time timers are processed in the hardclock() routine of
649 * kern_clock.c.  The real time timer is processed by a timeout routine,
650 * called from the softclock() routine.  Since a callout may be delayed in
651 * real time due to interrupt processing in the system, it is possible for
652 * the real time timeout routine (realitexpire, given below), to be delayed
653 * in real time past when it is supposed to occur.  It does not suffice,
654 * therefore, to reload the real timer .it_value from the real time timers
655 * .it_interval.  Rather, we compute the next time in absolute time the timer
656 * should go off.
657 */
658#ifndef _SYS_SYSPROTO_H_
659struct getitimer_args {
660        u_int   which;
661        struct  itimerval *itv;
662};
663#endif
664int
665sys_getitimer(struct thread *td, struct getitimer_args *uap)
666{
667        struct itimerval aitv;
668        int error;
669
670        error = kern_getitimer(td, uap->which, &aitv);
671        if (error != 0)
672                return (error);
673        return (copyout(&aitv, uap->itv, sizeof (struct itimerval)));
674}
675
676int
677kern_getitimer(struct thread *td, u_int which, struct itimerval *aitv)
678{
679        struct proc *p = td->td_proc;
680        struct timeval ctv;
681
682        if (which > ITIMER_PROF)
683                return (EINVAL);
684
685        if (which == ITIMER_REAL) {
686                /*
687                 * Convert from absolute to relative time in .it_value
688                 * part of real time timer.  If time for real time timer
689                 * has passed return 0, else return difference between
690                 * current time and time for the timer to go off.
691                 */
692                PROC_LOCK(p);
693                *aitv = p->p_realtimer;
694                PROC_UNLOCK(p);
695                if (timevalisset(&aitv->it_value)) {
696                        getmicrouptime(&ctv);
697                        if (timevalcmp(&aitv->it_value, &ctv, <))
698                                timevalclear(&aitv->it_value);
699                        else
700                                timevalsub(&aitv->it_value, &ctv);
701                }
702        } else {
703                PROC_SLOCK(p);
704                *aitv = p->p_stats->p_timer[which];
705                PROC_SUNLOCK(p);
706        }
707        return (0);
708}
709
710#ifndef _SYS_SYSPROTO_H_
711struct setitimer_args {
712        u_int   which;
713        struct  itimerval *itv, *oitv;
714};
715#endif
716int
717sys_setitimer(struct thread *td, struct setitimer_args *uap)
718{
719        struct itimerval aitv, oitv;
720        int error;
721
722        if (uap->itv == NULL) {
723                uap->itv = uap->oitv;
724                return (sys_getitimer(td, (struct getitimer_args *)uap));
725        }
726
727        if ((error = copyin(uap->itv, &aitv, sizeof(struct itimerval))))
728                return (error);
729        error = kern_setitimer(td, uap->which, &aitv, &oitv);
730        if (error != 0 || uap->oitv == NULL)
731                return (error);
732        return (copyout(&oitv, uap->oitv, sizeof(struct itimerval)));
733}
734
735int
736kern_setitimer(struct thread *td, u_int which, struct itimerval *aitv,
737    struct itimerval *oitv)
738{
739        struct proc *p = td->td_proc;
740        struct timeval ctv;
741
742        if (aitv == NULL)
743                return (kern_getitimer(td, which, oitv));
744
745        if (which > ITIMER_PROF)
746                return (EINVAL);
747        if (itimerfix(&aitv->it_value))
748                return (EINVAL);
749        if (!timevalisset(&aitv->it_value))
750                timevalclear(&aitv->it_interval);
751        else if (itimerfix(&aitv->it_interval))
752                return (EINVAL);
753
754        if (which == ITIMER_REAL) {
755                PROC_LOCK(p);
756                if (timevalisset(&p->p_realtimer.it_value))
757                        callout_stop(&p->p_itcallout);
758                getmicrouptime(&ctv);
759                if (timevalisset(&aitv->it_value)) {
760                        callout_reset(&p->p_itcallout, tvtohz(&aitv->it_value),
761                            realitexpire, p);
762                        timevaladd(&aitv->it_value, &ctv);
763                }
764                *oitv = p->p_realtimer;
765                p->p_realtimer = *aitv;
766                PROC_UNLOCK(p);
767                if (timevalisset(&oitv->it_value)) {
768                        if (timevalcmp(&oitv->it_value, &ctv, <))
769                                timevalclear(&oitv->it_value);
770                        else
771                                timevalsub(&oitv->it_value, &ctv);
772                }
773        } else {
774                PROC_SLOCK(p);
775                *oitv = p->p_stats->p_timer[which];
776                p->p_stats->p_timer[which] = *aitv;
777                PROC_SUNLOCK(p);
778        }
779        return (0);
780}
781
782/*
783 * Real interval timer expired:
784 * send process whose timer expired an alarm signal.
785 * If time is not set up to reload, then just return.
786 * Else compute next time timer should go off which is > current time.
787 * This is where delay in processing this timeout causes multiple
788 * SIGALRM calls to be compressed into one.
789 * tvtohz() always adds 1 to allow for the time until the next clock
790 * interrupt being strictly less than 1 clock tick, but we don't want
791 * that here since we want to appear to be in sync with the clock
792 * interrupt even when we're delayed.
793 */
794void
795realitexpire(void *arg)
796{
797        struct proc *p;
798        struct timeval ctv, ntv;
799
800        p = (struct proc *)arg;
801        kern_psignal(p, SIGALRM);
802        if (!timevalisset(&p->p_realtimer.it_interval)) {
803                timevalclear(&p->p_realtimer.it_value);
804                if (p->p_flag & P_WEXIT)
805                        wakeup(&p->p_itcallout);
806                return;
807        }
808        for (;;) {
809                timevaladd(&p->p_realtimer.it_value,
810                    &p->p_realtimer.it_interval);
811                getmicrouptime(&ctv);
812                if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) {
813                        ntv = p->p_realtimer.it_value;
814                        timevalsub(&ntv, &ctv);
815                        callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1,
816                            realitexpire, p);
817                        return;
818                }
819        }
820        /*NOTREACHED*/
821}
822#endif /* __rtems__ */
823
824/*
825 * Check that a proposed value to load into the .it_value or
826 * .it_interval part of an interval timer is acceptable, and
827 * fix it to have at least minimal value (i.e. if it is less
828 * than the resolution of the clock, round it up.)
829 */
830int
831itimerfix(struct timeval *tv)
832{
833
834        if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000)
835                return (EINVAL);
836        if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
837                tv->tv_usec = tick;
838        return (0);
839}
840
841#ifndef __rtems__
842/*
843 * Decrement an interval timer by a specified number
844 * of microseconds, which must be less than a second,
845 * i.e. < 1000000.  If the timer expires, then reload
846 * it.  In this case, carry over (usec - old value) to
847 * reduce the value reloaded into the timer so that
848 * the timer does not drift.  This routine assumes
849 * that it is called in a context where the timers
850 * on which it is operating cannot change in value.
851 */
852int
853itimerdecr(struct itimerval *itp, int usec)
854{
855
856        if (itp->it_value.tv_usec < usec) {
857                if (itp->it_value.tv_sec == 0) {
858                        /* expired, and already in next interval */
859                        usec -= itp->it_value.tv_usec;
860                        goto expire;
861                }
862                itp->it_value.tv_usec += 1000000;
863                itp->it_value.tv_sec--;
864        }
865        itp->it_value.tv_usec -= usec;
866        usec = 0;
867        if (timevalisset(&itp->it_value))
868                return (1);
869        /* expired, exactly at end of interval */
870expire:
871        if (timevalisset(&itp->it_interval)) {
872                itp->it_value = itp->it_interval;
873                itp->it_value.tv_usec -= usec;
874                if (itp->it_value.tv_usec < 0) {
875                        itp->it_value.tv_usec += 1000000;
876                        itp->it_value.tv_sec--;
877                }
878        } else
879                itp->it_value.tv_usec = 0;              /* sec is already 0 */
880        return (0);
881}
882#endif /* __rtems__ */
883
884/*
885 * Add and subtract routines for timevals.
886 * N.B.: subtract routine doesn't deal with
887 * results which are before the beginning,
888 * it just gets very confused in this case.
889 * Caveat emptor.
890 */
891void
892timevaladd(struct timeval *t1, const struct timeval *t2)
893{
894
895        t1->tv_sec += t2->tv_sec;
896        t1->tv_usec += t2->tv_usec;
897        timevalfix(t1);
898}
899
900void
901timevalsub(struct timeval *t1, const struct timeval *t2)
902{
903
904        t1->tv_sec -= t2->tv_sec;
905        t1->tv_usec -= t2->tv_usec;
906        timevalfix(t1);
907}
908
909static void
910timevalfix(struct timeval *t1)
911{
912
913        if (t1->tv_usec < 0) {
914                t1->tv_sec--;
915                t1->tv_usec += 1000000;
916        }
917        if (t1->tv_usec >= 1000000) {
918                t1->tv_sec++;
919                t1->tv_usec -= 1000000;
920        }
921}
922
923/*
924 * ratecheck(): simple time-based rate-limit checking.
925 */
926int
927ratecheck(struct timeval *lasttime, const struct timeval *mininterval)
928{
929        struct timeval tv, delta;
930        int rv = 0;
931
932        getmicrouptime(&tv);            /* NB: 10ms precision */
933        delta = tv;
934        timevalsub(&delta, lasttime);
935
936        /*
937         * check for 0,0 is so that the message will be seen at least once,
938         * even if interval is huge.
939         */
940        if (timevalcmp(&delta, mininterval, >=) ||
941            (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {
942                *lasttime = tv;
943                rv = 1;
944        }
945
946        return (rv);
947}
948
949/*
950 * ppsratecheck(): packets (or events) per second limitation.
951 *
952 * Return 0 if the limit is to be enforced (e.g. the caller
953 * should drop a packet because of the rate limitation).
954 *
955 * maxpps of 0 always causes zero to be returned.  maxpps of -1
956 * always causes 1 to be returned; this effectively defeats rate
957 * limiting.
958 *
959 * Note that we maintain the struct timeval for compatibility
960 * with other bsd systems.  We reuse the storage and just monitor
961 * clock ticks for minimal overhead. 
962 */
963int
964ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
965{
966        int now;
967
968        /*
969         * Reset the last time and counter if this is the first call
970         * or more than a second has passed since the last update of
971         * lasttime.
972         */
973        now = ticks;
974        if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) {
975                lasttime->tv_sec = now;
976                *curpps = 1;
977                return (maxpps != 0);
978        } else {
979                (*curpps)++;            /* NB: ignore potential overflow */
980                return (maxpps < 0 || *curpps < maxpps);
981        }
982}
983
984#ifndef __rtems__
985static void
986itimer_start(void)
987{
988        struct kclock rt_clock = {
989                .timer_create  = realtimer_create,
990                .timer_delete  = realtimer_delete,
991                .timer_settime = realtimer_settime,
992                .timer_gettime = realtimer_gettime,
993                .event_hook    = NULL
994        };
995
996        itimer_zone = uma_zcreate("itimer", sizeof(struct itimer),
997                NULL, NULL, itimer_init, itimer_fini, UMA_ALIGN_PTR, 0);
998        register_posix_clock(CLOCK_REALTIME,  &rt_clock);
999        register_posix_clock(CLOCK_MONOTONIC, &rt_clock);
1000        p31b_setcfg(CTL_P1003_1B_TIMERS, 200112L);
1001        p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, INT_MAX);
1002        p31b_setcfg(CTL_P1003_1B_TIMER_MAX, TIMER_MAX);
1003        EVENTHANDLER_REGISTER(process_exit, itimers_event_hook_exit,
1004                (void *)ITIMER_EV_EXIT, EVENTHANDLER_PRI_ANY);
1005        EVENTHANDLER_REGISTER(process_exec, itimers_event_hook_exec,
1006                (void *)ITIMER_EV_EXEC, EVENTHANDLER_PRI_ANY);
1007}
1008
1009int
1010register_posix_clock(int clockid, struct kclock *clk)
1011{
1012        if ((unsigned)clockid >= MAX_CLOCKS) {
1013                printf("%s: invalid clockid\n", __func__);
1014                return (0);
1015        }
1016        posix_clocks[clockid] = *clk;
1017        return (1);
1018}
1019
1020static int
1021itimer_init(void *mem, int size, int flags)
1022{
1023        struct itimer *it;
1024
1025        it = (struct itimer *)mem;
1026        mtx_init(&it->it_mtx, "itimer lock", NULL, MTX_DEF);
1027        return (0);
1028}
1029
1030static void
1031itimer_fini(void *mem, int size)
1032{
1033        struct itimer *it;
1034
1035        it = (struct itimer *)mem;
1036        mtx_destroy(&it->it_mtx);
1037}
1038
1039static void
1040itimer_enter(struct itimer *it)
1041{
1042
1043        mtx_assert(&it->it_mtx, MA_OWNED);
1044        it->it_usecount++;
1045}
1046
1047static void
1048itimer_leave(struct itimer *it)
1049{
1050
1051        mtx_assert(&it->it_mtx, MA_OWNED);
1052        KASSERT(it->it_usecount > 0, ("invalid it_usecount"));
1053
1054        if (--it->it_usecount == 0 && (it->it_flags & ITF_WANTED) != 0)
1055                wakeup(it);
1056}
1057
1058#ifndef _SYS_SYSPROTO_H_
1059struct ktimer_create_args {
1060        clockid_t clock_id;
1061        struct sigevent * evp;
1062        int * timerid;
1063};
1064#endif
1065int
1066sys_ktimer_create(struct thread *td, struct ktimer_create_args *uap)
1067{
1068        struct sigevent *evp, ev;
1069        int id;
1070        int error;
1071
1072        if (uap->evp == NULL) {
1073                evp = NULL;
1074        } else {
1075                error = copyin(uap->evp, &ev, sizeof(ev));
1076                if (error != 0)
1077                        return (error);
1078                evp = &ev;
1079        }
1080        error = kern_ktimer_create(td, uap->clock_id, evp, &id, -1);
1081        if (error == 0) {
1082                error = copyout(&id, uap->timerid, sizeof(int));
1083                if (error != 0)
1084                        kern_ktimer_delete(td, id);
1085        }
1086        return (error);
1087}
1088
1089int
1090kern_ktimer_create(struct thread *td, clockid_t clock_id, struct sigevent *evp,
1091    int *timerid, int preset_id)
1092{
1093        struct proc *p = td->td_proc;
1094        struct itimer *it;
1095        int id;
1096        int error;
1097
1098        if (clock_id < 0 || clock_id >= MAX_CLOCKS)
1099                return (EINVAL);
1100
1101        if (posix_clocks[clock_id].timer_create == NULL)
1102                return (EINVAL);
1103
1104        if (evp != NULL) {
1105                if (evp->sigev_notify != SIGEV_NONE &&
1106                    evp->sigev_notify != SIGEV_SIGNAL &&
1107                    evp->sigev_notify != SIGEV_THREAD_ID)
1108                        return (EINVAL);
1109                if ((evp->sigev_notify == SIGEV_SIGNAL ||
1110                     evp->sigev_notify == SIGEV_THREAD_ID) &&
1111                        !_SIG_VALID(evp->sigev_signo))
1112                        return (EINVAL);
1113        }
1114       
1115        if (p->p_itimers == NULL)
1116                itimers_alloc(p);
1117       
1118        it = uma_zalloc(itimer_zone, M_WAITOK);
1119        it->it_flags = 0;
1120        it->it_usecount = 0;
1121        it->it_active = 0;
1122        timespecclear(&it->it_time.it_value);
1123        timespecclear(&it->it_time.it_interval);
1124        it->it_overrun = 0;
1125        it->it_overrun_last = 0;
1126        it->it_clockid = clock_id;
1127        it->it_timerid = -1;
1128        it->it_proc = p;
1129        ksiginfo_init(&it->it_ksi);
1130        it->it_ksi.ksi_flags |= KSI_INS | KSI_EXT;
1131        error = CLOCK_CALL(clock_id, timer_create, (it));
1132        if (error != 0)
1133                goto out;
1134
1135        PROC_LOCK(p);
1136        if (preset_id != -1) {
1137                KASSERT(preset_id >= 0 && preset_id < 3, ("invalid preset_id"));
1138                id = preset_id;
1139                if (p->p_itimers->its_timers[id] != NULL) {
1140                        PROC_UNLOCK(p);
1141                        error = 0;
1142                        goto out;
1143                }
1144        } else {
1145                /*
1146                 * Find a free timer slot, skipping those reserved
1147                 * for setitimer().
1148                 */
1149                for (id = 3; id < TIMER_MAX; id++)
1150                        if (p->p_itimers->its_timers[id] == NULL)
1151                                break;
1152                if (id == TIMER_MAX) {
1153                        PROC_UNLOCK(p);
1154                        error = EAGAIN;
1155                        goto out;
1156                }
1157        }
1158        it->it_timerid = id;
1159        p->p_itimers->its_timers[id] = it;
1160        if (evp != NULL)
1161                it->it_sigev = *evp;
1162        else {
1163                it->it_sigev.sigev_notify = SIGEV_SIGNAL;
1164                switch (clock_id) {
1165                default:
1166                case CLOCK_REALTIME:
1167                        it->it_sigev.sigev_signo = SIGALRM;
1168                        break;
1169                case CLOCK_VIRTUAL:
1170                        it->it_sigev.sigev_signo = SIGVTALRM;
1171                        break;
1172                case CLOCK_PROF:
1173                        it->it_sigev.sigev_signo = SIGPROF;
1174                        break;
1175                }
1176                it->it_sigev.sigev_value.sival_int = id;
1177        }
1178
1179        if (it->it_sigev.sigev_notify == SIGEV_SIGNAL ||
1180            it->it_sigev.sigev_notify == SIGEV_THREAD_ID) {
1181                it->it_ksi.ksi_signo = it->it_sigev.sigev_signo;
1182                it->it_ksi.ksi_code = SI_TIMER;
1183                it->it_ksi.ksi_value = it->it_sigev.sigev_value;
1184                it->it_ksi.ksi_timerid = id;
1185        }
1186        PROC_UNLOCK(p);
1187        *timerid = id;
1188        return (0);
1189
1190out:
1191        ITIMER_LOCK(it);
1192        CLOCK_CALL(it->it_clockid, timer_delete, (it));
1193        ITIMER_UNLOCK(it);
1194        uma_zfree(itimer_zone, it);
1195        return (error);
1196}
1197
1198#ifndef _SYS_SYSPROTO_H_
1199struct ktimer_delete_args {
1200        int timerid;
1201};
1202#endif
1203int
1204sys_ktimer_delete(struct thread *td, struct ktimer_delete_args *uap)
1205{
1206
1207        return (kern_ktimer_delete(td, uap->timerid));
1208}
1209
1210static struct itimer *
1211itimer_find(struct proc *p, int timerid)
1212{
1213        struct itimer *it;
1214
1215        PROC_LOCK_ASSERT(p, MA_OWNED);
1216        if ((p->p_itimers == NULL) ||
1217            (timerid < 0) || (timerid >= TIMER_MAX) ||
1218            (it = p->p_itimers->its_timers[timerid]) == NULL) {
1219                return (NULL);
1220        }
1221        ITIMER_LOCK(it);
1222        if ((it->it_flags & ITF_DELETING) != 0) {
1223                ITIMER_UNLOCK(it);
1224                it = NULL;
1225        }
1226        return (it);
1227}
1228
1229int
1230kern_ktimer_delete(struct thread *td, int timerid)
1231{
1232        struct proc *p = td->td_proc;
1233        struct itimer *it;
1234
1235        PROC_LOCK(p);
1236        it = itimer_find(p, timerid);
1237        if (it == NULL) {
1238                PROC_UNLOCK(p);
1239                return (EINVAL);
1240        }
1241        PROC_UNLOCK(p);
1242
1243        it->it_flags |= ITF_DELETING;
1244        while (it->it_usecount > 0) {
1245                it->it_flags |= ITF_WANTED;
1246                msleep(it, &it->it_mtx, PPAUSE, "itimer", 0);
1247        }
1248        it->it_flags &= ~ITF_WANTED;
1249        CLOCK_CALL(it->it_clockid, timer_delete, (it));
1250        ITIMER_UNLOCK(it);
1251
1252        PROC_LOCK(p);
1253        if (KSI_ONQ(&it->it_ksi))
1254                sigqueue_take(&it->it_ksi);
1255        p->p_itimers->its_timers[timerid] = NULL;
1256        PROC_UNLOCK(p);
1257        uma_zfree(itimer_zone, it);
1258        return (0);
1259}
1260
1261#ifndef _SYS_SYSPROTO_H_
1262struct ktimer_settime_args {
1263        int timerid;
1264        int flags;
1265        const struct itimerspec * value;
1266        struct itimerspec * ovalue;
1267};
1268#endif
1269int
1270sys_ktimer_settime(struct thread *td, struct ktimer_settime_args *uap)
1271{
1272        struct itimerspec val, oval, *ovalp;
1273        int error;
1274
1275        error = copyin(uap->value, &val, sizeof(val));
1276        if (error != 0)
1277                return (error);
1278        ovalp = uap->ovalue != NULL ? &oval : NULL;
1279        error = kern_ktimer_settime(td, uap->timerid, uap->flags, &val, ovalp);
1280        if (error == 0 && uap->ovalue != NULL)
1281                error = copyout(ovalp, uap->ovalue, sizeof(*ovalp));
1282        return (error);
1283}
1284
1285int
1286kern_ktimer_settime(struct thread *td, int timer_id, int flags,
1287    struct itimerspec *val, struct itimerspec *oval)
1288{
1289        struct proc *p;
1290        struct itimer *it;
1291        int error;
1292
1293        p = td->td_proc;
1294        PROC_LOCK(p);
1295        if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) {
1296                PROC_UNLOCK(p);
1297                error = EINVAL;
1298        } else {
1299                PROC_UNLOCK(p);
1300                itimer_enter(it);
1301                error = CLOCK_CALL(it->it_clockid, timer_settime, (it,
1302                    flags, val, oval));
1303                itimer_leave(it);
1304                ITIMER_UNLOCK(it);
1305        }
1306        return (error);
1307}
1308
1309#ifndef _SYS_SYSPROTO_H_
1310struct ktimer_gettime_args {
1311        int timerid;
1312        struct itimerspec * value;
1313};
1314#endif
1315int
1316sys_ktimer_gettime(struct thread *td, struct ktimer_gettime_args *uap)
1317{
1318        struct itimerspec val;
1319        int error;
1320
1321        error = kern_ktimer_gettime(td, uap->timerid, &val);
1322        if (error == 0)
1323                error = copyout(&val, uap->value, sizeof(val));
1324        return (error);
1325}
1326
1327int
1328kern_ktimer_gettime(struct thread *td, int timer_id, struct itimerspec *val)
1329{
1330        struct proc *p;
1331        struct itimer *it;
1332        int error;
1333
1334        p = td->td_proc;
1335        PROC_LOCK(p);
1336        if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) {
1337                PROC_UNLOCK(p);
1338                error = EINVAL;
1339        } else {
1340                PROC_UNLOCK(p);
1341                itimer_enter(it);
1342                error = CLOCK_CALL(it->it_clockid, timer_gettime, (it, val));
1343                itimer_leave(it);
1344                ITIMER_UNLOCK(it);
1345        }
1346        return (error);
1347}
1348
1349#ifndef _SYS_SYSPROTO_H_
1350struct timer_getoverrun_args {
1351        int timerid;
1352};
1353#endif
1354int
1355sys_ktimer_getoverrun(struct thread *td, struct ktimer_getoverrun_args *uap)
1356{
1357
1358        return (kern_ktimer_getoverrun(td, uap->timerid));
1359}
1360
1361int
1362kern_ktimer_getoverrun(struct thread *td, int timer_id)
1363{
1364        struct proc *p = td->td_proc;
1365        struct itimer *it;
1366        int error ;
1367
1368        PROC_LOCK(p);
1369        if (timer_id < 3 ||
1370            (it = itimer_find(p, timer_id)) == NULL) {
1371                PROC_UNLOCK(p);
1372                error = EINVAL;
1373        } else {
1374                td->td_retval[0] = it->it_overrun_last;
1375                ITIMER_UNLOCK(it);
1376                PROC_UNLOCK(p);
1377                error = 0;
1378        }
1379        return (error);
1380}
1381
1382static int
1383realtimer_create(struct itimer *it)
1384{
1385        callout_init_mtx(&it->it_callout, &it->it_mtx, 0);
1386        return (0);
1387}
1388
1389static int
1390realtimer_delete(struct itimer *it)
1391{
1392        mtx_assert(&it->it_mtx, MA_OWNED);
1393       
1394        /*
1395         * clear timer's value and interval to tell realtimer_expire
1396         * to not rearm the timer.
1397         */
1398        timespecclear(&it->it_time.it_value);
1399        timespecclear(&it->it_time.it_interval);
1400        ITIMER_UNLOCK(it);
1401        callout_drain(&it->it_callout);
1402        ITIMER_LOCK(it);
1403        return (0);
1404}
1405
1406static int
1407realtimer_gettime(struct itimer *it, struct itimerspec *ovalue)
1408{
1409        struct timespec cts;
1410
1411        mtx_assert(&it->it_mtx, MA_OWNED);
1412
1413        realtimer_clocktime(it->it_clockid, &cts);
1414        *ovalue = it->it_time;
1415        if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_nsec != 0) {
1416                timespecsub(&ovalue->it_value, &cts);
1417                if (ovalue->it_value.tv_sec < 0 ||
1418                    (ovalue->it_value.tv_sec == 0 &&
1419                     ovalue->it_value.tv_nsec == 0)) {
1420                        ovalue->it_value.tv_sec  = 0;
1421                        ovalue->it_value.tv_nsec = 1;
1422                }
1423        }
1424        return (0);
1425}
1426
1427static int
1428realtimer_settime(struct itimer *it, int flags,
1429        struct itimerspec *value, struct itimerspec *ovalue)
1430{
1431        struct timespec cts, ts;
1432        struct timeval tv;
1433        struct itimerspec val;
1434
1435        mtx_assert(&it->it_mtx, MA_OWNED);
1436
1437        val = *value;
1438        if (itimespecfix(&val.it_value))
1439                return (EINVAL);
1440
1441        if (timespecisset(&val.it_value)) {
1442                if (itimespecfix(&val.it_interval))
1443                        return (EINVAL);
1444        } else {
1445                timespecclear(&val.it_interval);
1446        }
1447       
1448        if (ovalue != NULL)
1449                realtimer_gettime(it, ovalue);
1450
1451        it->it_time = val;
1452        if (timespecisset(&val.it_value)) {
1453                realtimer_clocktime(it->it_clockid, &cts);
1454                ts = val.it_value;
1455                if ((flags & TIMER_ABSTIME) == 0) {
1456                        /* Convert to absolute time. */
1457                        timespecadd(&it->it_time.it_value, &cts);
1458                } else {
1459                        timespecsub(&ts, &cts);
1460                        /*
1461                         * We don't care if ts is negative, tztohz will
1462                         * fix it.
1463                         */
1464                }
1465                TIMESPEC_TO_TIMEVAL(&tv, &ts);
1466                callout_reset(&it->it_callout, tvtohz(&tv),
1467                        realtimer_expire, it);
1468        } else {
1469                callout_stop(&it->it_callout);
1470        }
1471
1472        return (0);
1473}
1474
1475static void
1476realtimer_clocktime(clockid_t id, struct timespec *ts)
1477{
1478        if (id == CLOCK_REALTIME)
1479                getnanotime(ts);
1480        else    /* CLOCK_MONOTONIC */
1481                getnanouptime(ts);
1482}
1483
1484int
1485itimer_accept(struct proc *p, int timerid, ksiginfo_t *ksi)
1486{
1487        struct itimer *it;
1488
1489        PROC_LOCK_ASSERT(p, MA_OWNED);
1490        it = itimer_find(p, timerid);
1491        if (it != NULL) {
1492                ksi->ksi_overrun = it->it_overrun;
1493                it->it_overrun_last = it->it_overrun;
1494                it->it_overrun = 0;
1495                ITIMER_UNLOCK(it);
1496                return (0);
1497        }
1498        return (EINVAL);
1499}
1500
1501int
1502itimespecfix(struct timespec *ts)
1503{
1504
1505        if (ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000)
1506                return (EINVAL);
1507        if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000)
1508                ts->tv_nsec = tick * 1000;
1509        return (0);
1510}
1511
1512/* Timeout callback for realtime timer */
1513static void
1514realtimer_expire(void *arg)
1515{
1516        struct timespec cts, ts;
1517        struct timeval tv;
1518        struct itimer *it;
1519
1520        it = (struct itimer *)arg;
1521
1522        realtimer_clocktime(it->it_clockid, &cts);
1523        /* Only fire if time is reached. */
1524        if (timespeccmp(&cts, &it->it_time.it_value, >=)) {
1525                if (timespecisset(&it->it_time.it_interval)) {
1526                        timespecadd(&it->it_time.it_value,
1527                                    &it->it_time.it_interval);
1528                        while (timespeccmp(&cts, &it->it_time.it_value, >=)) {
1529                                if (it->it_overrun < INT_MAX)
1530                                        it->it_overrun++;
1531                                else
1532                                        it->it_ksi.ksi_errno = ERANGE;
1533                                timespecadd(&it->it_time.it_value,
1534                                            &it->it_time.it_interval);
1535                        }
1536                } else {
1537                        /* single shot timer ? */
1538                        timespecclear(&it->it_time.it_value);
1539                }
1540                if (timespecisset(&it->it_time.it_value)) {
1541                        ts = it->it_time.it_value;
1542                        timespecsub(&ts, &cts);
1543                        TIMESPEC_TO_TIMEVAL(&tv, &ts);
1544                        callout_reset(&it->it_callout, tvtohz(&tv),
1545                                 realtimer_expire, it);
1546                }
1547                itimer_enter(it);
1548                ITIMER_UNLOCK(it);
1549                itimer_fire(it);
1550                ITIMER_LOCK(it);
1551                itimer_leave(it);
1552        } else if (timespecisset(&it->it_time.it_value)) {
1553                ts = it->it_time.it_value;
1554                timespecsub(&ts, &cts);
1555                TIMESPEC_TO_TIMEVAL(&tv, &ts);
1556                callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire,
1557                        it);
1558        }
1559}
1560
1561void
1562itimer_fire(struct itimer *it)
1563{
1564        struct proc *p = it->it_proc;
1565        struct thread *td;
1566
1567        if (it->it_sigev.sigev_notify == SIGEV_SIGNAL ||
1568            it->it_sigev.sigev_notify == SIGEV_THREAD_ID) {
1569                if (sigev_findtd(p, &it->it_sigev, &td) != 0) {
1570                        ITIMER_LOCK(it);
1571                        timespecclear(&it->it_time.it_value);
1572                        timespecclear(&it->it_time.it_interval);
1573                        callout_stop(&it->it_callout);
1574                        ITIMER_UNLOCK(it);
1575                        return;
1576                }
1577                if (!KSI_ONQ(&it->it_ksi)) {
1578                        it->it_ksi.ksi_errno = 0;
1579                        ksiginfo_set_sigev(&it->it_ksi, &it->it_sigev);
1580                        tdsendsignal(p, td, it->it_ksi.ksi_signo, &it->it_ksi);
1581                } else {
1582                        if (it->it_overrun < INT_MAX)
1583                                it->it_overrun++;
1584                        else
1585                                it->it_ksi.ksi_errno = ERANGE;
1586                }
1587                PROC_UNLOCK(p);
1588        }
1589}
1590
1591static void
1592itimers_alloc(struct proc *p)
1593{
1594        struct itimers *its;
1595        int i;
1596
1597        its = malloc(sizeof (struct itimers), M_SUBPROC, M_WAITOK | M_ZERO);
1598        LIST_INIT(&its->its_virtual);
1599        LIST_INIT(&its->its_prof);
1600        TAILQ_INIT(&its->its_worklist);
1601        for (i = 0; i < TIMER_MAX; i++)
1602                its->its_timers[i] = NULL;
1603        PROC_LOCK(p);
1604        if (p->p_itimers == NULL) {
1605                p->p_itimers = its;
1606                PROC_UNLOCK(p);
1607        }
1608        else {
1609                PROC_UNLOCK(p);
1610                free(its, M_SUBPROC);
1611        }
1612}
1613
1614static void
1615itimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp __unused)
1616{
1617        itimers_event_hook_exit(arg, p);
1618}
1619
1620/* Clean up timers when some process events are being triggered. */
1621static void
1622itimers_event_hook_exit(void *arg, struct proc *p)
1623{
1624        struct itimers *its;
1625        struct itimer *it;
1626        int event = (int)(intptr_t)arg;
1627        int i;
1628
1629        if (p->p_itimers != NULL) {
1630                its = p->p_itimers;
1631                for (i = 0; i < MAX_CLOCKS; ++i) {
1632                        if (posix_clocks[i].event_hook != NULL)
1633                                CLOCK_CALL(i, event_hook, (p, i, event));
1634                }
1635                /*
1636                 * According to susv3, XSI interval timers should be inherited
1637                 * by new image.
1638                 */
1639                if (event == ITIMER_EV_EXEC)
1640                        i = 3;
1641                else if (event == ITIMER_EV_EXIT)
1642                        i = 0;
1643                else
1644                        panic("unhandled event");
1645                for (; i < TIMER_MAX; ++i) {
1646                        if ((it = its->its_timers[i]) != NULL)
1647                                kern_ktimer_delete(curthread, i);
1648                }
1649                if (its->its_timers[0] == NULL &&
1650                    its->its_timers[1] == NULL &&
1651                    its->its_timers[2] == NULL) {
1652                        free(its, M_SUBPROC);
1653                        p->p_itimers = NULL;
1654                }
1655        }
1656}
1657#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.