OSDN Git Service

reference-ril/atchannel.c: Fix time conversion
authorJinhui Li <jinhui.li@intel.com>
Thu, 24 Mar 2016 00:55:10 +0000 (08:55 +0800)
committerbohu <bohu@google.com>
Fri, 8 Apr 2016 00:31:11 +0000 (17:31 -0700)
setTimespecRelative() converts a relative time to an absolute time, by
adding the relative time to current system time. However, it fails to
handle the case where the nanosecond component (tv_nsec) of the
conversion result exceeds 10^9, which can cause a subsequent call to
pthread_cond_timedwait() to return EINVAL.

This bug is the root cause of the "no SIM card" error seen occasionally
on x86_64 Android emulator. In fact, all 64-bit targets use
setTimespecRelative() in conjunction with pthread_cond_timedwait()
during AT handshake, but an EINVAL return value from the latter will
lead to an infinite loop and hang the communication. With this fix,
x86_64 emulator can boot with functional 3G networking every time.

Signed-off-by: Jinhui Li <jinhui.li@intel.com>
[Revised code and commit message]
Signed-off-by: Yu Ning <yu.ning@intel.com>
(cherry picked from commit 11476211584f1a82c870b9486ace8f6f8bb9fc7c)

Change-Id: I5d7396ef7f0af5ef02ccab785046d635fb8f168c

reference-ril/atchannel.c

index f38545d..ac01cbc 100644 (file)
@@ -86,6 +86,7 @@ static int writeCtrlZ (const char *s);
 static int writeline (const char *s);
 
 #ifndef USE_NP
+#define NS_PER_S 1000000000
 static void setTimespecRelative(struct timespec *p_ts, long long msec)
 {
     struct timeval tv;
@@ -97,6 +98,11 @@ static void setTimespecRelative(struct timespec *p_ts, long long msec)
        a relative time again */
     p_ts->tv_sec = tv.tv_sec + (msec / 1000);
     p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L;
+    /* assuming tv.tv_usec < 10^6 */
+    if (p_ts->tv_nsec >= NS_PER_S) {
+        p_ts->tv_sec++;
+        p_ts->tv_nsec -= NS_PER_S;
+    }
 }
 #endif /*USE_NP*/