Skip to content
  • Patrick Pannuto's avatar
    timer: Added usleep_range timer · 5e7f5a17
    Patrick Pannuto authored
    usleep_range is a finer precision implementations of msleep
    and is designed to be a drop-in replacement for udelay where
    a precise sleep / busy-wait is unnecessary.
    
    Since an easy interface to hrtimers could lead to an undesired
    proliferation of interrupts, we provide only a "range" API,
    forcing the caller to think about an acceptable tolerance on
    both ends and hopefully avoiding introducing another interrupt.
    
    INTRO
    
    As discussed here ( http://lkml.org/lkml/2007/8/3/250
    
     ), msleep(1) is not
    precise enough for many drivers (yes, sleep precision is an unfair notion,
    but consistently sleeping for ~an order of magnitude greater than requested
    is worth fixing). This patch adds a usleep API so that udelay does not have
    to be used. Obviously not every udelay can be replaced (those in atomic
    contexts or being used for simple bitbanging come to mind), but there are
    many, many examples of
    
    mydriver_write(...)
    /* Wait for hardware to latch */
    udelay(100)
    
    in various drivers where a busy-wait loop is neither beneficial nor
    necessary, but msleep simply does not provide enough precision and people
    are using a busy-wait loop instead.
    
    CONCERNS FROM THE RFC
    
    Why is udelay a problem / necessary? Most callers of udelay are in device/
    driver initialization code, which is serial...
    
    	As I see it, there is only benefit to sleeping over a delay; the
    	notion of "refactoring" areas that use udelay was presented, but
    	I see usleep as the refactoring. Consider i2c, if the bus is busy,
    	you need to wait a bit (say 100us) before trying again, your
    	current options are:
    
    		* udelay(100)
    		* msleep(1) <-- As noted above, actually as high as ~20ms
    				on some platforms, so not really an option
    		* Manually set up an hrtimer to try again in 100us (which
    		  is what usleep does anyway...)
    
    	People choose the udelay route because it is EASY; we need to
    	provide a better easy route.
    
    	Device / driver / boot code is *currently* serial, but every few
    	months someone makes noise about parallelizing boot, and IMHO, a
    	little forward-thinking now is one less thing to worry about
    	if/when that ever happens
    
    udelay's could be preempted
    
    	Sure, but if udelay plans on looping 1000 times, and it gets
    	preempted on loop 200, whenever it's scheduled again, it is
    	going to do the next 800 loops.
    
    Is the interruptible case needed?
    
    	Probably not, but I see usleep as a very logical parallel to msleep,
    	so it made sense to include the "full" API. Processors are getting
    	faster (albeit not as quickly as they are becoming more parallel),
    	so if someone wanted to be interruptible for a few usecs, why not
    	let them? If this is a contentious point, I'm happy to remove it.
    
    OTHER THOUGHTS
    
    I believe there is also value in exposing the usleep_range option; it gives
    the scheduler a lot more flexibility and allows the programmer to express
    his intent much more clearly; it's something I would hope future driver
    writers will take advantage of.
    
    To get the results in the NUMBERS section below, I literally s/udelay/usleep
    the kernel tree; I had to go in and undo the changes to the USB drivers, but
    everything else booted successfully; I find that extremely telling in and
    of itself -- many people are using a delay API where a sleep will suit them
    just fine.
    
    SOME ATTEMPTS AT NUMBERS
    
    It turns out that calculating quantifiable benefit on this is challenging,
    so instead I will simply present the current state of things, and I hope
    this to be sufficient:
    
    How many udelay calls are there in 2.6.35-rc5?
    
    	udealy(ARG) >=	| COUNT
    	1000		| 319
    	500		| 414
    	100		| 1146
    	20		| 1832
    
    I am working on Android, so that is my focus for this. The following table
    is a modified usleep that simply printk's the amount of time requested to
    sleep; these tests were run on a kernel with udelay >= 20 --> usleep
    
    "boot" is power-on to lock screen
    "power collapse" is when the power button is pushed and the device suspends
    "resume" is when the power button is pushed and the lock screen is displayed
             (no touchscreen events or anything, just turning on the display)
    "use device" is from the unlock swipe to clicking around a bit; there is no
    	sd card in this phone, so fail loading music, video, camera
    
    	ACTION		| TOTAL NUMBER OF USLEEP CALLS	| NET TIME (us)
    	boot		| 22				| 1250
    	power-collapse	| 9				| 1200
    	resume		| 5				| 500
    	use device	| 59				| 7700
    
    The most interesting category to me is the "use device" field; 7700us of
    busy-wait time that could be put towards better responsiveness, or at the
    least less power usage.
    
    Signed-off-by: default avatarPatrick Pannuto <ppannuto@codeaurora.org>
    Cc: apw@canonical.com
    Cc: corbet@lwn.net
    Cc: arjan@linux.intel.com
    Cc: Randy Dunlap <rdunlap@xenotime.net>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    5e7f5a17