xref: /f-stack/lib/ff_kern_timeout.c (revision 2317ada5)
1a9643ea8Slogwang /*-
2a9643ea8Slogwang  * Copyright (c) 1982, 1986, 1991, 1993
3a9643ea8Slogwang  *  The Regents of the University of California.  All rights reserved.
4a9643ea8Slogwang  * (c) UNIX System Laboratories, Inc.
5a9643ea8Slogwang  * All or some portions of this file are derived from material licensed
6a9643ea8Slogwang  * to the University of California by American Telephone and Telegraph
7a9643ea8Slogwang  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8a9643ea8Slogwang  * the permission of UNIX System Laboratories, Inc.
9a9643ea8Slogwang  *
10a9643ea8Slogwang  * Copyright (c) 2010 Kip Macy. All rights reserved.
11a9643ea8Slogwang  * Copyright (c) 2013 Patrick Kelsey. All rights reserved.
12*2317ada5Sfengbojiang  * Copyright (C) 2017-2021 THL A29 Limited, a Tencent company.
13a9643ea8Slogwang  * All rights reserved.
14a9643ea8Slogwang  *
15a9643ea8Slogwang  * Redistribution and use in source and binary forms, with or without
16a9643ea8Slogwang  * modification, are permitted provided that the following conditions
17a9643ea8Slogwang  * are met:
18a9643ea8Slogwang  * 1. Redistributions of source code must retain the above copyright
19a9643ea8Slogwang  *    notice, this list of conditions and the following disclaimer.
20a9643ea8Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
21a9643ea8Slogwang  *    notice, this list of conditions and the following disclaimer in the
22a9643ea8Slogwang  *    documentation and/or other materials provided with the distribution.
23a9643ea8Slogwang  * 4. Neither the name of the University nor the names of its contributors
24a9643ea8Slogwang  *    may be used to endorse or promote products derived from this software
25a9643ea8Slogwang  *    without specific prior written permission.
26a9643ea8Slogwang  *
27a9643ea8Slogwang  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28a9643ea8Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29a9643ea8Slogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30a9643ea8Slogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31a9643ea8Slogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32a9643ea8Slogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33a9643ea8Slogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34a9643ea8Slogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35a9643ea8Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36a9643ea8Slogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37a9643ea8Slogwang  * SUCH DAMAGE.
38a9643ea8Slogwang  *
39a9643ea8Slogwang  *  From: @(#)kern_clock.c  8.5 (Berkeley) 1/21/94
40a9643ea8Slogwang  *
41a9643ea8Slogwang  * Derived in part from libplebnet's pn_kern_timeout.c and libuinet's uinet_timecounter.c.
42a9643ea8Slogwang  *
43a9643ea8Slogwang  */
44a9643ea8Slogwang 
45a9643ea8Slogwang #include <sys/cdefs.h>
46a9643ea8Slogwang __FBSDID("$FreeBSD$");
47a9643ea8Slogwang 
48a9643ea8Slogwang #include "opt_callout_profiling.h"
49a9643ea8Slogwang #include "opt_ddb.h"
50a9643ea8Slogwang #if defined(__arm__)
51a9643ea8Slogwang #include "opt_timer.h"
52a9643ea8Slogwang #endif
53a9643ea8Slogwang #include "opt_rss.h"
54a9643ea8Slogwang 
55a9643ea8Slogwang #include <sys/param.h>
56a9643ea8Slogwang #include <sys/systm.h>
57a9643ea8Slogwang #include <sys/bus.h>
58a9643ea8Slogwang #include <sys/callout.h>
59a9643ea8Slogwang #include <sys/file.h>
60a9643ea8Slogwang #include <sys/interrupt.h>
61a9643ea8Slogwang #include <sys/kernel.h>
62a9643ea8Slogwang #include <sys/ktr.h>
63a9643ea8Slogwang #include <sys/lock.h>
64a9643ea8Slogwang #include <sys/malloc.h>
65a9643ea8Slogwang #include <sys/mutex.h>
66a9643ea8Slogwang #include <sys/proc.h>
67a9643ea8Slogwang #include <sys/sdt.h>
68a9643ea8Slogwang #include <sys/sleepqueue.h>
69a9643ea8Slogwang #include <sys/sysctl.h>
70a9643ea8Slogwang #include <sys/smp.h>
71a9643ea8Slogwang #include <sys/timetc.h>
72a9643ea8Slogwang 
73a9643ea8Slogwang SDT_PROVIDER_DEFINE(callout_execute);
74a9643ea8Slogwang SDT_PROBE_DEFINE1(callout_execute, , , callout__start, "struct callout *");
75a9643ea8Slogwang SDT_PROBE_DEFINE1(callout_execute, , , callout__end, "struct callout *");
76a9643ea8Slogwang 
77a9643ea8Slogwang #ifdef CALLOUT_PROFILING
78a9643ea8Slogwang static int avg_depth;
79a9643ea8Slogwang SYSCTL_INT(_debug, OID_AUTO, to_avg_depth, CTLFLAG_RD, &avg_depth, 0,
80a9643ea8Slogwang     "Average number of items examined per softclock call. Units = 1/1000");
81a9643ea8Slogwang static int avg_gcalls;
82a9643ea8Slogwang SYSCTL_INT(_debug, OID_AUTO, to_avg_gcalls, CTLFLAG_RD, &avg_gcalls, 0,
83a9643ea8Slogwang     "Average number of Giant callouts made per softclock call. Units = 1/1000");
84a9643ea8Slogwang static int avg_lockcalls;
85a9643ea8Slogwang SYSCTL_INT(_debug, OID_AUTO, to_avg_lockcalls, CTLFLAG_RD, &avg_lockcalls, 0,
86a9643ea8Slogwang     "Average number of lock callouts made per softclock call. Units = 1/1000");
87a9643ea8Slogwang static int avg_mpcalls;
88a9643ea8Slogwang SYSCTL_INT(_debug, OID_AUTO, to_avg_mpcalls, CTLFLAG_RD, &avg_mpcalls, 0,
89a9643ea8Slogwang     "Average number of MP callouts made per softclock call. Units = 1/1000");
90a9643ea8Slogwang #endif
91a9643ea8Slogwang 
92a9643ea8Slogwang static int ncallout;
93a9643ea8Slogwang SYSCTL_INT(_kern, OID_AUTO, ncallout, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &ncallout, 0,
94a9643ea8Slogwang     "Number of entries in callwheel and size of timeout() preallocation");
95a9643ea8Slogwang 
96a9643ea8Slogwang #ifdef RSS
97a9643ea8Slogwang static int pin_default_swi = 1;
98a9643ea8Slogwang static int pin_pcpu_swi = 1;
99a9643ea8Slogwang #else
100a9643ea8Slogwang static int pin_default_swi = 0;
101a9643ea8Slogwang static int pin_pcpu_swi = 0;
102a9643ea8Slogwang #endif
103a9643ea8Slogwang 
104a9643ea8Slogwang SYSCTL_INT(_kern, OID_AUTO, pin_default_swi, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &pin_default_swi,
105a9643ea8Slogwang     0, "Pin the default (non-per-cpu) swi (shared with PCPU 0 swi)");
106a9643ea8Slogwang SYSCTL_INT(_kern, OID_AUTO, pin_pcpu_swi, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &pin_pcpu_swi,
107a9643ea8Slogwang     0, "Pin the per-CPU swis (except PCPU 0, which is also default");
108a9643ea8Slogwang 
109a9643ea8Slogwang #define sleepq_lock(w) do {} while(0)
110a9643ea8Slogwang #define sleepq_release(w) do {} while(0)
111a9643ea8Slogwang #define sleepq_add(a, b, c, d, e) do {} while(0)
112a9643ea8Slogwang #define sleepq_wait(w, p) do {} while(0)
113a9643ea8Slogwang 
1145e5c25c3Slogwang #define    CC_HASH_SHIFT    8
1155e5c25c3Slogwang 
116a9643ea8Slogwang /*
117a9643ea8Slogwang  * TODO:
118a9643ea8Slogwang  *    allocate more timeout table slots when table overflows.
119a9643ea8Slogwang  */
120a9643ea8Slogwang u_int callwheelsize, callwheelmask;
121a9643ea8Slogwang 
122a9643ea8Slogwang /*
123a9643ea8Slogwang  * The callout cpu exec entities represent informations necessary for
124a9643ea8Slogwang  * describing the state of callouts currently running on the CPU and the ones
125a9643ea8Slogwang  * necessary for migrating callouts to the new callout cpu. In particular,
126a9643ea8Slogwang  * the first entry of the array cc_exec_entity holds informations for callout
127a9643ea8Slogwang  * running in SWI thread context, while the second one holds informations
128a9643ea8Slogwang  * for callout running directly from hardware interrupt context.
129a9643ea8Slogwang  * The cached informations are very important for deferring migration when
130a9643ea8Slogwang  * the migrating callout is already running.
131a9643ea8Slogwang  */
132a9643ea8Slogwang struct cc_exec {
133a9643ea8Slogwang     struct callout *cc_curr;
134a9643ea8Slogwang     void (*cc_drain)(void *);
135a9643ea8Slogwang     bool cc_cancel;
136a9643ea8Slogwang     bool cc_waiting;
137a9643ea8Slogwang };
138a9643ea8Slogwang 
139a9643ea8Slogwang /*
140a9643ea8Slogwang  * There is one struct callout_cpu per cpu, holding all relevant
141a9643ea8Slogwang  * state for the callout processing thread on the individual CPU.
142a9643ea8Slogwang  */
143a9643ea8Slogwang struct callout_cpu {
144a9643ea8Slogwang     struct mtx_padalign cc_lock;
145a9643ea8Slogwang     struct cc_exec cc_exec_entity[2];
146a9643ea8Slogwang     struct callout *cc_next;
147a9643ea8Slogwang     struct callout *cc_callout;
148a9643ea8Slogwang     struct callout_list *cc_callwheel;
149a9643ea8Slogwang     struct callout_tailq cc_expireq;
150a9643ea8Slogwang     struct callout_slist cc_callfree;
1515e5c25c3Slogwang     int cc_softticks;
152a9643ea8Slogwang     void *cc_cookie;
153a9643ea8Slogwang     u_int cc_bucket;
154a9643ea8Slogwang     u_int cc_inited;
155a9643ea8Slogwang     char cc_ktr_event_name[20];
156a9643ea8Slogwang };
157a9643ea8Slogwang 
158a9643ea8Slogwang #define callout_migrating(c)    ((c)->c_iflags & CALLOUT_DFRMIGRATION)
159a9643ea8Slogwang 
160a9643ea8Slogwang #define cc_exec_curr(cc, dir)        cc->cc_exec_entity[dir].cc_curr
161a9643ea8Slogwang #define cc_exec_drain(cc, dir)       cc->cc_exec_entity[dir].cc_drain
162a9643ea8Slogwang #define cc_exec_next(cc)             cc->cc_next
163a9643ea8Slogwang #define cc_exec_cancel(cc, dir)      cc->cc_exec_entity[dir].cc_cancel
164a9643ea8Slogwang #define cc_exec_waiting(cc, dir)     cc->cc_exec_entity[dir].cc_waiting
165a9643ea8Slogwang struct callout_cpu cc_cpu;
166a9643ea8Slogwang #define CC_CPU(cpu)    &cc_cpu
167a9643ea8Slogwang #define CC_SELF()      &cc_cpu
168a9643ea8Slogwang #define CC_LOCK(cc)           mtx_lock_spin(&(cc)->cc_lock)
169a9643ea8Slogwang #define CC_UNLOCK(cc)         mtx_unlock_spin(&(cc)->cc_lock)
170a9643ea8Slogwang #define CC_LOCK_ASSERT(cc)    mtx_assert(&(cc)->cc_lock, MA_OWNED)
171a9643ea8Slogwang 
172a9643ea8Slogwang static int timeout_cpu;
173a9643ea8Slogwang 
174a9643ea8Slogwang static void callout_cpu_init(struct callout_cpu *cc, int cpu);
175a9643ea8Slogwang static void softclock_call_cc(struct callout *c, struct callout_cpu *cc,
176a9643ea8Slogwang #ifdef CALLOUT_PROFILING
177a9643ea8Slogwang     int *mpcalls, int *lockcalls, int *gcalls,
178a9643ea8Slogwang #endif
179a9643ea8Slogwang     int direct);
180a9643ea8Slogwang 
181a9643ea8Slogwang static MALLOC_DEFINE(M_CALLOUT, "callout", "Callout datastructures");
182a9643ea8Slogwang 
183a9643ea8Slogwang /**
184a9643ea8Slogwang  * Locked by cc_lock:
185a9643ea8Slogwang  *   cc_curr         - If a callout is in progress, it is cc_curr.
186a9643ea8Slogwang  *                     If cc_curr is non-NULL, threads waiting in
187a9643ea8Slogwang  *                     callout_drain() will be woken up as soon as the
188a9643ea8Slogwang  *                     relevant callout completes.
189a9643ea8Slogwang  *   cc_cancel       - Changing to 1 with both callout_lock and cc_lock held
190a9643ea8Slogwang  *                     guarantees that the current callout will not run.
191a9643ea8Slogwang  *                     The softclock() function sets this to 0 before it
192a9643ea8Slogwang  *                     drops callout_lock to acquire c_lock, and it calls
193a9643ea8Slogwang  *                     the handler only if curr_cancelled is still 0 after
194a9643ea8Slogwang  *                     cc_lock is successfully acquired.
195a9643ea8Slogwang  *   cc_waiting      - If a thread is waiting in callout_drain(), then
196a9643ea8Slogwang  *                     callout_wait is nonzero.  Set only when
197a9643ea8Slogwang  *                     cc_curr is non-NULL.
198a9643ea8Slogwang  */
199a9643ea8Slogwang 
200a9643ea8Slogwang /*
201a9643ea8Slogwang  * Resets the execution entity tied to a specific callout cpu.
202a9643ea8Slogwang  */
203a9643ea8Slogwang static void
cc_cce_cleanup(struct callout_cpu * cc,int direct)204a9643ea8Slogwang cc_cce_cleanup(struct callout_cpu *cc, int direct)
205a9643ea8Slogwang {
206a9643ea8Slogwang     cc_exec_curr(cc, direct) = NULL;
207a9643ea8Slogwang     cc_exec_cancel(cc, direct) = false;
208a9643ea8Slogwang     cc_exec_waiting(cc, direct) = false;
209a9643ea8Slogwang }
210a9643ea8Slogwang 
211a9643ea8Slogwang /*
212a9643ea8Slogwang  * Checks if migration is requested by a specific callout cpu.
213a9643ea8Slogwang  */
214a9643ea8Slogwang static int
cc_cce_migrating(struct callout_cpu * cc,int direct)215a9643ea8Slogwang cc_cce_migrating(struct callout_cpu *cc, int direct)
216a9643ea8Slogwang {
217a9643ea8Slogwang     return (0);
218a9643ea8Slogwang }
219a9643ea8Slogwang 
220a9643ea8Slogwang /*
221a9643ea8Slogwang  * Kernel low level callwheel initialization
222a9643ea8Slogwang  * called on cpu0 during kernel startup.
223a9643ea8Slogwang  */
224a9643ea8Slogwang static void
callout_callwheel_init(void * dummy)225a9643ea8Slogwang callout_callwheel_init(void *dummy)
226a9643ea8Slogwang {
227a9643ea8Slogwang     struct callout_cpu *cc;
228a9643ea8Slogwang 
229a9643ea8Slogwang     /*
230a9643ea8Slogwang      * Calculate the size of the callout wheel and the preallocated
231a9643ea8Slogwang      * timeout() structures.
232a9643ea8Slogwang      * XXX: Clip callout to result of previous function of maxusers
233a9643ea8Slogwang      * maximum 384.  This is still huge, but acceptable.
234a9643ea8Slogwang      */
235a9643ea8Slogwang     memset(CC_CPU(0), 0, sizeof(cc_cpu));
236a9643ea8Slogwang     ncallout = imin(16 + maxproc + maxfiles, 18508);
237a9643ea8Slogwang     TUNABLE_INT_FETCH("kern.ncallout", &ncallout);
238a9643ea8Slogwang 
239a9643ea8Slogwang     /*
240a9643ea8Slogwang      * Calculate callout wheel size, should be next power of two higher
241a9643ea8Slogwang      * than 'ncallout'.
242a9643ea8Slogwang      */
243a9643ea8Slogwang     callwheelsize = 1 << fls(ncallout);
244a9643ea8Slogwang     callwheelmask = callwheelsize - 1;
245a9643ea8Slogwang 
246a9643ea8Slogwang     /*
247a9643ea8Slogwang      * Fetch whether we're pinning the swi's or not.
248a9643ea8Slogwang      */
249a9643ea8Slogwang     TUNABLE_INT_FETCH("kern.pin_default_swi", &pin_default_swi);
250a9643ea8Slogwang     TUNABLE_INT_FETCH("kern.pin_pcpu_swi", &pin_pcpu_swi);
251a9643ea8Slogwang 
252a9643ea8Slogwang     /*
253a9643ea8Slogwang      * Only cpu0 handles timeout(9) and receives a preallocation.
254a9643ea8Slogwang      *
255a9643ea8Slogwang      * XXX: Once all timeout(9) consumers are converted this can
256a9643ea8Slogwang      * be removed.
257a9643ea8Slogwang      */
258a9643ea8Slogwang     timeout_cpu = PCPU_GET(cpuid);
259a9643ea8Slogwang     cc = CC_CPU(timeout_cpu);
260a9643ea8Slogwang     cc->cc_callout = malloc(ncallout * sizeof(struct callout),
261a9643ea8Slogwang         M_CALLOUT, M_WAITOK);
262a9643ea8Slogwang     callout_cpu_init(cc, timeout_cpu);
263a9643ea8Slogwang }
264a9643ea8Slogwang SYSINIT(callwheel_init, SI_SUB_CPU, SI_ORDER_ANY, callout_callwheel_init, NULL);
265a9643ea8Slogwang 
266a9643ea8Slogwang /*
267a9643ea8Slogwang  * Initialize the per-cpu callout structures.
268a9643ea8Slogwang  */
269a9643ea8Slogwang static void
callout_cpu_init(struct callout_cpu * cc,int cpu)270a9643ea8Slogwang callout_cpu_init(struct callout_cpu *cc, int cpu)
271a9643ea8Slogwang {
272a9643ea8Slogwang     struct callout *c;
273a9643ea8Slogwang     int i;
274a9643ea8Slogwang 
275a9643ea8Slogwang     mtx_init(&cc->cc_lock, "callout", NULL, MTX_SPIN | MTX_RECURSE);
276a9643ea8Slogwang     SLIST_INIT(&cc->cc_callfree);
277a9643ea8Slogwang     cc->cc_inited = 1;
278a9643ea8Slogwang     cc->cc_callwheel = malloc(sizeof(struct callout_list) * callwheelsize,
279a9643ea8Slogwang         M_CALLOUT, M_WAITOK);
280a9643ea8Slogwang     for (i = 0; i < callwheelsize; i++)
281a9643ea8Slogwang         LIST_INIT(&cc->cc_callwheel[i]);
282a9643ea8Slogwang     TAILQ_INIT(&cc->cc_expireq);
283a9643ea8Slogwang     for (i = 0; i < 2; i++)
284a9643ea8Slogwang         cc_cce_cleanup(cc, i);
285a9643ea8Slogwang     snprintf(cc->cc_ktr_event_name, sizeof(cc->cc_ktr_event_name),
286a9643ea8Slogwang         "callwheel cpu %d", cpu);
287a9643ea8Slogwang     if (cc->cc_callout == NULL)    /* Only cpu0 handles timeout(9) */
288a9643ea8Slogwang         return;
289a9643ea8Slogwang     for (i = 0; i < ncallout; i++) {
290a9643ea8Slogwang         c = &cc->cc_callout[i];
291a9643ea8Slogwang         callout_init(c, 0);
292a9643ea8Slogwang         c->c_iflags = CALLOUT_LOCAL_ALLOC;
293a9643ea8Slogwang         SLIST_INSERT_HEAD(&cc->cc_callfree, c, c_links.sle);
294a9643ea8Slogwang     }
295a9643ea8Slogwang }
296a9643ea8Slogwang 
297a9643ea8Slogwang static inline u_int
callout_get_bucket(int to_ticks)2985e5c25c3Slogwang callout_get_bucket(int to_ticks)
299a9643ea8Slogwang {
3005e5c25c3Slogwang     return (to_ticks & callwheelmask);
301a9643ea8Slogwang }
302a9643ea8Slogwang 
303a9643ea8Slogwang void
callout_tick(void)3045e5c25c3Slogwang callout_tick(void)
305a9643ea8Slogwang {
306a9643ea8Slogwang     struct callout_cpu *cc;
3075e5c25c3Slogwang     int need_softclock;
3085e5c25c3Slogwang     int bucket;
309a9643ea8Slogwang 
3105e5c25c3Slogwang     /*
3115e5c25c3Slogwang      * Process callouts at a very low cpu priority, so we don't keep the
3125e5c25c3Slogwang      * relatively high clock interrupt priority any longer than necessary.
3135e5c25c3Slogwang      */
3145e5c25c3Slogwang     need_softclock = 0;
315a9643ea8Slogwang     cc = CC_SELF();
3165e5c25c3Slogwang     mtx_lock(&cc->cc_lock);
3175e5c25c3Slogwang     for (; (cc->cc_softticks - ticks) < 0; cc->cc_softticks++) {
3185e5c25c3Slogwang         bucket = cc->cc_softticks & callwheelmask;
3195e5c25c3Slogwang         if (!LIST_EMPTY(&cc->cc_callwheel[bucket])) {
3205e5c25c3Slogwang             need_softclock = 1;
3215e5c25c3Slogwang             break;
322a9643ea8Slogwang         }
323a9643ea8Slogwang     }
3245e5c25c3Slogwang     mtx_unlock(&cc->cc_lock);
325a9643ea8Slogwang     /*
326a9643ea8Slogwang      * swi_sched acquires the thread lock, so we don't want to call it
327a9643ea8Slogwang      * with cc_lock held; incorrect locking order.
328a9643ea8Slogwang      */
3295e5c25c3Slogwang     if (need_softclock)
330a9643ea8Slogwang         softclock(cc);
331a9643ea8Slogwang }
332a9643ea8Slogwang 
333a9643ea8Slogwang static struct callout_cpu *
callout_lock(struct callout * c)334a9643ea8Slogwang callout_lock(struct callout *c)
335a9643ea8Slogwang {
336a9643ea8Slogwang     struct callout_cpu *cc;
337a9643ea8Slogwang     int cpu;
338a9643ea8Slogwang 
339a9643ea8Slogwang     for (;;) {
340a9643ea8Slogwang         cpu = c->c_cpu;
341a9643ea8Slogwang         cc = CC_CPU(cpu);
342a9643ea8Slogwang         CC_LOCK(cc);
343a9643ea8Slogwang         if (cpu == c->c_cpu)
344a9643ea8Slogwang             break;
345a9643ea8Slogwang         CC_UNLOCK(cc);
346a9643ea8Slogwang     }
347a9643ea8Slogwang     return (cc);
348a9643ea8Slogwang }
349a9643ea8Slogwang 
350a9643ea8Slogwang static void
callout_cc_add(struct callout * c,struct callout_cpu * cc,int to_ticks,void (* func)(void *),void * arg,int cpu,int flags)351a9643ea8Slogwang callout_cc_add(struct callout *c, struct callout_cpu *cc,
3525e5c25c3Slogwang     int to_ticks, void (*func)(void *), void *arg, int cpu, int flags)
353a9643ea8Slogwang {
354a9643ea8Slogwang     int bucket;
355a9643ea8Slogwang 
356a9643ea8Slogwang     CC_LOCK_ASSERT(cc);
3575e5c25c3Slogwang 
358a9643ea8Slogwang     c->c_arg = arg;
359a9643ea8Slogwang     c->c_iflags |= CALLOUT_PENDING;
360a9643ea8Slogwang     c->c_iflags &= ~CALLOUT_PROCESSED;
361a9643ea8Slogwang     c->c_flags |= CALLOUT_ACTIVE;
362a9643ea8Slogwang     if (flags & C_DIRECT_EXEC)
363a9643ea8Slogwang         c->c_iflags |= CALLOUT_DIRECT;
364a9643ea8Slogwang     c->c_func = func;
3655e5c25c3Slogwang     c->c_time = ticks + to_ticks;
366a9643ea8Slogwang     bucket = callout_get_bucket(c->c_time);
367a9643ea8Slogwang     LIST_INSERT_HEAD(&cc->cc_callwheel[bucket], c, c_links.le);
368a9643ea8Slogwang     if (cc->cc_bucket == bucket)
369a9643ea8Slogwang         cc_exec_next(cc) = c;
370a9643ea8Slogwang }
371a9643ea8Slogwang 
372a9643ea8Slogwang static void
callout_cc_del(struct callout * c,struct callout_cpu * cc)373a9643ea8Slogwang callout_cc_del(struct callout *c, struct callout_cpu *cc)
374a9643ea8Slogwang {
375a9643ea8Slogwang 
376a9643ea8Slogwang     if ((c->c_iflags & CALLOUT_LOCAL_ALLOC) == 0)
377a9643ea8Slogwang         return;
378a9643ea8Slogwang     c->c_func = NULL;
379a9643ea8Slogwang     SLIST_INSERT_HEAD(&cc->cc_callfree, c, c_links.sle);
380a9643ea8Slogwang }
381a9643ea8Slogwang 
382a9643ea8Slogwang static void
softclock_call_cc(struct callout * c,struct callout_cpu * cc,int * mpcalls,int * lockcalls,int * gcalls,int direct)383a9643ea8Slogwang softclock_call_cc(struct callout *c, struct callout_cpu *cc,
384a9643ea8Slogwang #ifdef CALLOUT_PROFILING
385a9643ea8Slogwang     int *mpcalls, int *lockcalls, int *gcalls,
386a9643ea8Slogwang #endif
387a9643ea8Slogwang     int direct)
388a9643ea8Slogwang {
389a9643ea8Slogwang     struct rm_priotracker tracker;
390a9643ea8Slogwang     void (*c_func)(void *);
391a9643ea8Slogwang     void *c_arg;
392a9643ea8Slogwang     struct lock_class *class;
393a9643ea8Slogwang     struct lock_object *c_lock;
394a9643ea8Slogwang     uintptr_t lock_status;
395a9643ea8Slogwang     int c_iflags;
396a9643ea8Slogwang #if defined(DIAGNOSTIC) || defined(CALLOUT_PROFILING)
397a9643ea8Slogwang     sbintime_t sbt1, sbt2;
398a9643ea8Slogwang     struct timespec ts2;
399a9643ea8Slogwang     static sbintime_t maxdt = 2 * SBT_1MS;    /* 2 msec */
400a9643ea8Slogwang     static timeout_t *lastfunc;
401a9643ea8Slogwang #endif
402a9643ea8Slogwang 
403a9643ea8Slogwang     KASSERT((c->c_iflags & CALLOUT_PENDING) == CALLOUT_PENDING,
404a9643ea8Slogwang         ("softclock_call_cc: pend %p %x", c, c->c_iflags));
405a9643ea8Slogwang     KASSERT((c->c_flags & CALLOUT_ACTIVE) == CALLOUT_ACTIVE,
406a9643ea8Slogwang         ("softclock_call_cc: act %p %x", c, c->c_flags));
407a9643ea8Slogwang     class = (c->c_lock != NULL) ? LOCK_CLASS(c->c_lock) : NULL;
408a9643ea8Slogwang     lock_status = 0;
409a9643ea8Slogwang     if (c->c_flags & CALLOUT_SHAREDLOCK) {
410a9643ea8Slogwang         if (class == &lock_class_rm)
411a9643ea8Slogwang             lock_status = (uintptr_t)&tracker;
412a9643ea8Slogwang         else
413a9643ea8Slogwang             lock_status = 1;
414a9643ea8Slogwang     }
415a9643ea8Slogwang     c_lock = c->c_lock;
416a9643ea8Slogwang     c_func = c->c_func;
417a9643ea8Slogwang     c_arg = c->c_arg;
418a9643ea8Slogwang     c_iflags = c->c_iflags;
419a9643ea8Slogwang     if (c->c_iflags & CALLOUT_LOCAL_ALLOC)
420a9643ea8Slogwang         c->c_iflags = CALLOUT_LOCAL_ALLOC;
421a9643ea8Slogwang     else
422a9643ea8Slogwang         c->c_iflags &= ~CALLOUT_PENDING;
423a9643ea8Slogwang 
424a9643ea8Slogwang     cc_exec_curr(cc, direct) = c;
425a9643ea8Slogwang     cc_exec_cancel(cc, direct) = false;
426a9643ea8Slogwang     cc_exec_drain(cc, direct) = NULL;
427a9643ea8Slogwang     CC_UNLOCK(cc);
428a9643ea8Slogwang     if (c_lock != NULL) {
429a9643ea8Slogwang         class->lc_lock(c_lock, lock_status);
430a9643ea8Slogwang         /*
431a9643ea8Slogwang          * The callout may have been cancelled
432a9643ea8Slogwang          * while we switched locks.
433a9643ea8Slogwang          */
434a9643ea8Slogwang         if (cc_exec_cancel(cc, direct)) {
435a9643ea8Slogwang             class->lc_unlock(c_lock);
436a9643ea8Slogwang             goto skip;
437a9643ea8Slogwang         }
438a9643ea8Slogwang         /* The callout cannot be stopped now. */
439a9643ea8Slogwang         cc_exec_cancel(cc, direct) = true;
440a9643ea8Slogwang         if (c_lock == &Giant.lock_object) {
441a9643ea8Slogwang #ifdef CALLOUT_PROFILING
442a9643ea8Slogwang             (*gcalls)++;
443a9643ea8Slogwang #endif
444a9643ea8Slogwang             CTR3(KTR_CALLOUT, "callout giant %p func %p arg %p",
445a9643ea8Slogwang                 c, c_func, c_arg);
446a9643ea8Slogwang         } else {
447a9643ea8Slogwang #ifdef CALLOUT_PROFILING
448a9643ea8Slogwang             (*lockcalls)++;
449a9643ea8Slogwang #endif
450a9643ea8Slogwang             CTR3(KTR_CALLOUT, "callout lock %p func %p arg %p",
451a9643ea8Slogwang                 c, c_func, c_arg);
452a9643ea8Slogwang         }
453a9643ea8Slogwang     } else {
454a9643ea8Slogwang #ifdef CALLOUT_PROFILING
455a9643ea8Slogwang         (*mpcalls)++;
456a9643ea8Slogwang #endif
457a9643ea8Slogwang         CTR3(KTR_CALLOUT, "callout %p func %p arg %p",
458a9643ea8Slogwang             c, c_func, c_arg);
459a9643ea8Slogwang     }
460a9643ea8Slogwang     KTR_STATE3(KTR_SCHED, "callout", cc->cc_ktr_event_name, "running",
461a9643ea8Slogwang         "func:%p", c_func, "arg:%p", c_arg, "direct:%d", direct);
462a9643ea8Slogwang #if defined(DIAGNOSTIC) || defined(CALLOUT_PROFILING)
463a9643ea8Slogwang     sbt1 = sbinuptime();
464a9643ea8Slogwang #endif
465a9643ea8Slogwang     THREAD_NO_SLEEPING();
466a9643ea8Slogwang     SDT_PROBE1(callout_execute, , , callout__start, c);
467a9643ea8Slogwang     c_func(c_arg);
468a9643ea8Slogwang     SDT_PROBE1(callout_execute, , , callout__end, c);
469a9643ea8Slogwang     THREAD_SLEEPING_OK();
470a9643ea8Slogwang #if defined(DIAGNOSTIC) || defined(CALLOUT_PROFILING)
471a9643ea8Slogwang     sbt2 = sbinuptime();
472a9643ea8Slogwang     sbt2 -= sbt1;
473a9643ea8Slogwang     if (sbt2 > maxdt) {
474a9643ea8Slogwang         if (lastfunc != c_func || sbt2 > maxdt * 2) {
475a9643ea8Slogwang             ts2 = sbttots(sbt2);
476a9643ea8Slogwang             printf(
477a9643ea8Slogwang         "Expensive timeout(9) function: %p(%p) %jd.%09ld s\n",
478a9643ea8Slogwang                 c_func, c_arg, (intmax_t)ts2.tv_sec, ts2.tv_nsec);
479a9643ea8Slogwang         }
480a9643ea8Slogwang         maxdt = sbt2;
481a9643ea8Slogwang         lastfunc = c_func;
482a9643ea8Slogwang     }
483a9643ea8Slogwang #endif
484a9643ea8Slogwang     KTR_STATE0(KTR_SCHED, "callout", cc->cc_ktr_event_name, "idle");
485a9643ea8Slogwang     CTR1(KTR_CALLOUT, "callout %p finished", c);
486a9643ea8Slogwang     if ((c_iflags & CALLOUT_RETURNUNLOCKED) == 0)
487a9643ea8Slogwang         class->lc_unlock(c_lock);
488a9643ea8Slogwang skip:
489a9643ea8Slogwang     CC_LOCK(cc);
490a9643ea8Slogwang     KASSERT(cc_exec_curr(cc, direct) == c, ("mishandled cc_curr"));
491a9643ea8Slogwang     cc_exec_curr(cc, direct) = NULL;
492a9643ea8Slogwang     if (cc_exec_drain(cc, direct)) {
493a9643ea8Slogwang         void (*drain)(void *);
494a9643ea8Slogwang 
495a9643ea8Slogwang         drain = cc_exec_drain(cc, direct);
496a9643ea8Slogwang         cc_exec_drain(cc, direct) = NULL;
497a9643ea8Slogwang         CC_UNLOCK(cc);
498a9643ea8Slogwang         drain(c_arg);
499a9643ea8Slogwang         CC_LOCK(cc);
500a9643ea8Slogwang     }
501a9643ea8Slogwang     if (cc_exec_waiting(cc, direct)) {
502a9643ea8Slogwang         /*
503a9643ea8Slogwang          * There is someone waiting for the
504a9643ea8Slogwang          * callout to complete.
505a9643ea8Slogwang          * If the callout was scheduled for
506a9643ea8Slogwang          * migration just cancel it.
507a9643ea8Slogwang          */
508a9643ea8Slogwang         if (cc_cce_migrating(cc, direct)) {
509a9643ea8Slogwang             cc_cce_cleanup(cc, direct);
510a9643ea8Slogwang 
511a9643ea8Slogwang             /*
512a9643ea8Slogwang              * It should be assert here that the callout is not
513a9643ea8Slogwang              * destroyed but that is not easy.
514a9643ea8Slogwang              */
515a9643ea8Slogwang             c->c_iflags &= ~CALLOUT_DFRMIGRATION;
516a9643ea8Slogwang         }
517a9643ea8Slogwang         cc_exec_waiting(cc, direct) = false;
518a9643ea8Slogwang         CC_UNLOCK(cc);
519a9643ea8Slogwang         wakeup(&cc_exec_waiting(cc, direct));
520a9643ea8Slogwang         CC_LOCK(cc);
521a9643ea8Slogwang     } else if (cc_cce_migrating(cc, direct)) {
522a9643ea8Slogwang         KASSERT((c_iflags & CALLOUT_LOCAL_ALLOC) == 0,
523a9643ea8Slogwang             ("Migrating legacy callout %p", c));
524a9643ea8Slogwang         panic("migration should not happen");
525a9643ea8Slogwang     }
526a9643ea8Slogwang     /*
527a9643ea8Slogwang      * If the current callout is locally allocated (from
528a9643ea8Slogwang      * timeout(9)) then put it on the freelist.
529a9643ea8Slogwang      *
530a9643ea8Slogwang      * Note: we need to check the cached copy of c_iflags because
531a9643ea8Slogwang      * if it was not local, then it's not safe to deref the
532a9643ea8Slogwang      * callout pointer.
533a9643ea8Slogwang      */
534a9643ea8Slogwang     KASSERT((c_iflags & CALLOUT_LOCAL_ALLOC) == 0 ||
535a9643ea8Slogwang         c->c_iflags == CALLOUT_LOCAL_ALLOC,
536a9643ea8Slogwang         ("corrupted callout"));
537a9643ea8Slogwang     if (c_iflags & CALLOUT_LOCAL_ALLOC)
538a9643ea8Slogwang         callout_cc_del(c, cc);
539a9643ea8Slogwang }
540a9643ea8Slogwang 
541a9643ea8Slogwang /*
542a9643ea8Slogwang  * The callout mechanism is based on the work of Adam M. Costello and
543a9643ea8Slogwang  * George Varghese, published in a technical report entitled "Redesigning
544a9643ea8Slogwang  * the BSD Callout and Timer Facilities" and modified slightly for inclusion
545a9643ea8Slogwang  * in FreeBSD by Justin T. Gibbs.  The original work on the data structures
546a9643ea8Slogwang  * used in this implementation was published by G. Varghese and T. Lauck in
547a9643ea8Slogwang  * the paper "Hashed and Hierarchical Timing Wheels: Data Structures for
548a9643ea8Slogwang  * the Efficient Implementation of a Timer Facility" in the Proceedings of
549a9643ea8Slogwang  * the 11th ACM Annual Symposium on Operating Systems Principles,
550a9643ea8Slogwang  * Austin, Texas Nov 1987.
551a9643ea8Slogwang  */
552a9643ea8Slogwang 
553a9643ea8Slogwang /*
554a9643ea8Slogwang  * Software (low priority) clock interrupt.
555a9643ea8Slogwang  * Run periodic events from timeout queue.
556a9643ea8Slogwang  */
557a9643ea8Slogwang void
softclock(void * arg)558a9643ea8Slogwang softclock(void *arg)
559a9643ea8Slogwang {
560a9643ea8Slogwang     struct callout *c;
5615e5c25c3Slogwang     struct callout_cpu *cc;
5625e5c25c3Slogwang     struct callout_list *sc;
5635e5c25c3Slogwang     int curticks;
564a9643ea8Slogwang #ifdef CALLOUT_PROFILING
5655e5c25c3Slogwang     int depth = 0, gcalls = 0, mpcalls = 0, lockcalls = 0;
566a9643ea8Slogwang #endif
567a9643ea8Slogwang 
568a9643ea8Slogwang     cc = (struct callout_cpu *)arg;
569a9643ea8Slogwang     CC_LOCK(cc);
5705e5c25c3Slogwang 
5715e5c25c3Slogwang     while (cc->cc_softticks != ticks) {
5725e5c25c3Slogwang         /*
5735e5c25c3Slogwang          * cc_softticks may be modified by hard clock, so cache
5745e5c25c3Slogwang          * it while we work on a given bucket.
5755e5c25c3Slogwang          */
5765e5c25c3Slogwang         curticks = cc->cc_softticks;
5775e5c25c3Slogwang         cc->cc_softticks++;
5785e5c25c3Slogwang         sc = &cc->cc_callwheel[curticks & callwheelmask];
5795e5c25c3Slogwang         c = LIST_FIRST(sc);
5805e5c25c3Slogwang         while (c) {
5815e5c25c3Slogwang #ifdef CALLOUT_PROFILING
5825e5c25c3Slogwang             depth++;
5835e5c25c3Slogwang #endif
5845e5c25c3Slogwang             if (c->c_time != curticks) {
5855e5c25c3Slogwang                 c = LIST_NEXT(c, c_links.le);
5865e5c25c3Slogwang             } else {
5875e5c25c3Slogwang                 cc_exec_next(cc) =
5885e5c25c3Slogwang                     LIST_NEXT(c, c_links.le);
5895e5c25c3Slogwang                 cc->cc_bucket = callout_get_bucket(curticks);
5905e5c25c3Slogwang                 LIST_REMOVE(c, c_links.le);
591a9643ea8Slogwang                 softclock_call_cc(c, cc,
592a9643ea8Slogwang #ifdef CALLOUT_PROFILING
593a9643ea8Slogwang                     &mpcalls, &lockcalls, &gcalls,
594a9643ea8Slogwang #endif
5955e5c25c3Slogwang                     1);
5965e5c25c3Slogwang                 c = cc_exec_next(cc);
5975e5c25c3Slogwang                 cc_exec_next(cc) = NULL;
598a9643ea8Slogwang             }
5995e5c25c3Slogwang         }
6005e5c25c3Slogwang     }
6015e5c25c3Slogwang 
602a9643ea8Slogwang #ifdef CALLOUT_PROFILING
603a9643ea8Slogwang     avg_depth += (depth * 1000 - avg_depth) >> 8;
604a9643ea8Slogwang     avg_mpcalls += (mpcalls * 1000 - avg_mpcalls) >> 8;
605a9643ea8Slogwang     avg_lockcalls += (lockcalls * 1000 - avg_lockcalls) >> 8;
606a9643ea8Slogwang     avg_gcalls += (gcalls * 1000 - avg_gcalls) >> 8;
607a9643ea8Slogwang #endif
608a9643ea8Slogwang     CC_UNLOCK(cc);
609a9643ea8Slogwang }
610a9643ea8Slogwang 
61122ce4affSfengbojiang #if 0
612a9643ea8Slogwang /*
613a9643ea8Slogwang  * timeout --
614a9643ea8Slogwang  *    Execute a function after a specified length of time.
615a9643ea8Slogwang  *
616a9643ea8Slogwang  * untimeout --
617a9643ea8Slogwang  *    Cancel previous timeout function call.
618a9643ea8Slogwang  *
619a9643ea8Slogwang  * callout_handle_init --
620a9643ea8Slogwang  *    Initialize a handle so that using it with untimeout is benign.
621a9643ea8Slogwang  *
622a9643ea8Slogwang  *    See AT&T BCI Driver Reference Manual for specification.  This
623a9643ea8Slogwang  *    implementation differs from that one in that although an
624a9643ea8Slogwang  *    identification value is returned from timeout, the original
625a9643ea8Slogwang  *    arguments to timeout as well as the identifier are used to
626a9643ea8Slogwang  *    identify entries for untimeout.
627a9643ea8Slogwang  */
628a9643ea8Slogwang struct callout_handle
629a9643ea8Slogwang timeout(timeout_t *ftn, void *arg, int to_ticks)
630a9643ea8Slogwang {
631a9643ea8Slogwang     struct callout_cpu *cc;
632a9643ea8Slogwang     struct callout *new;
633a9643ea8Slogwang     struct callout_handle handle;
634a9643ea8Slogwang 
635a9643ea8Slogwang     cc = CC_CPU(timeout_cpu);
636a9643ea8Slogwang     CC_LOCK(cc);
637a9643ea8Slogwang     /* Fill in the next free callout structure. */
638a9643ea8Slogwang     new = SLIST_FIRST(&cc->cc_callfree);
639a9643ea8Slogwang     if (new == NULL)
640a9643ea8Slogwang         /* XXX Attempt to malloc first */
641a9643ea8Slogwang         panic("timeout table full");
642a9643ea8Slogwang     SLIST_REMOVE_HEAD(&cc->cc_callfree, c_links.sle);
643a9643ea8Slogwang     callout_reset(new, to_ticks, ftn, arg);
644a9643ea8Slogwang     handle.callout = new;
645a9643ea8Slogwang     CC_UNLOCK(cc);
646a9643ea8Slogwang 
647a9643ea8Slogwang     return (handle);
648a9643ea8Slogwang }
649a9643ea8Slogwang 
650a9643ea8Slogwang void
651a9643ea8Slogwang untimeout(timeout_t *ftn, void *arg, struct callout_handle handle)
652a9643ea8Slogwang {
653a9643ea8Slogwang     struct callout_cpu *cc;
654a9643ea8Slogwang 
655a9643ea8Slogwang     /*
656a9643ea8Slogwang      * Check for a handle that was initialized
657a9643ea8Slogwang      * by callout_handle_init, but never used
658a9643ea8Slogwang      * for a real timeout.
659a9643ea8Slogwang      */
660a9643ea8Slogwang     if (handle.callout == NULL)
661a9643ea8Slogwang         return;
662a9643ea8Slogwang 
663a9643ea8Slogwang     cc = callout_lock(handle.callout);
664a9643ea8Slogwang     if (handle.callout->c_func == ftn && handle.callout->c_arg == arg)
665a9643ea8Slogwang         callout_stop(handle.callout);
666a9643ea8Slogwang     CC_UNLOCK(cc);
667a9643ea8Slogwang }
668a9643ea8Slogwang 
669a9643ea8Slogwang void
670a9643ea8Slogwang callout_handle_init(struct callout_handle *handle)
671a9643ea8Slogwang {
672a9643ea8Slogwang     handle->callout = NULL;
673a9643ea8Slogwang }
67422ce4affSfengbojiang #endif
675a9643ea8Slogwang 
676a9643ea8Slogwang /*
677a9643ea8Slogwang  * New interface; clients allocate their own callout structures.
678a9643ea8Slogwang  *
679a9643ea8Slogwang  * callout_reset() - establish or change a timeout
680a9643ea8Slogwang  * callout_stop() - disestablish a timeout
681a9643ea8Slogwang  * callout_init() - initialize a callout structure so that it can
682a9643ea8Slogwang  *    safely be passed to callout_reset() and callout_stop()
683a9643ea8Slogwang  *
684a9643ea8Slogwang  * <sys/callout.h> defines three convenience macros:
685a9643ea8Slogwang  *
686a9643ea8Slogwang  * callout_active() - returns truth if callout has not been stopped,
687a9643ea8Slogwang  *    drained, or deactivated since the last time the callout was
688a9643ea8Slogwang  *    reset.
689a9643ea8Slogwang  * callout_pending() - returns truth if callout is still waiting for timeout
690a9643ea8Slogwang  * callout_deactivate() - marks the callout as having been serviced
691a9643ea8Slogwang  */
692a9643ea8Slogwang int
callout_reset_tick_on(struct callout * c,int to_ticks,void (* ftn)(void *),void * arg,int cpu,int flags)6935e5c25c3Slogwang callout_reset_tick_on(struct callout *c, int to_ticks,
694a9643ea8Slogwang     void (*ftn)(void *), void *arg, int cpu, int flags)
695a9643ea8Slogwang {
696a9643ea8Slogwang     struct callout_cpu *cc;
697a9643ea8Slogwang     int cancelled, direct;
698a9643ea8Slogwang     int ignore_cpu=0;
699a9643ea8Slogwang 
700a9643ea8Slogwang     cancelled = 0;
701a9643ea8Slogwang     if (cpu == -1) {
702a9643ea8Slogwang         ignore_cpu = 1;
703a9643ea8Slogwang     } else if ((cpu >= MAXCPU) ||
704a9643ea8Slogwang            ((CC_CPU(cpu))->cc_inited == 0)) {
705a9643ea8Slogwang         /* Invalid CPU spec */
706a9643ea8Slogwang         panic("Invalid CPU in callout %d", cpu);
707a9643ea8Slogwang     }
708a9643ea8Slogwang 
709a9643ea8Slogwang     /*
710a9643ea8Slogwang      * This flag used to be added by callout_cc_add, but the
711a9643ea8Slogwang      * first time you call this we could end up with the
712a9643ea8Slogwang      * wrong direct flag if we don't do it before we add.
713a9643ea8Slogwang      */
714a9643ea8Slogwang     if (flags & C_DIRECT_EXEC) {
715a9643ea8Slogwang         direct = 1;
716a9643ea8Slogwang     } else {
717a9643ea8Slogwang         direct = 0;
718a9643ea8Slogwang     }
719a9643ea8Slogwang     KASSERT(!direct || c->c_lock == NULL,
720a9643ea8Slogwang         ("%s: direct callout %p has lock", __func__, c));
721a9643ea8Slogwang     cc = callout_lock(c);
722a9643ea8Slogwang     /*
723a9643ea8Slogwang      * Don't allow migration of pre-allocated callouts lest they
724a9643ea8Slogwang      * become unbalanced or handle the case where the user does
725a9643ea8Slogwang      * not care.
726a9643ea8Slogwang      */
727a9643ea8Slogwang     if ((c->c_iflags & CALLOUT_LOCAL_ALLOC) ||
728a9643ea8Slogwang         ignore_cpu) {
729a9643ea8Slogwang         cpu = c->c_cpu;
730a9643ea8Slogwang     }
731a9643ea8Slogwang 
732a9643ea8Slogwang     if (cc_exec_curr(cc, direct) == c) {
733a9643ea8Slogwang         /*
734a9643ea8Slogwang          * We're being asked to reschedule a callout which is
735a9643ea8Slogwang          * currently in progress.  If there is a lock then we
736a9643ea8Slogwang          * can cancel the callout if it has not really started.
737a9643ea8Slogwang          */
738a9643ea8Slogwang         if (c->c_lock != NULL && !cc_exec_cancel(cc, direct))
739a9643ea8Slogwang             cancelled = cc_exec_cancel(cc, direct) = true;
740a9643ea8Slogwang         if (cc_exec_waiting(cc, direct)) {
741a9643ea8Slogwang             /*
742a9643ea8Slogwang              * Someone has called callout_drain to kill this
743a9643ea8Slogwang              * callout.  Don't reschedule.
744a9643ea8Slogwang              */
745a9643ea8Slogwang             CTR4(KTR_CALLOUT, "%s %p func %p arg %p",
746a9643ea8Slogwang                 cancelled ? "cancelled" : "failed to cancel",
747a9643ea8Slogwang                 c, c->c_func, c->c_arg);
748a9643ea8Slogwang             CC_UNLOCK(cc);
749a9643ea8Slogwang             return (cancelled);
750a9643ea8Slogwang         }
751a9643ea8Slogwang     }
752a9643ea8Slogwang     if (c->c_iflags & CALLOUT_PENDING) {
753a9643ea8Slogwang         if ((c->c_iflags & CALLOUT_PROCESSED) == 0) {
754a9643ea8Slogwang             if (cc_exec_next(cc) == c)
755a9643ea8Slogwang                 cc_exec_next(cc) = LIST_NEXT(c, c_links.le);
756a9643ea8Slogwang             LIST_REMOVE(c, c_links.le);
757a9643ea8Slogwang         } else {
758a9643ea8Slogwang             TAILQ_REMOVE(&cc->cc_expireq, c, c_links.tqe);
759a9643ea8Slogwang         }
760a9643ea8Slogwang         cancelled = 1;
761a9643ea8Slogwang         c->c_iflags &= ~ CALLOUT_PENDING;
762a9643ea8Slogwang         c->c_flags &= ~ CALLOUT_ACTIVE;
763a9643ea8Slogwang     }
764a9643ea8Slogwang 
7655e5c25c3Slogwang     if (to_ticks <= 0)
7665e5c25c3Slogwang         to_ticks = 1;
767a9643ea8Slogwang 
7685e5c25c3Slogwang     callout_cc_add(c, cc, to_ticks, ftn, arg, cpu, flags);
7695e5c25c3Slogwang     CTR5(KTR_CALLOUT, "%sscheduled %p func %p arg %p in %d",
7705e5c25c3Slogwang         cancelled ? "re" : "", c, c->c_func, c->c_arg, to_ticks);
771a9643ea8Slogwang     CC_UNLOCK(cc);
772a9643ea8Slogwang 
773a9643ea8Slogwang     return (cancelled);
774a9643ea8Slogwang }
775a9643ea8Slogwang 
776a9643ea8Slogwang /*
777a9643ea8Slogwang  * Common idioms that can be optimized in the future.
778a9643ea8Slogwang  */
779a9643ea8Slogwang int
callout_schedule_on(struct callout * c,int to_ticks,int cpu)780a9643ea8Slogwang callout_schedule_on(struct callout *c, int to_ticks, int cpu)
781a9643ea8Slogwang {
782a9643ea8Slogwang     return callout_reset_on(c, to_ticks, c->c_func, c->c_arg, cpu);
783a9643ea8Slogwang }
784a9643ea8Slogwang 
785a9643ea8Slogwang int
callout_schedule(struct callout * c,int to_ticks)786a9643ea8Slogwang callout_schedule(struct callout *c, int to_ticks)
787a9643ea8Slogwang {
788a9643ea8Slogwang     return callout_reset_on(c, to_ticks, c->c_func, c->c_arg, c->c_cpu);
789a9643ea8Slogwang }
790a9643ea8Slogwang 
791a9643ea8Slogwang int
_callout_stop_safe(struct callout * c,int flags,void (* drain)(void *))792a9643ea8Slogwang _callout_stop_safe(struct callout *c, int flags, void (*drain)(void *))
793a9643ea8Slogwang {
794a9643ea8Slogwang     struct callout_cpu *cc, *old_cc;
795a9643ea8Slogwang     struct lock_class *class;
796a9643ea8Slogwang     int direct, sq_locked, use_lock;
797a9643ea8Slogwang     int cancelled, not_on_a_list;
798a9643ea8Slogwang 
799a9643ea8Slogwang     if ((flags & CS_DRAIN) != 0)
800a9643ea8Slogwang         WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, c->c_lock,
801a9643ea8Slogwang             "calling %s", __func__);
802a9643ea8Slogwang 
803a9643ea8Slogwang     /*
804a9643ea8Slogwang      * Some old subsystems don't hold Giant while running a callout_stop(),
805a9643ea8Slogwang      * so just discard this check for the moment.
806a9643ea8Slogwang      */
807a9643ea8Slogwang     if ((flags & CS_DRAIN) == 0 && c->c_lock != NULL) {
808a9643ea8Slogwang         if (c->c_lock == &Giant.lock_object)
809a9643ea8Slogwang             use_lock = mtx_owned(&Giant);
810a9643ea8Slogwang         else {
811a9643ea8Slogwang             use_lock = 1;
812a9643ea8Slogwang             class = LOCK_CLASS(c->c_lock);
813a9643ea8Slogwang             class->lc_assert(c->c_lock, LA_XLOCKED);
814a9643ea8Slogwang         }
815a9643ea8Slogwang     } else
816a9643ea8Slogwang         use_lock = 0;
817a9643ea8Slogwang     if (c->c_iflags & CALLOUT_DIRECT) {
818a9643ea8Slogwang         direct = 1;
819a9643ea8Slogwang     } else {
820a9643ea8Slogwang         direct = 0;
821a9643ea8Slogwang     }
822a9643ea8Slogwang     sq_locked = 0;
823a9643ea8Slogwang     old_cc = NULL;
824a9643ea8Slogwang again:
825a9643ea8Slogwang     cc = callout_lock(c);
826a9643ea8Slogwang 
827a9643ea8Slogwang     if ((c->c_iflags & (CALLOUT_DFRMIGRATION | CALLOUT_PENDING)) ==
828a9643ea8Slogwang         (CALLOUT_DFRMIGRATION | CALLOUT_PENDING) &&
829a9643ea8Slogwang         ((c->c_flags & CALLOUT_ACTIVE) == CALLOUT_ACTIVE)) {
830a9643ea8Slogwang         /*
831a9643ea8Slogwang          * Special case where this slipped in while we
832a9643ea8Slogwang          * were migrating *as* the callout is about to
833a9643ea8Slogwang          * execute. The caller probably holds the lock
834a9643ea8Slogwang          * the callout wants.
835a9643ea8Slogwang          *
836a9643ea8Slogwang          * Get rid of the migration first. Then set
837a9643ea8Slogwang          * the flag that tells this code *not* to
838a9643ea8Slogwang          * try to remove it from any lists (its not
839a9643ea8Slogwang          * on one yet). When the callout wheel runs,
840a9643ea8Slogwang          * it will ignore this callout.
841a9643ea8Slogwang          */
842a9643ea8Slogwang         c->c_iflags &= ~CALLOUT_PENDING;
843a9643ea8Slogwang         c->c_flags &= ~CALLOUT_ACTIVE;
844a9643ea8Slogwang         not_on_a_list = 1;
845a9643ea8Slogwang     } else {
846a9643ea8Slogwang         not_on_a_list = 0;
847a9643ea8Slogwang     }
848a9643ea8Slogwang 
849a9643ea8Slogwang     /*
850a9643ea8Slogwang      * If the callout was migrating while the callout cpu lock was
851a9643ea8Slogwang      * dropped,  just drop the sleepqueue lock and check the states
852a9643ea8Slogwang      * again.
853a9643ea8Slogwang      */
854a9643ea8Slogwang     if (sq_locked != 0 && cc != old_cc) {
855a9643ea8Slogwang         panic("migration should not happen");
856a9643ea8Slogwang     }
857a9643ea8Slogwang 
858a9643ea8Slogwang     /*
859a9643ea8Slogwang      * If the callout is running, try to stop it or drain it.
860a9643ea8Slogwang      */
861a9643ea8Slogwang     if (cc_exec_curr(cc, direct) == c) {
862a9643ea8Slogwang         /*
863a9643ea8Slogwang          * Succeed we to stop it or not, we must clear the
864a9643ea8Slogwang          * active flag - this is what API users expect.
865a9643ea8Slogwang          */
866a9643ea8Slogwang         c->c_flags &= ~CALLOUT_ACTIVE;
867a9643ea8Slogwang 
868a9643ea8Slogwang         if ((flags & CS_DRAIN) != 0) {
869a9643ea8Slogwang             /*
870a9643ea8Slogwang              * The current callout is running (or just
871a9643ea8Slogwang              * about to run) and blocking is allowed, so
872a9643ea8Slogwang              * just wait for the current invocation to
873a9643ea8Slogwang              * finish.
874a9643ea8Slogwang              */
875a9643ea8Slogwang             while (cc_exec_curr(cc, direct) == c) {
876a9643ea8Slogwang                 /*
877a9643ea8Slogwang                  * Use direct calls to sleepqueue interface
878a9643ea8Slogwang                  * instead of cv/msleep in order to avoid
879a9643ea8Slogwang                  * a LOR between cc_lock and sleepqueue
880a9643ea8Slogwang                  * chain spinlocks.  This piece of code
881a9643ea8Slogwang                  * emulates a msleep_spin() call actually.
882a9643ea8Slogwang                  *
883a9643ea8Slogwang                  * If we already have the sleepqueue chain
884a9643ea8Slogwang                  * locked, then we can safely block.  If we
885a9643ea8Slogwang                  * don't already have it locked, however,
886a9643ea8Slogwang                  * we have to drop the cc_lock to lock
887a9643ea8Slogwang                  * it.  This opens several races, so we
888a9643ea8Slogwang                  * restart at the beginning once we have
889a9643ea8Slogwang                  * both locks.  If nothing has changed, then
890a9643ea8Slogwang                  * we will end up back here with sq_locked
891a9643ea8Slogwang                  * set.
892a9643ea8Slogwang                  */
893a9643ea8Slogwang                 if (!sq_locked) {
894a9643ea8Slogwang                     CC_UNLOCK(cc);
895a9643ea8Slogwang                     sleepq_lock(
896a9643ea8Slogwang                         &cc_exec_waiting(cc, direct));
897a9643ea8Slogwang                     sq_locked = 1;
898a9643ea8Slogwang                     old_cc = cc;
899a9643ea8Slogwang                     goto again;
900a9643ea8Slogwang                 }
901a9643ea8Slogwang 
902a9643ea8Slogwang                 /*
903a9643ea8Slogwang                  * Migration could be cancelled here, but
904a9643ea8Slogwang                  * as long as it is still not sure when it
905a9643ea8Slogwang                  * will be packed up, just let softclock()
906a9643ea8Slogwang                  * take care of it.
907a9643ea8Slogwang                  */
908a9643ea8Slogwang                 cc_exec_waiting(cc, direct) = true;
909a9643ea8Slogwang                 DROP_GIANT();
910a9643ea8Slogwang                 CC_UNLOCK(cc);
911a9643ea8Slogwang                 sleepq_add(
912a9643ea8Slogwang                     &cc_exec_waiting(cc, direct),
913a9643ea8Slogwang                     &cc->cc_lock.lock_object, "codrain",
914a9643ea8Slogwang                     SLEEPQ_SLEEP, 0);
915a9643ea8Slogwang                 sleepq_wait(
916a9643ea8Slogwang                     &cc_exec_waiting(cc, direct),
917a9643ea8Slogwang                          0);
918a9643ea8Slogwang                 sq_locked = 0;
919a9643ea8Slogwang                 old_cc = NULL;
920a9643ea8Slogwang 
921a9643ea8Slogwang                 /* Reacquire locks previously released. */
922a9643ea8Slogwang                 PICKUP_GIANT();
923a9643ea8Slogwang                 CC_LOCK(cc);
924a9643ea8Slogwang             }
925a9643ea8Slogwang         } else if (use_lock &&
926a9643ea8Slogwang                !cc_exec_cancel(cc, direct) && (drain == NULL)) {
927a9643ea8Slogwang 
928a9643ea8Slogwang             /*
929a9643ea8Slogwang              * The current callout is waiting for its
930a9643ea8Slogwang              * lock which we hold.  Cancel the callout
931a9643ea8Slogwang              * and return.  After our caller drops the
932a9643ea8Slogwang              * lock, the callout will be skipped in
933a9643ea8Slogwang              * softclock(). This *only* works with a
934a9643ea8Slogwang              * callout_stop() *not* callout_drain() or
935a9643ea8Slogwang              * callout_async_drain().
936a9643ea8Slogwang              */
937a9643ea8Slogwang             cc_exec_cancel(cc, direct) = true;
938a9643ea8Slogwang             CTR3(KTR_CALLOUT, "cancelled %p func %p arg %p",
939a9643ea8Slogwang                 c, c->c_func, c->c_arg);
940a9643ea8Slogwang             KASSERT(!cc_cce_migrating(cc, direct),
941a9643ea8Slogwang                 ("callout wrongly scheduled for migration"));
942a9643ea8Slogwang             if (callout_migrating(c)) {
943a9643ea8Slogwang                 c->c_iflags &= ~CALLOUT_DFRMIGRATION;
944a9643ea8Slogwang             }
945a9643ea8Slogwang             CC_UNLOCK(cc);
946a9643ea8Slogwang             KASSERT(!sq_locked, ("sleepqueue chain locked"));
947a9643ea8Slogwang             return (1);
948a9643ea8Slogwang         } else if (callout_migrating(c)) {
949a9643ea8Slogwang             /*
950a9643ea8Slogwang              * The callout is currently being serviced
951a9643ea8Slogwang              * and the "next" callout is scheduled at
952a9643ea8Slogwang              * its completion with a migration. We remove
953a9643ea8Slogwang              * the migration flag so it *won't* get rescheduled,
954a9643ea8Slogwang              * but we can't stop the one thats running so
955a9643ea8Slogwang              * we return 0.
956a9643ea8Slogwang              */
957a9643ea8Slogwang             c->c_iflags &= ~CALLOUT_DFRMIGRATION;
958a9643ea8Slogwang             CTR3(KTR_CALLOUT, "postponing stop %p func %p arg %p",
959a9643ea8Slogwang                 c, c->c_func, c->c_arg);
960a9643ea8Slogwang              if (drain) {
961a9643ea8Slogwang                 cc_exec_drain(cc, direct) = drain;
962a9643ea8Slogwang             }
963a9643ea8Slogwang             CC_UNLOCK(cc);
964a9643ea8Slogwang             return ((flags & CS_EXECUTING) != 0);
965a9643ea8Slogwang         }
966a9643ea8Slogwang         CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p",
967a9643ea8Slogwang             c, c->c_func, c->c_arg);
968a9643ea8Slogwang         if (drain) {
969a9643ea8Slogwang             cc_exec_drain(cc, direct) = drain;
970a9643ea8Slogwang         }
971a9643ea8Slogwang         KASSERT(!sq_locked, ("sleepqueue chain still locked"));
972a9643ea8Slogwang         cancelled = ((flags & CS_EXECUTING) != 0);
973a9643ea8Slogwang     } else
974a9643ea8Slogwang         cancelled = 1;
975a9643ea8Slogwang 
976a9643ea8Slogwang     if (sq_locked)
977a9643ea8Slogwang         sleepq_release(&cc_exec_waiting(cc, direct));
978a9643ea8Slogwang 
979a9643ea8Slogwang     if ((c->c_iflags & CALLOUT_PENDING) == 0) {
980a9643ea8Slogwang         CTR3(KTR_CALLOUT, "failed to stop %p func %p arg %p",
981a9643ea8Slogwang             c, c->c_func, c->c_arg);
982a9643ea8Slogwang         /*
983a9643ea8Slogwang          * For not scheduled and not executing callout return
984a9643ea8Slogwang          * negative value.
985a9643ea8Slogwang          */
986a9643ea8Slogwang         if (cc_exec_curr(cc, direct) != c)
987a9643ea8Slogwang             cancelled = -1;
988a9643ea8Slogwang         CC_UNLOCK(cc);
989a9643ea8Slogwang         return (cancelled);
990a9643ea8Slogwang     }
991a9643ea8Slogwang 
992a9643ea8Slogwang     c->c_iflags &= ~CALLOUT_PENDING;
993a9643ea8Slogwang     c->c_flags &= ~CALLOUT_ACTIVE;
994a9643ea8Slogwang 
995a9643ea8Slogwang     CTR3(KTR_CALLOUT, "cancelled %p func %p arg %p",
996a9643ea8Slogwang         c, c->c_func, c->c_arg);
997a9643ea8Slogwang     if (not_on_a_list == 0) {
998a9643ea8Slogwang         if ((c->c_iflags & CALLOUT_PROCESSED) == 0) {
999a9643ea8Slogwang             if (cc_exec_next(cc) == c)
1000a9643ea8Slogwang                 cc_exec_next(cc) = LIST_NEXT(c, c_links.le);
1001a9643ea8Slogwang             LIST_REMOVE(c, c_links.le);
1002a9643ea8Slogwang         } else {
1003a9643ea8Slogwang             TAILQ_REMOVE(&cc->cc_expireq, c, c_links.tqe);
1004a9643ea8Slogwang         }
1005a9643ea8Slogwang     }
1006a9643ea8Slogwang     callout_cc_del(c, cc);
1007a9643ea8Slogwang     CC_UNLOCK(cc);
1008a9643ea8Slogwang     return (cancelled);
1009a9643ea8Slogwang }
1010a9643ea8Slogwang 
1011a9643ea8Slogwang void
callout_init(struct callout * c,int mpsafe)1012a9643ea8Slogwang callout_init(struct callout *c, int mpsafe)
1013a9643ea8Slogwang {
1014a9643ea8Slogwang     bzero(c, sizeof *c);
1015a9643ea8Slogwang     if (mpsafe) {
1016a9643ea8Slogwang         c->c_lock = NULL;
1017a9643ea8Slogwang         c->c_iflags = CALLOUT_RETURNUNLOCKED;
1018a9643ea8Slogwang     } else {
1019a9643ea8Slogwang         c->c_lock = &Giant.lock_object;
1020a9643ea8Slogwang         c->c_iflags = 0;
1021a9643ea8Slogwang     }
1022a9643ea8Slogwang     c->c_cpu = timeout_cpu;
1023a9643ea8Slogwang }
1024a9643ea8Slogwang 
1025a9643ea8Slogwang void
_callout_init_lock(struct callout * c,struct lock_object * lock,int flags)1026a9643ea8Slogwang _callout_init_lock(struct callout *c, struct lock_object *lock, int flags)
1027a9643ea8Slogwang {
1028a9643ea8Slogwang     bzero(c, sizeof *c);
1029a9643ea8Slogwang     c->c_lock = lock;
1030a9643ea8Slogwang     KASSERT((flags & ~(CALLOUT_RETURNUNLOCKED | CALLOUT_SHAREDLOCK)) == 0,
1031a9643ea8Slogwang         ("callout_init_lock: bad flags %d", flags));
1032a9643ea8Slogwang     KASSERT(lock != NULL || (flags & CALLOUT_RETURNUNLOCKED) == 0,
1033a9643ea8Slogwang         ("callout_init_lock: CALLOUT_RETURNUNLOCKED with no lock"));
1034a9643ea8Slogwang     KASSERT(lock == NULL || !(LOCK_CLASS(lock)->lc_flags &
1035a9643ea8Slogwang         (LC_SPINLOCK | LC_SLEEPABLE)), ("%s: invalid lock class",
1036a9643ea8Slogwang         __func__));
1037a9643ea8Slogwang     c->c_iflags = flags & (CALLOUT_RETURNUNLOCKED | CALLOUT_SHAREDLOCK);
1038a9643ea8Slogwang     c->c_cpu = timeout_cpu;
1039a9643ea8Slogwang }
1040a9643ea8Slogwang 
1041a9643ea8Slogwang #ifdef APM_FIXUP_CALLTODO
1042a9643ea8Slogwang /*
1043a9643ea8Slogwang  * Adjust the kernel calltodo timeout list.  This routine is used after
1044a9643ea8Slogwang  * an APM resume to recalculate the calltodo timer list values with the
1045a9643ea8Slogwang  * number of hz's we have been sleeping.  The next hardclock() will detect
1046a9643ea8Slogwang  * that there are fired timers and run softclock() to execute them.
1047a9643ea8Slogwang  *
1048a9643ea8Slogwang  * Please note, I have not done an exhaustive analysis of what code this
1049a9643ea8Slogwang  * might break.  I am motivated to have my select()'s and alarm()'s that
1050a9643ea8Slogwang  * have expired during suspend firing upon resume so that the applications
1051a9643ea8Slogwang  * which set the timer can do the maintanence the timer was for as close
1052a9643ea8Slogwang  * as possible to the originally intended time.  Testing this code for a
1053a9643ea8Slogwang  * week showed that resuming from a suspend resulted in 22 to 25 timers
1054a9643ea8Slogwang  * firing, which seemed independent on whether the suspend was 2 hours or
1055a9643ea8Slogwang  * 2 days.  Your milage may vary.   - Ken Key <[email protected]>
1056a9643ea8Slogwang  */
1057a9643ea8Slogwang void
adjust_timeout_calltodo(struct timeval * time_change)1058a9643ea8Slogwang adjust_timeout_calltodo(struct timeval *time_change)
1059a9643ea8Slogwang {
1060a9643ea8Slogwang     register struct callout *p;
1061a9643ea8Slogwang     unsigned long delta_ticks;
1062a9643ea8Slogwang 
1063a9643ea8Slogwang     /*
1064a9643ea8Slogwang      * How many ticks were we asleep?
1065a9643ea8Slogwang      * (stolen from tvtohz()).
1066a9643ea8Slogwang      */
1067a9643ea8Slogwang 
1068a9643ea8Slogwang     /* Don't do anything */
1069a9643ea8Slogwang     if (time_change->tv_sec < 0)
1070a9643ea8Slogwang         return;
1071a9643ea8Slogwang     else if (time_change->tv_sec <= LONG_MAX / 1000000)
1072a9643ea8Slogwang         delta_ticks = howmany(time_change->tv_sec * 1000000 +
1073a9643ea8Slogwang             time_change->tv_usec, tick) + 1;
1074a9643ea8Slogwang     else if (time_change->tv_sec <= LONG_MAX / hz)
1075a9643ea8Slogwang         delta_ticks = time_change->tv_sec * hz +
1076a9643ea8Slogwang             howmany(time_change->tv_usec, tick) + 1;
1077a9643ea8Slogwang     else
1078a9643ea8Slogwang         delta_ticks = LONG_MAX;
1079a9643ea8Slogwang 
1080a9643ea8Slogwang     if (delta_ticks > INT_MAX)
1081a9643ea8Slogwang         delta_ticks = INT_MAX;
1082a9643ea8Slogwang 
1083a9643ea8Slogwang     /*
1084a9643ea8Slogwang      * Now rip through the timer calltodo list looking for timers
1085a9643ea8Slogwang      * to expire.
1086a9643ea8Slogwang      */
1087a9643ea8Slogwang 
1088a9643ea8Slogwang     /* don't collide with softclock() */
1089a9643ea8Slogwang     CC_LOCK(cc);
1090a9643ea8Slogwang     for (p = calltodo.c_next; p != NULL; p = p->c_next) {
1091a9643ea8Slogwang         p->c_time -= delta_ticks;
1092a9643ea8Slogwang 
1093a9643ea8Slogwang         /* Break if the timer had more time on it than delta_ticks */
1094a9643ea8Slogwang         if (p->c_time > 0)
1095a9643ea8Slogwang             break;
1096a9643ea8Slogwang 
1097a9643ea8Slogwang         /* take back the ticks the timer didn't use (p->c_time <= 0) */
1098a9643ea8Slogwang         delta_ticks = -p->c_time;
1099a9643ea8Slogwang     }
1100a9643ea8Slogwang     CC_UNLOCK(cc);
1101a9643ea8Slogwang 
1102a9643ea8Slogwang     return;
1103a9643ea8Slogwang }
1104a9643ea8Slogwang #endif /* APM_FIXUP_CALLTODO */
1105a9643ea8Slogwang 
1106a9643ea8Slogwang static int
flssbt(sbintime_t sbt)1107a9643ea8Slogwang flssbt(sbintime_t sbt)
1108a9643ea8Slogwang {
1109a9643ea8Slogwang 
1110a9643ea8Slogwang     sbt += (uint64_t)sbt >> 1;
1111a9643ea8Slogwang     if (sizeof(long) >= sizeof(sbintime_t))
1112a9643ea8Slogwang         return (flsl(sbt));
1113a9643ea8Slogwang     if (sbt >= SBT_1S)
1114a9643ea8Slogwang         return (flsl(((uint64_t)sbt) >> 32) + 32);
1115a9643ea8Slogwang     return (flsl(sbt));
1116a9643ea8Slogwang }
1117a9643ea8Slogwang 
1118a9643ea8Slogwang /*
1119a9643ea8Slogwang  * Dump immediate statistic snapshot of the scheduled callouts.
1120a9643ea8Slogwang  */
1121a9643ea8Slogwang static int
sysctl_kern_callout_stat(SYSCTL_HANDLER_ARGS)1122a9643ea8Slogwang sysctl_kern_callout_stat(SYSCTL_HANDLER_ARGS)
1123a9643ea8Slogwang {
1124a9643ea8Slogwang     struct callout *tmp;
1125a9643ea8Slogwang     struct callout_cpu *cc;
1126a9643ea8Slogwang     struct callout_list *sc;
11275e5c25c3Slogwang     int st, maxt, tick, now;
11285e5c25c3Slogwang     sbintime_t medt;
11295e5c25c3Slogwang     int ct[64], ccpbk[32];
1130a9643ea8Slogwang     int error, val, i, count, tcum, pcum, maxc, c, medc;
1131a9643ea8Slogwang 
1132a9643ea8Slogwang     val = 0;
1133a9643ea8Slogwang     error = sysctl_handle_int(oidp, &val, 0, req);
1134a9643ea8Slogwang     if (error != 0 || req->newptr == NULL)
1135a9643ea8Slogwang         return (error);
1136a9643ea8Slogwang     count = maxc = 0;
11375e5c25c3Slogwang     st = maxt = 0;
1138a9643ea8Slogwang     bzero(ccpbk, sizeof(ccpbk));
1139a9643ea8Slogwang     bzero(ct, sizeof(ct));
11405e5c25c3Slogwang     now = ticks;
11415e5c25c3Slogwang 
1142a9643ea8Slogwang     cc = CC_CPU(timeout_cpu);
1143a9643ea8Slogwang     CC_LOCK(cc);
1144a9643ea8Slogwang     for (i = 0; i < callwheelsize; i++) {
1145a9643ea8Slogwang         sc = &cc->cc_callwheel[i];
1146a9643ea8Slogwang         c = 0;
1147a9643ea8Slogwang         LIST_FOREACH(tmp, sc, c_links.le) {
1148a9643ea8Slogwang             c++;
11495e5c25c3Slogwang             tick = tmp->c_time - now;
11505e5c25c3Slogwang             if (tick < 0)
11515e5c25c3Slogwang                 tick = 0;
11525e5c25c3Slogwang             st += tick*(1000/hz);
11535e5c25c3Slogwang             if (tick > maxt)
11545e5c25c3Slogwang                 maxt = tick;
11555e5c25c3Slogwang             ct[flssbt(tick)]++;
1156a9643ea8Slogwang         }
1157a9643ea8Slogwang         if (c > maxc)
1158a9643ea8Slogwang             maxc = c;
1159a9643ea8Slogwang         ccpbk[fls(c + c / 2)]++;
1160a9643ea8Slogwang         count += c;
1161a9643ea8Slogwang     }
1162a9643ea8Slogwang     CC_UNLOCK(cc);
1163a9643ea8Slogwang 
1164a9643ea8Slogwang     for (i = 0, tcum = 0; i < 64 && tcum < count / 2; i++)
1165a9643ea8Slogwang         tcum += ct[i];
1166a9643ea8Slogwang     medt = (i >= 2) ? (((sbintime_t)1) << (i - 2)) : 0;
1167a9643ea8Slogwang     for (i = 0, c = 0; i < 32 && c < count / 2; i++)
1168a9643ea8Slogwang         c += ccpbk[i];
1169a9643ea8Slogwang     medc = (i >= 2) ? (1 << (i - 2)) : 0;
1170a9643ea8Slogwang 
1171a9643ea8Slogwang     printf("Scheduled callouts statistic snapshot:\n");
1172a9643ea8Slogwang     printf("  Callouts: %6d  Buckets: %6d*%-3d  Bucket size: 0.%06ds\n",
1173a9643ea8Slogwang         count, callwheelsize, mp_ncpus, 1000000 >> CC_HASH_SHIFT);
1174a9643ea8Slogwang     printf("  C/Bk: med %5d         avg %6d.%06jd  max %6d\n",
1175a9643ea8Slogwang         medc,
1176a9643ea8Slogwang         count / callwheelsize / mp_ncpus,
1177a9643ea8Slogwang         (uint64_t)count * 1000000 / callwheelsize / mp_ncpus % 1000000,
1178a9643ea8Slogwang         maxc);
11795e5c25c3Slogwang     printf("  Time: med %5jd.%06jds avg %6d.%06ds max %ds\n",
1180a9643ea8Slogwang         medt / SBT_1S, (medt & 0xffffffff) * 1000000 >> 32,
11815e5c25c3Slogwang         st / count / 1000, (st / count) % 1000, maxt);
11825e5c25c3Slogwang     printf("  Distribution:       \tbuckets\t   time\t   tcum\n");
1183a9643ea8Slogwang     for (i = 0, tcum = pcum = 0; i < 64; i++) {
11845e5c25c3Slogwang         if (ct[i] == 0)
1185a9643ea8Slogwang             continue;
11865e5c25c3Slogwang         sbintime_t t;
1187a9643ea8Slogwang         t = (i != 0) ? (((sbintime_t)1) << (i - 1)) : 0;
1188a9643ea8Slogwang         tcum += ct[i];
11895e5c25c3Slogwang         printf("  %10jd.%06jds\t 2**%d\t%7d\t%7d\n",
1190a9643ea8Slogwang             t / SBT_1S, (t & 0xffffffff) * 1000000 >> 32,
11915e5c25c3Slogwang             i - 1 - (32 - CC_HASH_SHIFT), ct[i], tcum);
1192a9643ea8Slogwang     }
1193a9643ea8Slogwang     return (error);
1194a9643ea8Slogwang }
1195a9643ea8Slogwang SYSCTL_PROC(_kern, OID_AUTO, callout_stat,
1196a9643ea8Slogwang     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
1197a9643ea8Slogwang     0, 0, sysctl_kern_callout_stat, "I",
1198a9643ea8Slogwang     "Dump immediate statistic snapshot of the scheduled callouts");
1199a9643ea8Slogwang 
1200a9643ea8Slogwang #ifdef FSTACK
1201a9643ea8Slogwang void ff_hardclock(void);
1202a9643ea8Slogwang 
1203a9643ea8Slogwang void
ff_hardclock(void)1204a9643ea8Slogwang ff_hardclock(void)
1205a9643ea8Slogwang {
1206a9643ea8Slogwang     atomic_add_int(&ticks, 1);
12075e5c25c3Slogwang     callout_tick();
1208a9643ea8Slogwang     tc_ticktock(1);
1209a9643ea8Slogwang     cpu_tick_calibration();
1210a9643ea8Slogwang 
1211a9643ea8Slogwang #ifdef DEVICE_POLLING
1212a9643ea8Slogwang     hardclock_device_poll();    /* this is very short and quick */
1213a9643ea8Slogwang #endif /* DEVICE_POLLING */
1214a9643ea8Slogwang }
1215a9643ea8Slogwang 
1216a9643ea8Slogwang static unsigned int
ff_tc_get_timecount(struct timecounter * tc)1217a9643ea8Slogwang ff_tc_get_timecount(struct timecounter *tc)
1218a9643ea8Slogwang {
121939be5a50Slogwang     uint64_t ns;
122039be5a50Slogwang     ns = ff_get_tsc_ns();
122139be5a50Slogwang     return ((ns * tc->tc_frequency) / ff_NSEC_PER_SEC);
1222a9643ea8Slogwang }
1223a9643ea8Slogwang 
1224a9643ea8Slogwang static struct timecounter ff_timecounter = {
12251fdd2a6eSlogwang     ff_tc_get_timecount, 0, ~0u, 100, "ff_clock", 1
1226a9643ea8Slogwang };
1227a9643ea8Slogwang 
1228a9643ea8Slogwang static void
ff_tc_init(void)1229a9643ea8Slogwang ff_tc_init(void)
1230a9643ea8Slogwang {
1231a9643ea8Slogwang     ff_timecounter.tc_frequency = hz;
1232a9643ea8Slogwang     tc_init(&ff_timecounter);
1233a9643ea8Slogwang }
1234a9643ea8Slogwang SYSINIT(ff_tc, SI_SUB_SMP, SI_ORDER_ANY, ff_tc_init, NULL);
1235a9643ea8Slogwang #endif
1236