1.\" $NetBSD: timeout.9,v 1.2 1996/06/23 22:32:34 pk Exp $ 2.\" 3.\" Copyright (c) 1996 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" 6.\" This code is derived from software contributed to The NetBSD Foundation 7.\" by Paul Kranenburg. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 22.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28.\" POSSIBILITY OF SUCH DAMAGE. 29.\" 30.Dd September 1, 2021 31.Dt CALLOUT 9 32.Os 33.Sh NAME 34.Nm callout_active , 35.Nm callout_deactivate , 36.Nm callout_async_drain , 37.Nm callout_drain , 38.Nm callout_init , 39.Nm callout_init_mtx , 40.Nm callout_init_rm , 41.Nm callout_init_rw , 42.Nm callout_pending , 43.Nm callout_reset , 44.Nm callout_reset_curcpu , 45.Nm callout_reset_on , 46.Nm callout_reset_sbt , 47.Nm callout_reset_sbt_curcpu , 48.Nm callout_reset_sbt_on , 49.Nm callout_schedule , 50.Nm callout_schedule_curcpu , 51.Nm callout_schedule_on , 52.Nm callout_schedule_sbt , 53.Nm callout_schedule_sbt_curcpu , 54.Nm callout_schedule_sbt_on , 55.Nm callout_stop , 56.Nm callout_when 57.Nd execute a function after a specified length of time 58.Sh SYNOPSIS 59.In sys/types.h 60.In sys/callout.h 61.Bd -literal 62typedef void callout_func_t (void *); 63.Ed 64.Ft int 65.Fn callout_active "struct callout *c" 66.Ft void 67.Fn callout_deactivate "struct callout *c" 68.Ft int 69.Fn callout_async_drain "struct callout *c" "callout_func_t *drain" 70.Ft int 71.Fn callout_drain "struct callout *c" 72.Ft void 73.Fn callout_init "struct callout *c" "int mpsafe" 74.Ft void 75.Fn callout_init_mtx "struct callout *c" "struct mtx *mtx" "int flags" 76.Ft void 77.Fn callout_init_rm "struct callout *c" "struct rmlock *rm" "int flags" 78.Ft void 79.Fn callout_init_rw "struct callout *c" "struct rwlock *rw" "int flags" 80.Ft int 81.Fn callout_pending "struct callout *c" 82.Ft int 83.Fo callout_reset 84.Fa "struct callout *c" 85.Fa "int ticks" 86.Fa "callout_func_t *func" 87.Fa "void *arg" 88.Fc 89.Ft int 90.Fo callout_reset_curcpu 91.Fa "struct callout *c" 92.Fa "int ticks" 93.Fa "callout_func_t *func" 94.Fa "void *arg" 95.Fc 96.Ft int 97.Fo callout_reset_on 98.Fa "struct callout *c" 99.Fa "int ticks" 100.Fa "callout_func_t *func" 101.Fa "void *arg" 102.Fa "int cpu" 103.Fc 104.Ft int 105.Fo callout_reset_sbt 106.Fa "struct callout *c" 107.Fa "sbintime_t sbt" 108.Fa "sbintime_t pr" 109.Fa "callout_func_t *func" 110.Fa "void *arg" 111.Fa "int flags" 112.Fc 113.Ft int 114.Fo callout_reset_sbt_curcpu 115.Fa "struct callout *c" 116.Fa "sbintime_t sbt" 117.Fa "sbintime_t pr" 118.Fa "callout_func_t *func" 119.Fa "void *arg" 120.Fa "int flags" 121.Fc 122.Ft int 123.Fo callout_reset_sbt_on 124.Fa "struct callout *c" 125.Fa "sbintime_t sbt" 126.Fa "sbintime_t pr" 127.Fa "callout_func_t *func" 128.Fa "void *arg" 129.Fa "int cpu" 130.Fa "int flags" 131.Fc 132.Ft int 133.Fn callout_schedule "struct callout *c" "int ticks" 134.Ft int 135.Fn callout_schedule_curcpu "struct callout *c" "int ticks" 136.Ft int 137.Fn callout_schedule_on "struct callout *c" "int ticks" "int cpu" 138.Ft int 139.Fo callout_schedule_sbt 140.Fa "struct callout *c" 141.Fa "sbintime_t sbt" 142.Fa "sbintime_t pr" 143.Fa "int flags" 144.Fc 145.Ft int 146.Fo callout_schedule_sbt_curcpu 147.Fa "struct callout *c" 148.Fa "sbintime_t sbt" 149.Fa "sbintime_t pr" 150.Fa "int flags" 151.Fc 152.Ft int 153.Fo callout_schedule_sbt_on 154.Fa "struct callout *c" 155.Fa "sbintime_t sbt" 156.Fa "sbintime_t pr" 157.Fa "int cpu" 158.Fa "int flags" 159.Fc 160.Ft int 161.Fn callout_stop "struct callout *c" 162.Ft sbintime_t 163.Fo callout_when 164.Fa "sbintime_t sbt" 165.Fa "sbintime_t precision" 166.Fa "int flags" 167.Fa "sbintime_t *sbt_res" 168.Fa "sbintime_t *precision_res" 169.Fc 170.Sh DESCRIPTION 171The 172.Nm callout 173API is used to schedule a call to an arbitrary function at a specific 174time in the future. 175Consumers of this API are required to allocate a callout structure 176.Pq struct callout 177for each pending function invocation. 178This structure stores state about the pending function invocation including 179the function to be called and the time at which the function should be invoked. 180Pending function calls can be cancelled or rescheduled to a different time. 181In addition, 182a callout structure may be reused to schedule a new function call after a 183scheduled call is completed. 184.Pp 185Callouts only provide a single-shot mode. 186If a consumer requires a periodic timer, 187it must explicitly reschedule each function call. 188This is normally done by rescheduling the subsequent call within the called 189function. 190.Pp 191Callout functions must not sleep. 192They may not acquire sleepable locks, 193wait on condition variables, 194perform blocking allocation requests, 195or invoke any other action that might sleep. 196.Pp 197Each callout structure must be initialized by 198.Fn callout_init , 199.Fn callout_init_mtx , 200.Fn callout_init_rm , 201or 202.Fn callout_init_rw 203before it is passed to any of the other callout functions. 204The 205.Fn callout_init 206function initializes a callout structure in 207.Fa c 208that is not associated with a specific lock. 209If the 210.Fa mpsafe 211argument is zero, 212the callout structure is not considered to be 213.Dq multi-processor safe ; 214and the Giant lock will be acquired before calling the callout function 215and released when the callout function returns. 216.Pp 217The 218.Fn callout_init_mtx , 219.Fn callout_init_rm , 220and 221.Fn callout_init_rw 222functions initialize a callout structure in 223.Fa c 224that is associated with a specific lock. 225The lock is specified by the 226.Fa mtx , 227.Fa rm , 228or 229.Fa rw 230parameter. 231The associated lock must be held while stopping or rescheduling the 232callout. 233The callout subsystem acquires the associated lock before calling the 234callout function and releases it after the function returns. 235If the callout was cancelled while the callout subsystem waited for the 236associated lock, 237the callout function is not called, 238and the associated lock is released. 239This ensures that stopping or rescheduling the callout will abort any 240previously scheduled invocation. 241.Pp 242A sleepable read-mostly lock 243.Po 244one initialized with the 245.Dv RM_SLEEPABLE 246flag 247.Pc 248may not be used with 249.Fn callout_init_rm . 250Similarly, other sleepable lock types such as 251.Xr sx 9 252and 253.Xr lockmgr 9 254cannot be used with callouts because sleeping is not permitted in 255the callout subsystem. 256.Pp 257These 258.Fa flags 259may be specified for 260.Fn callout_init_mtx , 261.Fn callout_init_rm , 262or 263.Fn callout_init_rw : 264.Bl -tag -width ".Dv CALLOUT_RETURNUNLOCKED" 265.It Dv CALLOUT_RETURNUNLOCKED 266The callout function will release the associated lock itself, 267so the callout subsystem should not attempt to unlock it 268after the callout function returns. 269.It Dv CALLOUT_SHAREDLOCK 270The lock is only acquired in read mode when running the callout handler. 271This flag is ignored by 272.Fn callout_init_mtx . 273.El 274.Pp 275The function 276.Fn callout_stop 277cancels a callout 278.Fa c 279if it is currently pending. 280If the callout is pending and successfully stopped, then 281.Fn callout_stop 282returns a value of one. 283If the callout is not set, or 284has already been serviced, then 285negative one is returned. 286If the callout is currently being serviced and cannot be stopped, 287then zero will be returned. 288If the callout is currently being serviced and cannot be stopped, and at the 289same time a next invocation of the same callout is also scheduled, then 290.Fn callout_stop 291unschedules the next run and returns zero. 292If the callout has an associated lock, 293then that lock must be held when this function is called. 294.Pp 295The function 296.Fn callout_async_drain 297is identical to 298.Fn callout_stop 299with one difference. 300When 301.Fn callout_async_drain 302returns zero it will arrange for the function 303.Fa drain 304to be called using the same argument given to the 305.Fn callout_reset 306function. 307.Fn callout_async_drain 308If the callout has an associated lock, 309then that lock must be held when this function is called. 310Note that when stopping multiple callouts that use the same lock it is possible 311to get multiple return's of zero and multiple calls to the 312.Fa drain 313function, depending upon which CPU's the callouts are running. 314The 315.Fa drain 316function itself is called from the context of the completing callout 317i.e. softclock or hardclock, just like a callout itself. 318.Pp 319The function 320.Fn callout_drain 321is identical to 322.Fn callout_stop 323except that it will wait for the callout 324.Fa c 325to complete if it is already in progress. 326This function MUST NOT be called while holding any 327locks on which the callout might block, or deadlock will result. 328Note that if the callout subsystem has already begun processing this 329callout, then the callout function may be invoked before 330.Fn callout_drain 331returns. 332However, the callout subsystem does guarantee that the callout will be 333fully stopped before 334.Fn callout_drain 335returns. 336.Pp 337The 338.Fn callout_reset 339and 340.Fn callout_schedule 341function families schedule a future function invocation for callout 342.Fa c . 343If 344.Fa c 345already has a pending callout, 346it is cancelled before the new invocation is scheduled. 347These functions return a value of one if a pending callout was cancelled 348and zero if there was no pending callout. 349If the callout has an associated lock, 350then that lock must be held when any of these functions are called. 351.Pp 352The time at which the callout function will be invoked is determined by 353either the 354.Fa ticks 355argument or the 356.Fa sbt , 357.Fa pr , 358and 359.Fa flags 360arguments. 361When 362.Fa ticks 363is used, 364the callout is scheduled to execute after 365.Fa ticks Ns No /hz 366seconds. 367Non-positive values of 368.Fa ticks 369are silently converted to the value 370.Sq 1 . 371.Pp 372The 373.Fa sbt , 374.Fa pr , 375and 376.Fa flags 377arguments provide more control over the scheduled time including 378support for higher resolution times, 379specifying the precision of the scheduled time, 380and setting an absolute deadline instead of a relative timeout. 381The callout is scheduled to execute in a time window which begins at 382the time specified in 383.Fa sbt 384and extends for the amount of time specified in 385.Fa pr . 386If 387.Fa sbt 388specifies a time in the past, 389the window is adjusted to start at the current time. 390A non-zero value for 391.Fa pr 392allows the callout subsystem to coalesce callouts scheduled close to each 393other into fewer timer interrupts, 394reducing processing overhead and power consumption. 395These 396.Fa flags 397may be specified to adjust the interpretation of 398.Fa sbt 399and 400.Fa pr : 401.Bl -tag -width ".Dv C_DIRECT_EXEC" 402.It Dv C_ABSOLUTE 403Handle the 404.Fa sbt 405argument as an absolute time since boot. 406By default, 407.Fa sbt 408is treated as a relative amount of time, 409similar to 410.Fa ticks . 411.It Dv C_DIRECT_EXEC 412Run the handler directly from hardware interrupt context instead of from the 413softclock thread. 414This reduces latency and overhead, but puts more constraints on the callout 415function. 416Callout functions run in this context may use only spin mutexes for locking 417and should be as small as possible because they run with absolute priority. 418.It Fn C_PREL 419Specifies relative event time precision as binary logarithm of time interval 420divided by acceptable time deviation: 1 -- 1/2, 2 -- 1/4, etc. 421Note that the larger of 422.Fa pr 423or this value is used as the length of the time window. 424Smaller values 425.Pq which result in larger time intervals 426allow the callout subsystem to aggregate more events in one timer interrupt. 427.It Dv C_PRECALC 428The 429.Fa sbt 430argument specifies the absolute time at which the callout should be run, 431and the 432.Fa pr 433argument specifies the requested precision, which will not be 434adjusted during the scheduling process. 435The 436.Fa sbt 437and 438.Fa pr 439values should be calculated by an earlier call to 440.Fn callout_when 441which uses the user-supplied 442.Fa sbt , 443.Fa pr , 444and 445.Fa flags 446values. 447.It Dv C_HARDCLOCK 448Align the timeouts to 449.Fn hardclock 450calls if possible. 451.El 452.Pp 453The 454.Fn callout_reset 455functions accept a 456.Fa func 457argument which identifies the function to be called when the time expires. 458It must be a pointer to a function that takes a single 459.Fa void * 460argument. 461Upon invocation, 462.Fa func 463will receive 464.Fa arg 465as its only argument. 466The 467.Fn callout_schedule 468functions reuse the 469.Fa func 470and 471.Fa arg 472arguments from the previous callout. 473Note that one of the 474.Fn callout_reset 475functions must always be called to initialize 476.Fa func 477and 478.Fa arg 479before one of the 480.Fn callout_schedule 481functions can be used. 482.Pp 483The callout subsystem provides a softclock thread for each CPU in the system. 484Callouts are assigned to a single CPU and are executed by the softclock thread 485for that CPU. 486Initially, 487callouts are assigned to CPU 0. 488The 489.Fn callout_reset_on , 490.Fn callout_reset_sbt_on , 491.Fn callout_schedule_on 492and 493.Fn callout_schedule_sbt_on 494functions assign the callout to CPU 495.Fa cpu . 496The 497.Fn callout_reset_curcpu , 498.Fn callout_reset_sbt_curpu , 499.Fn callout_schedule_curcpu 500and 501.Fn callout_schedule_sbt_curcpu 502functions assign the callout to the current CPU. 503The 504.Fn callout_reset , 505.Fn callout_reset_sbt , 506.Fn callout_schedule 507and 508.Fn callout_schedule_sbt 509functions schedule the callout to execute in the softclock thread of the CPU 510to which it is currently assigned. 511.Pp 512Softclock threads are not pinned to their respective CPUs by default. 513The softclock thread for CPU 0 can be pinned to CPU 0 by setting the 514.Va kern.pin_default_swi 515loader tunable to a non-zero value. 516Softclock threads for CPUs other than zero can be pinned to their 517respective CPUs by setting the 518.Va kern.pin_pcpu_swi 519loader tunable to a non-zero value. 520.Pp 521The macros 522.Fn callout_pending , 523.Fn callout_active 524and 525.Fn callout_deactivate 526provide access to the current state of the callout. 527The 528.Fn callout_pending 529macro checks whether a callout is 530.Em pending ; 531a callout is considered 532.Em pending 533when a timeout has been set but the time has not yet arrived. 534Note that once the timeout time arrives and the callout subsystem 535starts to process this callout, 536.Fn callout_pending 537will return 538.Dv FALSE 539even though the callout function may not have finished 540.Pq or even begun 541executing. 542The 543.Fn callout_active 544macro checks whether a callout is marked as 545.Em active , 546and the 547.Fn callout_deactivate 548macro clears the callout's 549.Em active 550flag. 551The callout subsystem marks a callout as 552.Em active 553when a timeout is set and it clears the 554.Em active 555flag in 556.Fn callout_stop 557and 558.Fn callout_drain , 559but it 560.Em does not 561clear it when a callout expires normally via the execution of the 562callout function. 563.Pp 564The 565.Fn callout_when 566function may be used to pre-calculate the absolute time at which the 567timeout should be run and the precision of the scheduled run time 568according to the required time 569.Fa sbt , 570precision 571.Fa precision , 572and additional adjustments requested by the 573.Fa flags 574argument. 575Flags accepted by the 576.Fn callout_when 577function are the same as flags for the 578.Fn callout_reset 579function. 580The resulting time is assigned to the variable pointed to by the 581.Fa sbt_res 582argument, and the resulting precision is assigned to 583.Fa *precision_res . 584When passing the results to 585.Fa callout_reset , 586add the 587.Va C_PRECALC 588flag to 589.Fa flags , 590to avoid incorrect re-adjustment. 591The function is intended for situations where precise time of the callout 592run should be known in advance, since 593trying to read this time from the callout structure itself after a 594.Fn callout_reset 595call is racy. 596.Ss "Avoiding Race Conditions" 597The callout subsystem invokes callout functions from its own thread 598context. 599Without some kind of synchronization, 600it is possible that a callout 601function will be invoked concurrently with an attempt to stop or reset 602the callout by another thread. 603In particular, since callout functions typically acquire a lock as 604their first action, the callout function may have already been invoked, 605but is blocked waiting for that lock at the time that another thread 606tries to reset or stop the callout. 607.Pp 608There are three main techniques for addressing these 609synchronization concerns. 610The first approach is preferred as it is the simplest: 611.Bl -enum -offset indent 612.It 613Callouts can be associated with a specific lock when they are initialized 614by 615.Fn callout_init_mtx , 616.Fn callout_init_rm , 617or 618.Fn callout_init_rw . 619When a callout is associated with a lock, 620the callout subsystem acquires the lock before the callout function is 621invoked. 622This allows the callout subsystem to transparently handle races between 623callout cancellation, 624scheduling, 625and execution. 626Note that the associated lock must be acquired before calling 627.Fn callout_stop 628or one of the 629.Fn callout_reset 630or 631.Fn callout_schedule 632functions to provide this safety. 633.Pp 634A callout initialized via 635.Fn callout_init 636with 637.Fa mpsafe 638set to zero is implicitly associated with the 639.Va Giant 640mutex. 641If 642.Va Giant 643is held when cancelling or rescheduling the callout, 644then its use will prevent races with the callout function. 645.It 646The return value from 647.Fn callout_stop 648.Po 649or the 650.Fn callout_reset 651and 652.Fn callout_schedule 653function families 654.Pc 655indicates whether or not the callout was removed. 656If it is known that the callout was set and the callout function has 657not yet executed, then a return value of 658.Dv FALSE 659indicates that the callout function is about to be called. 660For example: 661.Bd -literal -offset indent 662if (sc->sc_flags & SCFLG_CALLOUT_RUNNING) { 663 if (callout_stop(&sc->sc_callout)) { 664 sc->sc_flags &= ~SCFLG_CALLOUT_RUNNING; 665 /* successfully stopped */ 666 } else { 667 /* 668 * callout has expired and callout 669 * function is about to be executed 670 */ 671 } 672} 673.Ed 674.It 675The 676.Fn callout_pending , 677.Fn callout_active 678and 679.Fn callout_deactivate 680macros can be used together to work around the race conditions. 681When a callout's timeout is set, the callout subsystem marks the 682callout as both 683.Em active 684and 685.Em pending . 686When the timeout time arrives, the callout subsystem begins processing 687the callout by first clearing the 688.Em pending 689flag. 690It then invokes the callout function without changing the 691.Em active 692flag, and does not clear the 693.Em active 694flag even after the callout function returns. 695The mechanism described here requires the callout function itself to 696clear the 697.Em active 698flag using the 699.Fn callout_deactivate 700macro. 701The 702.Fn callout_stop 703and 704.Fn callout_drain 705functions always clear both the 706.Em active 707and 708.Em pending 709flags before returning. 710.Pp 711The callout function should first check the 712.Em pending 713flag and return without action if 714.Fn callout_pending 715returns 716.Dv TRUE . 717This indicates that the callout was rescheduled using 718.Fn callout_reset 719just before the callout function was invoked. 720If 721.Fn callout_active 722returns 723.Dv FALSE 724then the callout function should also return without action. 725This indicates that the callout has been stopped. 726Finally, the callout function should call 727.Fn callout_deactivate 728to clear the 729.Em active 730flag. 731For example: 732.Bd -literal -offset indent 733mtx_lock(&sc->sc_mtx); 734if (callout_pending(&sc->sc_callout)) { 735 /* callout was reset */ 736 mtx_unlock(&sc->sc_mtx); 737 return; 738} 739if (!callout_active(&sc->sc_callout)) { 740 /* callout was stopped */ 741 mtx_unlock(&sc->sc_mtx); 742 return; 743} 744callout_deactivate(&sc->sc_callout); 745/* rest of callout function */ 746.Ed 747.Pp 748Together with appropriate synchronization, such as the mutex used above, 749this approach permits the 750.Fn callout_stop 751and 752.Fn callout_reset 753functions to be used at any time without races. 754For example: 755.Bd -literal -offset indent 756mtx_lock(&sc->sc_mtx); 757callout_stop(&sc->sc_callout); 758/* The callout is effectively stopped now. */ 759.Ed 760.Pp 761If the callout is still pending then these functions operate normally, 762but if processing of the callout has already begun then the tests in 763the callout function cause it to return without further action. 764Synchronization between the callout function and other code ensures that 765stopping or resetting the callout will never be attempted while the 766callout function is past the 767.Fn callout_deactivate 768call. 769.Pp 770The above technique additionally ensures that the 771.Em active 772flag always reflects whether the callout is effectively enabled or 773disabled. 774If 775.Fn callout_active 776returns false, then the callout is effectively disabled, since even if 777the callout subsystem is actually just about to invoke the callout 778function, the callout function will return without action. 779.El 780.Pp 781There is one final race condition that must be considered when a 782callout is being stopped for the last time. 783In this case it may not be safe to let the callout function itself 784detect that the callout was stopped, since it may need to access 785data objects that have already been destroyed or recycled. 786To ensure that the callout is completely finished, a call to 787.Fn callout_drain 788should be used. 789In particular, 790a callout should always be drained prior to destroying its associated lock 791or releasing the storage for the callout structure. 792.Sh RETURN VALUES 793The 794.Fn callout_active 795macro returns the state of a callout's 796.Em active 797flag. 798.Pp 799The 800.Fn callout_pending 801macro returns the state of a callout's 802.Em pending 803flag. 804.Pp 805The 806.Fn callout_reset 807and 808.Fn callout_schedule 809function families return a value of one if the callout was pending before the new 810function invocation was scheduled. 811.Pp 812The 813.Fn callout_stop 814and 815.Fn callout_drain 816functions return a value of one if the callout was still pending when it was 817called, a zero if the callout could not be stopped and a negative one is it 818was either not running or has already completed. 819.Sh HISTORY 820.Fx 821initially used the long standing 822.Bx 823linked list 824callout mechanism which offered O(n) insertion and removal running time 825but did not generate or require handles for untimeout operations. 826.Pp 827.Fx 3.0 828introduced a new set of timeout and untimeout routines from 829.Nx 830based on the work of 831.An Adam M. Costello 832and 833.An George Varghese , 834published in a technical report entitled 835.%T "Redesigning the BSD Callout and Timer Facilities" 836and modified for inclusion in 837.Fx 838by 839.An Justin T. Gibbs . 840The original work on the data structures used in that implementation 841was published by 842.An G. Varghese 843and 844.An A. Lauck 845in the paper 846.%T "Hashed and Hierarchical Timing Wheels: Data Structures for the Efficient Implementation of a Timer Facility" 847in the 848.%B "Proceedings of the 11th ACM Annual Symposium on Operating Systems Principles" . 849.Pp 850.Fx 3.3 851introduced the first implementations of 852.Fn callout_init , 853.Fn callout_reset , 854and 855.Fn callout_stop 856which permitted callers to allocate dedicated storage for callouts. 857This ensured that a callout would always fire unlike 858.Fn timeout 859which would silently fail if it was unable to allocate a callout. 860.Pp 861.Fx 5.0 862permitted callout handlers to be tagged as MPSAFE via 863.Fn callout_init . 864.Pp 865.Fx 5.3 866introduced 867.Fn callout_drain . 868.Pp 869.Fx 6.0 870introduced 871.Fn callout_init_mtx . 872.Pp 873.Fx 8.0 874introduced per-CPU callout wheels, 875.Fn callout_init_rw , 876and 877.Fn callout_schedule . 878.Pp 879.Fx 9.0 880changed the underlying timer interrupts used to drive callouts to prefer 881one-shot event timers instead of a periodic timer interrupt. 882.Pp 883.Fx 10.0 884switched the callout wheel to support tickless operation. 885These changes introduced 886.Vt sbintime_t 887and the 888.Fn callout_reset_sbt* 889family of functions. 890.Fx 10.0 also added 891.Dv C_DIRECT_EXEC 892and 893.Fn callout_init_rm . 894.Pp 895.Fx 10.2 896introduced the 897.Fn callout_schedule_sbt* 898family of functions. 899.Pp 900.Fx 11.0 901introduced 902.Fn callout_async_drain . 903.Fx 11.1 904introduced 905.Fn callout_when . 906.Fx 13.0 907removed 908.Vt timeout_t , 909.Fn timeout , 910and 911.Fn untimeout . 912