pthread_cond_timedwait and alarm API - delay too long

297 views
Skip to first unread message

Josenivaldo Benito Junior

unread,
Oct 27, 2010, 6:12:58 PM10/27/10
to android-...@googlegroups.com
Hello all,

I am writing a small daemon using pthread API provided by bionic. The code have two thread, one main thread which communicate with framework (java) through a socket, process commands putting than in a execution queue. The second thread consumes the execution queue. All read/write to the queue are mutex protected. I am also using the phtread_cond_timedwait to block the execution until a condition be matched or a certain time elapses.

Everything was running very well in my tests. However I start to face issues when USB cable is disconnected from the device. Mainly a long delays are verified in the execution of second thread. Debugging it I discovered the timeout (initially set to 20 seconds) was taking more than minutes to be signal the thread. Actually, by logcat timestamp, the delay real time is different each time phtread_cond_timedwait. So a run the obvious verifications:

-> small delays (1 second);
-> check timespec calculations, no errors were found;
-> change implementation;
-> any flaw in my thread design?

None seemed to change the actual behavior.

Therefore I decided to eliminate any non necessary information by writing a small stub program just for test delays. I tested sleep(x) api, alarm() (with proper signal handling), pthread_cond_timedwait and pthread_cond_timedwait_monotonic. All performed very similar in three different hardwares (two based on Cortex A8 and one based on Qualcomm MSM ARM11 platform). I faced lateness of more than five minutes for a asked delay of 20 seconds or less.

In my investigation, I went deeply in the kernel and also java framework to understand what is happening. I found:

-> clock_realtime read before and after the delay APIs present the real elapsed number of seconds
-> clock_monotonic read before and after the delay APIs present the "asked" delay time but logs show a bigger real elapsed time (i.e. alarm(20), clock_monotonic shows 20 seconds elapsed while logs shows, for instance, 5 minutes elapsed)
-> SystemClock.sleep (java API) is implemented by Dalvik as a Thread.sleep which may be using pthread_cond_timedwait so will present same behavior (tested and really happens)
-> the latiness is not linear. A timer of 1 second my be late in 1 minute or more, same happens for a timer of 20 seconds (may take a minute or even more).
-> AlarmManager (Java class) handle alarms which does not seem to present the problem described, however, it deals with an Android implementation of RTC driver (/dev/alarm) which I don't know yet if suitable for use in the linux userspace code.
-> I found in this group historic messages a TXT document from David explaining about bionic and other libc differences. My understand is that bionic support some of realtime services like settimer (i.e. used by alarm implementation).

My questions are:

Are the behavior presented by delay APIs (pthread_cond_timedwait, alarm and sleep) expected? Why?
How is the best way to implemented a time cyclic execution in the Android native code?

Thanks in advance for any help.

Best Regards,
Benito.
--
Josenivaldo Benito Jr.

PU2LBD
Contact me: http://www.google.com/profiles/jrbenito


Christopher Tate

unread,
Oct 27, 2010, 8:25:41 PM10/27/10
to android-...@googlegroups.com
It sounds like you are not using any wakelocks. When USB is plugged
in with debugging enabled, the device is held in an unsuspended state.
Unplugging it allows the device to fully sleep. My hunch is that you
are running your tests without using any wakelocks to make sure that
the device does not go to sleep in the middle of your testing.

--
christopher tate
android framework engineer

> --
> You received this message because you are subscribed to the Google Groups
> "android-platform" group.
> To post to this group, send email to android-...@googlegroups.com.
> To unsubscribe from this group, send email to
> android-platfo...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/android-platform?hl=en.
>

Josenivaldo Benito Junior

unread,
Oct 27, 2010, 11:09:15 PM10/27/10
to android-...@googlegroups.com
Hi Christopher,

Yes, you are right! I am not using wakelocks. Let me try to clarify my thoughts and you correct me if I getting the wrong point.

My understand about wakelocks is they are mechanism to held system in a certain level of wakeup state (full wakelock, partial wakelock, etc). Is that right? If I held an wakelock, system will not go fully sleep never during the period I am holding that lock. So, let's imagine:

(Native C - daemon code)
1> Thread2 is created
2> Thread2 do some simple job (i.e. increment a variable and log verbose)
3> Thread2 does nothing for 20 seconds **
4> Thread2 goto step 2
5> After N iterations above Thread2 returns (join)

In this scenario, is it right to hold a wakelock for the period in which Thread2 is doing nothing (step 3)? (sleep or waiting for a signal)
My idea was that the most important part of the code is step 2, hence a wakelock seems very important there. However, hold the lock during thread sleep time sounds strange to me because it avoids system to go deep sleep while  all the Thread2 will do is sleep for sometime. Am I understanding it wrong?

Furthermore, an timer armed with CLOCK_REALTIME source will not signal in a near realtime if a wakelock is not acquired? Finally, I got lateness bigger than 1000 seconds (more than 16 minutes) for a asked pause time of 20 seconds. Is possible that a deep sleep last for so long with no execution time slice to the timer expires?

Thanks for the valuable information.

Best regards,


--
Josenivaldo Benito Jr.

PU2LBD
Contact me: http://www.google.com/profiles/jrbenito




Christopher Tate

unread,
Oct 28, 2010, 12:35:03 AM10/28/10
to android-...@googlegroups.com
On Wed, Oct 27, 2010 at 8:09 PM, Josenivaldo Benito Junior
<jrbe...@benito.qsl.br> wrote:
>
> (Native C - daemon code)
> 1> Thread2 is created
> 2> Thread2 do some simple job (i.e. increment a variable and log verbose)
> 3> Thread2 does nothing for 20 seconds **
> 4> Thread2 goto step 2
> 5> After N iterations above Thread2 returns (join)
>
> In this scenario, is it right to hold a wakelock for the period in which
> Thread2 is doing nothing (step 3)? (sleep or waiting for a signal)
> My idea was that the most important part of the code is step 2, hence a
> wakelock seems very important there. However, hold the lock during thread
> sleep time sounds strange to me because it avoids system to go deep sleep
> while  all the Thread2 will do is sleep for sometime. Am I understanding it
> wrong?

Your hunch is entirely correct: holding a wakelock just to keep the
phone live in an idle state for 20 seconds is a terrible, terrible
thing to do. Do not use a wakelock for that. It's a total waste of
battery.

Instead, you should schedule a wakeup alarm for 20 realtime seconds in
the future, then use that alarm as the trigger to continue your work.
See the Alarm Manager documentation.

> Furthermore, an timer armed with CLOCK_REALTIME source will not signal in a
> near realtime if a wakelock is not acquired?

The Alarm Manager supports realtime (wall-clock time) alarms that wake
the phone for alarm processing.

> Finally, I got lateness bigger
> than 1000 seconds (more than 16 minutes) for a asked pause time of 20
> seconds. Is possible that a deep sleep last for so long with no execution
> time slice to the timer expires?

Absolutely. Android will aggressively sleep the hardware as deeply as
possible except when it is explicitly forced awake by wakelocks or
wakeup alarms.

Josenivaldo Benito Junior

unread,
Oct 28, 2010, 10:18:41 AM10/28/10
to android-...@googlegroups.com
Hi Christopher,


On Thu, Oct 28, 2010 at 01:35, Christopher Tate <ct...@google.com> wrote:

See the Alarm Manager documentation.


I guess you mean the Alarm Manager documentation available at developer.android.com.

 
The Alarm Manager supports realtime (wall-clock time) alarms that wake
the phone for alarm processing.

AlarmManager service exists in the Java framework, I didn't notice anything similar in the Linux userspace so I opened AlarmManager and figured out how it schedules alarm in the kernel/RTC. I wrote a program for open the device (/dev/alarm) and schedules an alarm exact as made by AlarmManager does.

I got the error "device or resource busy" when trying to schedule a new alarm. I am wondering if the /dev/alarm can handle more than one "client" because AlarmManager (Java framework) had it open I guess, and I am trying to do same in the user space at the same time. Do you know if it can handle alarm being schedule from framework and user space? (this question may more applicable to android-kernel group, please let me know)

Meanwhile, I could not find any reference of using RTC device in the user space, only in the Java framework (through the AlarmManager service). Any document shall I read?

 

Absolutely.  Android will aggressively sleep the hardware as deeply as
possible except when it is explicitly forced awake by wakelocks or
wakeup alarms.


Should not Bionic timer APIs like alarm() and settimer() rely on the RTC provided by kernel in order to trigger time accurate responses?

Thanks and best regards,
Benito.
Reply all
Reply to author
Forward
0 new messages