Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_timeout.c
| Show All 35 Lines | |||||
| * From: @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 | * From: @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 | ||||
| */ | */ | ||||
| #include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
| __FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
| #include "opt_callout_profiling.h" | #include "opt_callout_profiling.h" | ||||
| #include "opt_ddb.h" | #include "opt_ddb.h" | ||||
| #if defined(__arm__) | |||||
| #include "opt_timer.h" | |||||
| #endif | |||||
| #include "opt_rss.h" | #include "opt_rss.h" | ||||
| #include <sys/param.h> | #include <sys/param.h> | ||||
| #include <sys/systm.h> | #include <sys/systm.h> | ||||
| #include <sys/bus.h> | #include <sys/bus.h> | ||||
| #include <sys/callout.h> | #include <sys/callout.h> | ||||
| #include <sys/domainset.h> | #include <sys/domainset.h> | ||||
| #include <sys/file.h> | #include <sys/file.h> | ||||
| Show All 14 Lines | |||||
| #include <ddb/db_sym.h> | #include <ddb/db_sym.h> | ||||
| #include <machine/_inttypes.h> | #include <machine/_inttypes.h> | ||||
| #endif | #endif | ||||
| #ifdef SMP | #ifdef SMP | ||||
| #include <machine/cpu.h> | #include <machine/cpu.h> | ||||
| #endif | #endif | ||||
| #ifndef NO_EVENTTIMERS | |||||
| DPCPU_DECLARE(sbintime_t, hardclocktime); | DPCPU_DECLARE(sbintime_t, hardclocktime); | ||||
| #endif | |||||
| SDT_PROVIDER_DEFINE(callout_execute); | SDT_PROVIDER_DEFINE(callout_execute); | ||||
| SDT_PROBE_DEFINE1(callout_execute, , , callout__start, "struct callout *"); | SDT_PROBE_DEFINE1(callout_execute, , , callout__start, "struct callout *"); | ||||
| SDT_PROBE_DEFINE1(callout_execute, , , callout__end, "struct callout *"); | SDT_PROBE_DEFINE1(callout_execute, , , callout__end, "struct callout *"); | ||||
| #ifdef CALLOUT_PROFILING | #ifdef CALLOUT_PROFILING | ||||
| static int avg_depth; | static int avg_depth; | ||||
| SYSCTL_INT(_debug, OID_AUTO, to_avg_depth, CTLFLAG_RD, &avg_depth, 0, | SYSCTL_INT(_debug, OID_AUTO, to_avg_depth, CTLFLAG_RD, &avg_depth, 0, | ||||
| ▲ Show 20 Lines • Show All 434 Lines • ▼ Show 20 Lines | next: | ||||
| firstb++; | firstb++; | ||||
| /* | /* | ||||
| * Stop if we looked after present time and found | * Stop if we looked after present time and found | ||||
| * some event we can't execute at now. | * some event we can't execute at now. | ||||
| * Stop if we looked far enough into the future. | * Stop if we looked far enough into the future. | ||||
| */ | */ | ||||
| } while (((int)(firstb - lastb)) <= 0); | } while (((int)(firstb - lastb)) <= 0); | ||||
| cc->cc_firstevent = last; | cc->cc_firstevent = last; | ||||
| #ifndef NO_EVENTTIMERS | |||||
| cpu_new_callout(curcpu, last, first); | cpu_new_callout(curcpu, last, first); | ||||
| #endif | CC_UNLOCK_FLAGS(cc, MTX_QUIET); | ||||
| #ifdef CALLOUT_PROFILING | #ifdef CALLOUT_PROFILING | ||||
| avg_depth_dir += (depth_dir * 1000 - avg_depth_dir) >> 8; | avg_depth_dir += (depth_dir * 1000 - avg_depth_dir) >> 8; | ||||
| avg_mpcalls_dir += (mpcalls_dir * 1000 - avg_mpcalls_dir) >> 8; | avg_mpcalls_dir += (mpcalls_dir * 1000 - avg_mpcalls_dir) >> 8; | ||||
| avg_lockcalls_dir += (lockcalls_dir * 1000 - avg_lockcalls_dir) >> 8; | avg_lockcalls_dir += (lockcalls_dir * 1000 - avg_lockcalls_dir) >> 8; | ||||
| #endif | #endif | ||||
| CC_UNLOCK_FLAGS(cc, MTX_QUIET); | |||||
| /* | /* | ||||
| * swi_sched acquires the thread lock, so we don't want to call it | * swi_sched acquires the thread lock, so we don't want to call it | ||||
| * with cc_lock held; incorrect locking order. | * with cc_lock held; incorrect locking order. | ||||
| */ | */ | ||||
| if (!TAILQ_EMPTY(&cc->cc_expireq)) | if (!TAILQ_EMPTY(&cc->cc_expireq)) | ||||
| swi_sched(cc->cc_cookie, 0); | swi_sched(cc->cc_cookie, 0); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | callout_cc_add(struct callout *c, struct callout_cpu *cc, | ||||
| c->c_precision = precision; | c->c_precision = precision; | ||||
| bucket = callout_get_bucket(c->c_time); | bucket = callout_get_bucket(c->c_time); | ||||
| CTR3(KTR_CALLOUT, "precision set for %p: %d.%08x", | CTR3(KTR_CALLOUT, "precision set for %p: %d.%08x", | ||||
| c, (int)(c->c_precision >> 32), | c, (int)(c->c_precision >> 32), | ||||
| (u_int)(c->c_precision & 0xffffffff)); | (u_int)(c->c_precision & 0xffffffff)); | ||||
| LIST_INSERT_HEAD(&cc->cc_callwheel[bucket], c, c_links.le); | LIST_INSERT_HEAD(&cc->cc_callwheel[bucket], c, c_links.le); | ||||
| if (cc->cc_bucket == bucket) | if (cc->cc_bucket == bucket) | ||||
| cc_exec_next(cc) = c; | cc_exec_next(cc) = c; | ||||
| #ifndef NO_EVENTTIMERS | |||||
| /* | /* | ||||
| * Inform the eventtimers(4) subsystem there's a new callout | * Inform the eventtimers(4) subsystem there's a new callout | ||||
| * that has been inserted, but only if really required. | * that has been inserted, but only if really required. | ||||
| */ | */ | ||||
| if (SBT_MAX - c->c_time < c->c_precision) | if (SBT_MAX - c->c_time < c->c_precision) | ||||
| c->c_precision = SBT_MAX - c->c_time; | c->c_precision = SBT_MAX - c->c_time; | ||||
| sbt = c->c_time + c->c_precision; | sbt = c->c_time + c->c_precision; | ||||
| if (sbt < cc->cc_firstevent) { | if (sbt < cc->cc_firstevent) { | ||||
| cc->cc_firstevent = sbt; | cc->cc_firstevent = sbt; | ||||
| cpu_new_callout(cpu, sbt, c->c_time); | cpu_new_callout(cpu, sbt, c->c_time); | ||||
| } | } | ||||
| #endif | |||||
| } | } | ||||
| static void | static void | ||||
| softclock_call_cc(struct callout *c, struct callout_cpu *cc, | softclock_call_cc(struct callout *c, struct callout_cpu *cc, | ||||
| #ifdef CALLOUT_PROFILING | #ifdef CALLOUT_PROFILING | ||||
| int *mpcalls, int *lockcalls, int *gcalls, | int *mpcalls, int *lockcalls, int *gcalls, | ||||
| #endif | #endif | ||||
| int direct) | int direct) | ||||
| ▲ Show 20 Lines • Show All 227 Lines • ▼ Show 20 Lines | callout_when(sbintime_t sbt, sbintime_t precision, int flags, | ||||
| if ((flags & (C_ABSOLUTE | C_PRECALC)) != 0) { | if ((flags & (C_ABSOLUTE | C_PRECALC)) != 0) { | ||||
| *res = sbt; | *res = sbt; | ||||
| *prec_res = precision; | *prec_res = precision; | ||||
| return; | return; | ||||
| } | } | ||||
| if ((flags & C_HARDCLOCK) != 0 && sbt < tick_sbt) | if ((flags & C_HARDCLOCK) != 0 && sbt < tick_sbt) | ||||
| sbt = tick_sbt; | sbt = tick_sbt; | ||||
| if ((flags & C_HARDCLOCK) != 0 || | if ((flags & C_HARDCLOCK) != 0 || sbt >= sbt_tickthreshold) { | ||||
| #ifdef NO_EVENTTIMERS | |||||
| sbt >= sbt_timethreshold) { | |||||
| to_sbt = getsbinuptime(); | |||||
| /* Add safety belt for the case of hz > 1000. */ | |||||
| to_sbt += tc_tick_sbt - tick_sbt; | |||||
| #else | |||||
| sbt >= sbt_tickthreshold) { | |||||
| /* | /* | ||||
| * Obtain the time of the last hardclock() call on | * Obtain the time of the last hardclock() call on | ||||
| * this CPU directly from the kern_clocksource.c. | * this CPU directly from the kern_clocksource.c. | ||||
| * This value is per-CPU, but it is equal for all | * This value is per-CPU, but it is equal for all | ||||
| * active ones. | * active ones. | ||||
| */ | */ | ||||
| #ifdef __LP64__ | #ifdef __LP64__ | ||||
| to_sbt = DPCPU_GET(hardclocktime); | to_sbt = DPCPU_GET(hardclocktime); | ||||
| #else | #else | ||||
| spinlock_enter(); | spinlock_enter(); | ||||
| to_sbt = DPCPU_GET(hardclocktime); | to_sbt = DPCPU_GET(hardclocktime); | ||||
| spinlock_exit(); | spinlock_exit(); | ||||
| #endif | |||||
| #endif | #endif | ||||
| if (cold && to_sbt == 0) | if (cold && to_sbt == 0) | ||||
| to_sbt = sbinuptime(); | to_sbt = sbinuptime(); | ||||
| if ((flags & C_HARDCLOCK) == 0) | if ((flags & C_HARDCLOCK) == 0) | ||||
| to_sbt += tick_sbt; | to_sbt += tick_sbt; | ||||
| } else | } else | ||||
| to_sbt = sbinuptime(); | to_sbt = sbinuptime(); | ||||
| if (SBT_MAX - to_sbt < sbt) | if (SBT_MAX - to_sbt < sbt) | ||||
| ▲ Show 20 Lines • Show All 614 Lines • Show Last 20 Lines | |||||