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.\" 3. All advertising materials mentioning features or use of this software 18.\" must display the following acknowledgement: 19.\" This product includes software developed by the NetBSD 20.\" Foundation, Inc. and its contributors. 21.\" 4. Neither the name of The NetBSD Foundation nor the names of its 22.\" contributors may be used to endorse or promote products derived 23.\" from this software without specific prior written permission. 24.\" 25.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 29.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35.\" POSSIBILITY OF SUCH DAMAGE. 36.\"
|
37.\" $FreeBSD: head/share/man/man9/timeout.9 141428 2005-02-07 02:47:33Z iedowse $
|
37.\" $FreeBSD: head/share/man/man9/timeout.9 147398 2005-06-15 13:31:23Z ru $ |
38.\" 39.Dd February 6, 2005 40.Dt TIMEOUT 9 41.Os 42.Sh NAME 43.Nm timeout , 44.Nm untimeout , 45.Nm callout_handle_init , 46.Nm callout_init , 47.Nm callout_init_mtx , 48.Nm callout_stop , 49.Nm callout_drain , 50.Nm callout_reset , 51.Nm callout_pending , 52.Nm callout_active , 53.Nm callout_deactivate 54.Nd execute a function after a specified length of time 55.Sh SYNOPSIS 56.In sys/types.h 57.In sys/systm.h 58.Pp 59.Bd -literal 60typedef void timeout_t (void *); 61.Ed 62.Ft struct callout_handle 63.Fn timeout "timeout_t *func" "void *arg" "int ticks" 64.Ft void 65.Fn callout_handle_init "struct callout_handle *handle" 66.Pp 67.Bd -literal 68struct callout_handle handle = CALLOUT_HANDLE_INITIALIZER(&handle) 69.Ed 70.Ft void 71.Fn untimeout "timeout_t *func" "void *arg" "struct callout_handle handle" 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 int 77.Fn callout_stop "struct callout *c" 78.Ft int 79.Fn callout_drain "struct callout *c" 80.Ft void 81.Fn callout_reset "struct callout *c" "int ticks" "timeout_t *func" "void *arg" 82.Ft int 83.Fn callout_pending "struct callout *c" 84.Ft int 85.Fn callout_active "struct callout *c" 86.Fn callout_deactivate "struct callout *c" 87.Sh DESCRIPTION 88The function 89.Fn timeout 90schedules a call to the function given by the argument 91.Fa func 92to take place after 93.Fa ticks Ns No /hz 94seconds. 95Non-positive values of 96.Fa ticks 97are silently converted to the value 98.Sq 1 . 99.Fa func 100should be a pointer to a function that takes a 101.Fa void * 102argument. 103Upon invocation, 104.Fa func 105will receive 106.Fa arg 107as its only argument. 108The return value from 109.Fn timeout 110is a 111.Ft struct callout_handle 112which can be used in conjunction with the 113.Fn untimeout 114function to request that a scheduled timeout be canceled. 115The 116.Fn timeout 117call is the old style and new code should use the 118.Fn callout_* 119functions. 120.Pp 121The function 122.Fn callout_handle_init 123can be used to initialize a handle to a state which will cause 124any calls to untimeout with that handle to return with no side 125effects. 126.Pp 127Assigning a callout handle the value of 128.Fn CALLOUT_HANDLE_INITIALIZER 129performs the same function as 130.Fn callout_handle_init 131and is provided for use on statically declared or global callout handles. 132.Pp 133The function 134.Fn untimeout 135cancels the timeout associated with 136.Fa handle 137using the 138.Fa func 139and 140.Fa arg 141arguments to validate the handle. 142If the handle does not correspond to a timeout with 143the function 144.Fa func 145taking the argument 146.Fa arg 147no action is taken. 148.Fa handle 149must be initialized by a previous call to 150.Fn timeout , 151.Fn callout_handle_init , 152or assigned the value of 153.Fn CALLOUT_HANDLE_INITIALIZER "&handle" 154before being passed to 155.Fn untimeout . 156The behavior of calling untimeout without a previously initialized handle 157is undefined. 158The 159.Fn untimeout 160call is the old style and new code should use the 161.Fn callout_* 162functions. 163.Pp 164As handles are recycled by the system, it is possible (although unlikely) 165that a handle from one invocation of 166.Fn timeout 167may match the handle of another invocation of 168.Fn timeout 169if both calls used the same function pointer and argument, and the first 170timeout is expired or canceled before the second call. 171The timeout facility offers O(1) running time for 172.Fn timeout 173and 174.Fn untimeout . 175Timeouts are executed from 176.Fn softclock 177with the 178.Va Giant 179lock held. 180Thus they are protected from re-entrancy. 181.Pp 182The functions 183.Fn callout_init , 184.Fn callout_init_mtx , 185.Fn callout_stop , 186.Fn callout_drain 187and 188.Fn callout_reset 189are low-level routines for clients who wish to allocate their own 190callout structures. 191.Pp 192The function 193.Fn callout_init 194initializes a callout so it can be passed to 195.Fn callout_stop , 196.Fn callout_drain 197or 198.Fn callout_reset 199without any side effects. 200If the 201.Fa mpsafe 202argument is zero, 203the callout structure is not considered to be 204.Dq multi-processor safe ; 205that is, 206the Giant lock will be acquired before calling the callout function, 207and released when the callout function returns. 208.Pp 209The 210.Fn callout_init_mtx 211function may be used as an alternative to 212.Fn callout_init . 213The parameter 214.Fa mtx 215specifies a mutex that is to be acquired by the callout subsystem 216before calling the callout function, and released when the callout 217function returns. 218The following 219.Fa flags 220may be specified:
|
221.Bl -tag -width CALLOUT_RETURNUNLOCKED
|
221.Bl -tag -width ".Dv CALLOUT_RETURNUNLOCKED" |
222.It Dv CALLOUT_RETURNUNLOCKED 223The callout function will release 224.Fa mtx 225itself, so the callout subsystem should not attempt to unlock it 226after the callout function returns. 227.El 228.Pp 229The function 230.Fn callout_stop 231cancels a callout if it is currently pending. 232If the callout is pending, then 233.Fn callout_stop 234will return a non-zero value. 235If the callout is not set, has already been serviced or is currently 236being serviced, then zero will be returned. 237If the callout has an associated mutex, then that mutex must be 238held when this function is called. 239.Pp 240The function 241.Fn callout_drain 242is identical to 243.Fn callout_stop 244except that it will wait for the callout to be completed if it is 245already in progress. 246This function MUST NOT be called while holding any 247locks on which the callout might block, or deadlock will result. 248Note that if the callout subsystem has already begun processing this 249callout, then the callout function may be invoked during the execution of 250.Fn callout_drain . 251However, the callout subsystem does guarantee that the callout will be 252fully stopped before 253.Fn callout_drain 254returns. 255.Pp 256The function 257.Fn callout_reset 258first performs the equivalent of 259.Fn callout_stop 260to disestablish the callout, and then establishes a new callout in the 261same manner as 262.Fn timeout . 263If the callout has an associated mutex, then that mutex must be 264held when this function is called. 265.Pp 266The macros 267.Fn callout_pending , 268.Fn callout_active 269and 270.Fn callout_deactivate 271provide access to the current state of the callout. 272Careful use of these macros can avoid many of the race conditions 273that are inherent in asynchronous timer facilities; see 274.Sx "Avoiding Race Conditions" 275below for further details. 276The 277.Fn callout_pending 278macro checks whether a callout is 279.Em pending ; 280a callout is considered 281.Em pending 282when a timeout has been set but the time has not yet arrived. 283Note that once the timeout time arrives and the callout subsystem 284starts to process this callout, 285.Fn callout_pending 286will return 287.Dv FALSE 288even though the callout function may not have finished (or even begun) 289executing. 290The 291.Fn callout_active 292macro checks whether a callout is marked as 293.Em active , 294and the 295.Fn callout_deactivate 296macro clears the callout's 297.Em active 298flag. 299The callout subsystem marks a callout as 300.Em active 301when a timeout is set and it clears the 302.Em active 303flag in 304.Fn callout_stop 305and 306.Fn callout_drain , 307but it 308.Em does not 309clear it when a callout expires normally via the execution of the 310callout function. 311.Ss "Avoiding Race Conditions" 312The callout subsystem invokes callout functions from its own timer 313context. 314Without some kind of synchronization it is possible that a callout 315function will be invoked concurrently with an attempt to stop or reset 316the callout by another thread. 317In particular, since callout functions typically acquire a mutex as 318their first action, the callout function may have already been invoked, 319but be blocked waiting for that mutex at the time that another thread 320tries to reset or stop the callout. 321.Pp 322The callout subsystem provides a number of mechanisms to address these 323synchronization concerns: 324.Bl -enum -offset indent 325.It 326If the callout has an associated mutex that was specified using the 327.Fn callout_init_mtx 328function (or implicitly specified as the 329.Va Giant 330mutex using 331.Fn callout_init 332with 333.Fa mpsafe 334set to 335.Dv FALSE ) , 336then this mutex is used to avoid the race conditions. 337The associated mutex must be acquired by the caller before calling 338.Fn callout_stop 339or 340.Fn callout_reset 341and it is guaranteed that the callout will be correctly stopped 342or reset as expected. 343Note that it is still necessary to use 344.Fn callout_drain 345before destroying the callout or its associated mutex. 346.It 347The return value from 348.Fn callout_stop 349indicates whether or not the callout was removed. 350If it is known that the callout was set and the callout function has 351not yet executed, then a return value of 352.Dv FALSE 353indicates that the callout function is about to be called. 354For example: 355.Bd -literal -offset indent 356if (sc->sc_flags & SCFLG_CALLOUT_RUNNING) { 357 if (callout_stop(&sc->sc_callout)) { 358 sc->sc_flags &= ~SCFLG_CALLOUT_RUNNING; 359 /* successfully stopped */ 360 } else { 361 /* 362 * callout has expired and callout 363 * function is about to be executed 364 */ 365 } 366} 367.Ed 368.Pp 369Note that there is no equivalent mechanism to determine whether or not 370.Fn callout_reset 371stopped the callout. 372.It 373The 374.Fn callout_pending , 375.Fn callout_active 376and 377.Fn callout_deactivate 378macros can be used together to work around the race conditions. 379When a callout's timeout is set, the callout subsystem marks the 380callout as both 381.Em active 382and 383.Em pending . 384When the timeout time arrives, the callout subsystem begins processing 385the callout by first clearing the 386.Em pending 387flag. 388It then invokes the callout function without changing the 389.Em active 390flag, and does not clear the 391.Em active 392flag even after the callout function returns. 393The mechanism described here requires the callout function itself to 394clear the 395.Em active 396flag using the 397.Fn callout_deactivate 398macro. 399The 400.Fn callout_stop 401and 402.Fn callout_drain 403functions always clear both the 404.Em active 405and 406.Em pending 407flags before returning. 408.Pp 409The callout function should first check the 410.Em pending 411flag and return without action if 412.Fn callout_pending 413returns 414.Dv TRUE . 415This indicates that the callout was rescheduled using 416.Fn callout_reset 417just before the callout function was invoked. 418If 419.Fn callout_active 420returns 421.Dv FALSE 422then the callout function should also return without action. 423This indicates that the callout has been stopped. 424Finally, the callout function should call 425.Fn callout_deactivate 426to clear the 427.Em active 428flag. 429For example: 430.Bd -literal -offset indent 431mtx_lock(&sc->sc_mtx); 432if (callout_pending(&sc->sc_callout)) { 433 /* callout was reset */ 434 mtx_unlock(&sc->sc_mtx); 435 return; 436} 437if (!callout_active(&sc->sc_callout)) { 438 /* callout was stopped */ 439 mtx_unlock(&sc->sc_mtx); 440 return; 441} 442callout_deactivate(&sc->sc_callout); 443/* rest of callout function */ 444.Ed 445.Pp 446Together with appropriate synchronization, such as the mutex used above, 447this approach permits the 448.Fn callout_stop 449and 450.Fn callout_reset 451functions to be used at any time without races. 452For example: 453.Bd -literal -offset indent 454mtx_lock(&sc->sc_mtx); 455callout_stop(&sc->sc_callout); 456/* The callout is effectively stopped now. */ 457.Ed 458.Pp 459If the callout is still pending then these functions operate normally, 460but if processing of the callout has already begun then the tests in 461the callout function cause it to return without further action. 462Synchronization between the callout function and other code ensures that 463stopping or resetting the callout will never be attempted while the 464callout function is past the 465.Fn callout_deactivate 466call. 467.Pp 468The above technique additionally ensures that the 469.Em active 470flag always reflects whether the callout is effectively enabled or 471disabled. 472If 473.Fn callout_active 474returns false, then the callout is effectively disabled, since even if 475the callout subsystem is actually just about to invoke the callout 476function, the callout function will return without action. 477.El 478.Pp 479There is one final race condition that must be considered when a 480callout is being stopped for the last time. 481In this case it may not be safe to let the callout function itself 482detect that the callout was stopped, since it may need to access 483data objects that have already been destroyed or recycled. 484To ensure that the callout is completely finished, a call to 485.Fn callout_drain 486should be used. 487.Sh RETURN VALUES 488The 489.Fn timeout 490function returns a 491.Ft struct callout_handle 492that can be passed to 493.Fn untimeout . 494The 495.Fn callout_stop 496and 497.Fn callout_drain 498functions return non-zero if the callout was still pending when it was 499called or zero otherwise. 500.Sh HISTORY 501The current timeout and untimeout routines are based on the work of 502.An Adam M. Costello 503and 504.An George Varghese , 505published in a technical report entitled 506.%T "Redesigning the BSD Callout and Timer Facilities" 507and modified slightly for inclusion in 508.Fx 509by 510.An Justin T. Gibbs . 511The original work on the data structures used in this implementation 512was published by 513.An G. Varghese 514and 515.An A. Lauck 516in the paper 517.%T "Hashed and Hierarchical Timing Wheels: Data Structures for the Efficient Implementation of a Timer Facility" 518in the 519.%B "Proceedings of the 11th ACM Annual Symposium on Operating Systems Principles" . 520The current implementation replaces the long standing 521.Bx 522linked list 523callout mechanism which offered O(n) insertion and removal running time 524but did not generate or require handles for untimeout operations.
|