Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_time.c
Show All 37 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/limits.h> | #include <sys/limits.h> | ||||
#include <sys/clock.h> | #include <sys/clock.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/sysproto.h> | #include <sys/sysproto.h> | ||||
#include <sys/eventhandler.h> | |||||
#include <sys/resourcevar.h> | #include <sys/resourcevar.h> | ||||
#include <sys/signalvar.h> | #include <sys/signalvar.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/sleepqueue.h> | #include <sys/sleepqueue.h> | ||||
#include <sys/syscallsubr.h> | #include <sys/syscallsubr.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/sysent.h> | #include <sys/sysent.h> | ||||
#include <sys/priv.h> | #include <sys/priv.h> | ||||
Show All 39 Lines | |||||
static void itimer_start(void); | static void itimer_start(void); | ||||
static int itimer_init(void *, int, int); | static int itimer_init(void *, int, int); | ||||
static void itimer_fini(void *, int); | static void itimer_fini(void *, int); | ||||
static void itimer_enter(struct itimer *); | static void itimer_enter(struct itimer *); | ||||
static void itimer_leave(struct itimer *); | static void itimer_leave(struct itimer *); | ||||
static struct itimer *itimer_find(struct proc *, int); | static struct itimer *itimer_find(struct proc *, int); | ||||
static void itimers_alloc(struct proc *); | static void itimers_alloc(struct proc *); | ||||
static void itimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp); | |||||
static void itimers_event_hook_exit(void *arg, struct proc *p); | |||||
static int realtimer_create(struct itimer *); | static int realtimer_create(struct itimer *); | ||||
static int realtimer_gettime(struct itimer *, struct itimerspec *); | static int realtimer_gettime(struct itimer *, struct itimerspec *); | ||||
static int realtimer_settime(struct itimer *, int, | static int realtimer_settime(struct itimer *, int, | ||||
struct itimerspec *, struct itimerspec *); | struct itimerspec *, struct itimerspec *); | ||||
static int realtimer_delete(struct itimer *); | static int realtimer_delete(struct itimer *); | ||||
static void realtimer_clocktime(clockid_t, struct timespec *); | static void realtimer_clocktime(clockid_t, struct timespec *); | ||||
static void realtimer_expire(void *); | static void realtimer_expire(void *); | ||||
int register_posix_clock(int, struct kclock *); | static int register_posix_clock(int, const struct kclock *); | ||||
void itimer_fire(struct itimer *it); | void itimer_fire(struct itimer *it); | ||||
int itimespecfix(struct timespec *ts); | int itimespecfix(struct timespec *ts); | ||||
#define CLOCK_CALL(clock, call, arglist) \ | #define CLOCK_CALL(clock, call, arglist) \ | ||||
((*posix_clocks[clock].call) arglist) | ((*posix_clocks[clock].call) arglist) | ||||
SYSINIT(posix_timer, SI_SUB_P1003_1B, SI_ORDER_FIRST+4, itimer_start, NULL); | SYSINIT(posix_timer, SI_SUB_P1003_1B, SI_ORDER_FIRST+4, itimer_start, NULL); | ||||
▲ Show 20 Lines • Show All 960 Lines • ▼ Show 20 Lines | if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) { | ||||
(*curpps)++; /* NB: ignore potential overflow */ | (*curpps)++; /* NB: ignore potential overflow */ | ||||
return (maxpps < 0 || *curpps <= maxpps); | return (maxpps < 0 || *curpps <= maxpps); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
itimer_start(void) | itimer_start(void) | ||||
{ | { | ||||
struct kclock rt_clock = { | static const struct kclock rt_clock = { | ||||
.timer_create = realtimer_create, | .timer_create = realtimer_create, | ||||
.timer_delete = realtimer_delete, | .timer_delete = realtimer_delete, | ||||
.timer_settime = realtimer_settime, | .timer_settime = realtimer_settime, | ||||
.timer_gettime = realtimer_gettime, | .timer_gettime = realtimer_gettime, | ||||
.event_hook = NULL | |||||
}; | }; | ||||
itimer_zone = uma_zcreate("itimer", sizeof(struct itimer), | itimer_zone = uma_zcreate("itimer", sizeof(struct itimer), | ||||
NULL, NULL, itimer_init, itimer_fini, UMA_ALIGN_PTR, 0); | NULL, NULL, itimer_init, itimer_fini, UMA_ALIGN_PTR, 0); | ||||
register_posix_clock(CLOCK_REALTIME, &rt_clock); | register_posix_clock(CLOCK_REALTIME, &rt_clock); | ||||
register_posix_clock(CLOCK_MONOTONIC, &rt_clock); | register_posix_clock(CLOCK_MONOTONIC, &rt_clock); | ||||
p31b_setcfg(CTL_P1003_1B_TIMERS, 200112L); | p31b_setcfg(CTL_P1003_1B_TIMERS, 200112L); | ||||
p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, INT_MAX); | p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, INT_MAX); | ||||
p31b_setcfg(CTL_P1003_1B_TIMER_MAX, TIMER_MAX); | p31b_setcfg(CTL_P1003_1B_TIMER_MAX, TIMER_MAX); | ||||
EVENTHANDLER_REGISTER(process_exit, itimers_event_hook_exit, | |||||
(void *)ITIMER_EV_EXIT, EVENTHANDLER_PRI_ANY); | |||||
EVENTHANDLER_REGISTER(process_exec, itimers_event_hook_exec, | |||||
(void *)ITIMER_EV_EXEC, EVENTHANDLER_PRI_ANY); | |||||
} | } | ||||
int | static int | ||||
register_posix_clock(int clockid, struct kclock *clk) | register_posix_clock(int clockid, const struct kclock *clk) | ||||
{ | { | ||||
if ((unsigned)clockid >= MAX_CLOCKS) { | if ((unsigned)clockid >= MAX_CLOCKS) { | ||||
printf("%s: invalid clockid\n", __func__); | printf("%s: invalid clockid\n", __func__); | ||||
return (0); | return (0); | ||||
} | } | ||||
posix_clocks[clockid] = *clk; | posix_clocks[clockid] = *clk; | ||||
return (1); | return (1); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 589 Lines • ▼ Show 20 Lines | if (p->p_itimers == NULL) { | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
} | } | ||||
else { | else { | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
free(its, M_SUBPROC); | free(its, M_SUBPROC); | ||||
} | } | ||||
} | } | ||||
static void | |||||
itimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp __unused) | |||||
{ | |||||
itimers_event_hook_exit(arg, p); | |||||
} | |||||
/* Clean up timers when some process events are being triggered. */ | /* Clean up timers when some process events are being triggered. */ | ||||
static void | static void | ||||
itimers_event_hook_exit(void *arg, struct proc *p) | itimers_event_exit_exec(int start_idx, struct proc *p) | ||||
{ | { | ||||
struct itimers *its; | struct itimers *its; | ||||
struct itimer *it; | struct itimer *it; | ||||
int event = (int)(intptr_t)arg; | |||||
int i; | int i; | ||||
if (p->p_itimers != NULL) { | |||||
its = p->p_itimers; | its = p->p_itimers; | ||||
for (i = 0; i < MAX_CLOCKS; ++i) { | if (its == NULL) | ||||
if (posix_clocks[i].event_hook != NULL) | return; | ||||
CLOCK_CALL(i, event_hook, (p, i, event)); | |||||
} | for (i = start_idx; i < TIMER_MAX; ++i) { | ||||
/* | |||||
* According to susv3, XSI interval timers should be inherited | |||||
* by new image. | |||||
*/ | |||||
if (event == ITIMER_EV_EXEC) | |||||
i = 3; | |||||
else if (event == ITIMER_EV_EXIT) | |||||
i = 0; | |||||
else | |||||
panic("unhandled event"); | |||||
for (; i < TIMER_MAX; ++i) { | |||||
if ((it = its->its_timers[i]) != NULL) | if ((it = its->its_timers[i]) != NULL) | ||||
kern_ktimer_delete(curthread, i); | kern_ktimer_delete(curthread, i); | ||||
} | } | ||||
if (its->its_timers[0] == NULL && | if (its->its_timers[0] == NULL && its->its_timers[1] == NULL && | ||||
its->its_timers[1] == NULL && | |||||
its->its_timers[2] == NULL) { | its->its_timers[2] == NULL) { | ||||
free(its, M_SUBPROC); | free(its, M_SUBPROC); | ||||
p->p_itimers = NULL; | p->p_itimers = NULL; | ||||
} | } | ||||
} | } | ||||
void | |||||
itimers_exec(struct proc *p) | |||||
{ | |||||
/* | |||||
* According to susv3, XSI interval timers should be inherited | |||||
* by new image. | |||||
*/ | |||||
itimers_event_exit_exec(3, p); | |||||
} | |||||
void | |||||
itimers_exit(struct proc *p) | |||||
{ | |||||
itimers_event_exit_exec(0, p); | |||||
} | } |