Thanks to Takashi's advice, I managed to find out the reason why I was seeing null events returned by poll(). This could explain why PulseAudio doesn't seem to sleep much. It turns out that we have two calls to wakeup() in pcm_lib.c, and a nice race condition it seems. See the log below.
A wake-up is generated during the period interrupt, and a second wake-up is generated during the write loop, after the application was awaken but just before the pointers are updated. This second wake-up shouldn't exist, since the write loop actually fills the ring buffer. By the time the second wake-up is actually handled, there's really no space left in the buffer and a null event is generated; it'll wake-up the application a second time for nothing. Maybe we should move the call to snd_pcm_update_hw_ptr() after the transfer took place?
Can anyone apply the attached patches (only adds printks) and confirm this issue on their platforms? That would be very useful. Happy holidays everyone - Pierre
alsa-lib/test/pcm --verbose -Dhw -c2 -r48000 -f440 --method write_and_poll
[ 371.369865] snd_intel8x0_interrupt [ 371.369876] snd_intel8x0_update [ 371.369884] snd_pcm_period_elapsed [ 371.369890] snd_pcm_update_hw_ptr_interrupt [ 371.369900] snd_pcm_update_hw_ptr_post [ 371.369909] wakeup in snd_pcm_update_hw_ptr_post sound/core/pcm_lib.c: 214, avail 8194, avail_min 8192 [ 371.369935] ALSA: poll event POLLOUT|POLLWRNORM, avail 8194 avail_min 8192 [ 371.375449] snd_pcm_lib_write1: in [ 371.375457] snd_pcm_lib_write1 loop [ 371.375462] snd_pcm_update_hw_ptr [ 371.375472] snd_pcm_update_hw_ptr_post [ 371.375481] wakeup in snd_pcm_update_hw_ptr_post sound/core/pcm_lib.c: 214, avail 8462, avail_min 8192
Between these two points, the appl_ptr is updated, and there's no space left in the buffer. The wake-up is generated too early.
[ 371.375514] snd_pcm_lib_write1: out [ 371.375524] ALSA: null poll event, avail 270 avail_min 8192 [ 371.540532] snd_intel8x0_interrupt [ 371.540542] snd_intel8x0_update [ 371.540551] snd_pcm_period_elapsed [ 371.540556] snd_pcm_update_hw_ptr_interrupt [ 371.540566] snd_pcm_update_hw_ptr_post [ 371.540575] wakeup in snd_pcm_update_hw_ptr_post sound/core/pcm_lib.c: 214, avail 8194, avail_min 8192 [ 371.540601] ALSA: poll event POLLOUT|POLLWRNORM, avail 8194 avail_min 8192 [ 371.543734] snd_pcm_lib_write1: in [ 371.543741] snd_pcm_lib_write1 loop [ 371.543746] snd_pcm_update_hw_ptr [ 371.543755] snd_pcm_update_hw_ptr_post [ 371.543764] wakeup in snd_pcm_update_hw_ptr_post sound/core/pcm_lib.c: 214, avail 8347, avail_min 8192 [ 371.543797] snd_pcm_lib_write1: out [ 371.543807] ALSA: null poll event, avail 155 avail_min 8192