summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_tc.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-06-23 09:33:06 +0000
committerkib <kib@FreeBSD.org>2012-06-23 09:33:06 +0000
commit497817697cfb819824b7ae8619a5094ace1b3698 (patch)
treee776dfcefe80b16e0aa0a27d0fdb364391c6c4b8 /sys/kern/kern_tc.c
parente19c8fe0ffaebe2cb325b0d14102166d51b7429d (diff)
downloadFreeBSD-src-497817697cfb819824b7ae8619a5094ace1b3698.zip
FreeBSD-src-497817697cfb819824b7ae8619a5094ace1b3698.tar.gz
Stop updating the struct vdso_timehands from even handler executed in
the scheduled task from tc_windup(). Do it directly from tc_windup in interrupt context [1]. Establish the permanent mapping of the shared page into the kernel address space, avoiding the potential need to sleep waiting for allocation of sf buffer during vdso_timehands update. As a consequence, shared_page_write_start() and shared_page_write_end() functions are not needed anymore. Guess and memorize the pointers to native host and compat32 sysentvec during initialization, to avoid the need to get shared_page_alloc_sx lock during the update. In tc_fill_vdso_timehands(), do not loop waiting for timehands generation to stabilize, since vdso_timehands is written in the same interrupt context which wrote timehands. Requested by: mav [1] MFC after: 29 days
Diffstat (limited to 'sys/kern/kern_tc.c')
-rw-r--r--sys/kern/kern_tc.c62
1 files changed, 21 insertions, 41 deletions
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 0b8fefe..4a75af5 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -31,7 +31,6 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/timeffc.h>
#include <sys/timepps.h>
-#include <sys/taskqueue.h>
#include <sys/timetc.h>
#include <sys/timex.h>
#include <sys/vdso.h>
@@ -121,12 +120,8 @@ SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW,
&timestepwarnings, 0, "Log time steps");
static void tc_windup(void);
-static void tc_windup_push_vdso(void *ctx, int pending);
static void cpu_tick_calibrate(int);
-static struct task tc_windup_push_vdso_task = TASK_INITIALIZER(0,
- tc_windup_push_vdso, 0);
-
static int
sysctl_kern_boottime(SYSCTL_HANDLER_ARGS)
{
@@ -1367,7 +1362,7 @@ tc_windup(void)
#endif
timehands = th;
- taskqueue_enqueue_fast(taskqueue_fast, &tc_windup_push_vdso_task);
+ timekeep_push_vdso();
}
/* Report or change the active timecounter hardware. */
@@ -1394,7 +1389,7 @@ sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS)
(void)newtc->tc_get_timecount(newtc);
timecounter = newtc;
- EVENTHANDLER_INVOKE(tc_windup);
+ timekeep_push_vdso();
return (0);
}
return (EINVAL);
@@ -1865,7 +1860,7 @@ sysctl_fast_gettime(SYSCTL_HANDLER_ARGS)
if (error != 0)
return (error);
vdso_th_enable = old_vdso_th_enable;
- EVENTHANDLER_INVOKE(tc_windup);
+ timekeep_push_vdso();
return (0);
}
SYSCTL_PROC(_kern_timecounter, OID_AUTO, fast_gettime,
@@ -1877,19 +1872,15 @@ tc_fill_vdso_timehands(struct vdso_timehands *vdso_th)
{
struct timehands *th;
uint32_t enabled;
- int gen;
- do {
- th = timehands;
- gen = th->th_generation;
- vdso_th->th_algo = VDSO_TH_ALGO_1;
- vdso_th->th_scale = th->th_scale;
- vdso_th->th_offset_count = th->th_offset_count;
- vdso_th->th_counter_mask = th->th_counter->tc_counter_mask;
- vdso_th->th_offset = th->th_offset;
- vdso_th->th_boottime = boottimebin;
- enabled = cpu_fill_vdso_timehands(vdso_th);
- } while (gen == 0 || timehands->th_generation != gen);
+ th = timehands;
+ vdso_th->th_algo = VDSO_TH_ALGO_1;
+ vdso_th->th_scale = th->th_scale;
+ vdso_th->th_offset_count = th->th_offset_count;
+ vdso_th->th_counter_mask = th->th_counter->tc_counter_mask;
+ vdso_th->th_offset = th->th_offset;
+ vdso_th->th_boottime = boottimebin;
+ enabled = cpu_fill_vdso_timehands(vdso_th);
if (!vdso_th_enable)
enabled = 0;
return (enabled);
@@ -1901,30 +1892,19 @@ tc_fill_vdso_timehands32(struct vdso_timehands32 *vdso_th32)
{
struct timehands *th;
uint32_t enabled;
- int gen;
- do {
- th = timehands;
- gen = th->th_generation;
- vdso_th32->th_algo = VDSO_TH_ALGO_1;
- *(uint64_t *)&vdso_th32->th_scale[0] = th->th_scale;
- vdso_th32->th_offset_count = th->th_offset_count;
- vdso_th32->th_counter_mask = th->th_counter->tc_counter_mask;
- vdso_th32->th_offset.sec = th->th_offset.sec;
- *(uint64_t *)&vdso_th32->th_offset.frac[0] = th->th_offset.frac;
- vdso_th32->th_boottime.sec = boottimebin.sec;
- *(uint64_t *)&vdso_th32->th_boottime.frac[0] = boottimebin.frac;
- enabled = cpu_fill_vdso_timehands32(vdso_th32);
- } while (gen == 0 || timehands->th_generation != gen);
+ th = timehands;
+ vdso_th32->th_algo = VDSO_TH_ALGO_1;
+ *(uint64_t *)&vdso_th32->th_scale[0] = th->th_scale;
+ vdso_th32->th_offset_count = th->th_offset_count;
+ vdso_th32->th_counter_mask = th->th_counter->tc_counter_mask;
+ vdso_th32->th_offset.sec = th->th_offset.sec;
+ *(uint64_t *)&vdso_th32->th_offset.frac[0] = th->th_offset.frac;
+ vdso_th32->th_boottime.sec = boottimebin.sec;
+ *(uint64_t *)&vdso_th32->th_boottime.frac[0] = boottimebin.frac;
+ enabled = cpu_fill_vdso_timehands32(vdso_th32);
if (!vdso_th_enable)
enabled = 0;
return (enabled);
}
#endif
-
-static void
-tc_windup_push_vdso(void *ctx, int pending)
-{
-
- EVENTHANDLER_INVOKE(tc_windup);
-}
OpenPOWER on IntegriCloud