summaryrefslogtreecommitdiffstats
path: root/reference-ril/atchannel.c
diff options
context:
space:
mode:
authorWeilun Du <wdu@google.com>2017-02-07 10:47:19 -0800
committerWeilun Du <wdu@google.com>2017-02-07 11:46:50 -0800
commit9f471e2dd80b528a384813210ae64e3ea3527f35 (patch)
tree76097cb7b976af2578b5aa54b4525d87630b5733 /reference-ril/atchannel.c
parent5b1c10e498c0401318ac3f61f65034c14991b75d (diff)
downloadandroid_hardware_ril-9f471e2dd80b528a384813210ae64e3ea3527f35.tar.gz
android_hardware_ril-9f471e2dd80b528a384813210ae64e3ea3527f35.tar.bz2
android_hardware_ril-9f471e2dd80b528a384813210ae64e3ea3527f35.zip
Fix race condition in at_send_command_*
b/34883617 Change-Id: I946125e1c4db44e05afbc0e5d1fb22cc880f1d89 Signed-off-by: Weilun Du <wdu@google.com>
Diffstat (limited to 'reference-ril/atchannel.c')
-rw-r--r--reference-ril/atchannel.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/reference-ril/atchannel.c b/reference-ril/atchannel.c
index 5dc3e3c..0041836 100644
--- a/reference-ril/atchannel.c
+++ b/reference-ril/atchannel.c
@@ -61,12 +61,17 @@ void AT_DUMP(const char* prefix, const char* buff, int len)
#endif
/*
- * for current pending command
- * these are protected by s_commandmutex
+ * There is one reader thread |s_tid_reader| and potentially multiple writer
+ * threads. |s_commandmutex| and |s_commandcond| are used to maintain the
+ * condition that the writer thread will not read from |sp_response| until the
+ * reader thread has signaled itself is finished, etc. |s_writeMutex| is used to
+ * prevent multiple writer threads from calling at_send_command_full_nolock
+ * function at the same time.
*/
static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t s_writeMutex = PTHREAD_MUTEX_INITIALIZER;
static ATCommandType s_type;
static const char *s_responsePrefix = NULL;
@@ -736,12 +741,16 @@ static int at_send_command_full (const char *command, ATCommandType type,
long long timeoutMsec, ATResponse **pp_outResponse)
{
int err;
+ bool inEmulator;
if (0 != pthread_equal(s_tid_reader, pthread_self())) {
/* cannot be called from reader thread */
return AT_ERROR_INVALID_THREAD;
}
-
+ inEmulator = isInEmulator();
+ if (inEmulator) {
+ pthread_mutex_lock(&s_writeMutex);
+ }
pthread_mutex_lock(&s_commandmutex);
err = at_send_command_full_nolock(command, type,
@@ -749,6 +758,9 @@ static int at_send_command_full (const char *command, ATCommandType type,
timeoutMsec, pp_outResponse);
pthread_mutex_unlock(&s_commandmutex);
+ if (inEmulator) {
+ pthread_mutex_unlock(&s_writeMutex);
+ }
if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) {
s_onTimeout();
@@ -888,12 +900,16 @@ int at_handshake()
{
int i;
int err = 0;
+ bool inEmulator;
if (0 != pthread_equal(s_tid_reader, pthread_self())) {
/* cannot be called from reader thread */
return AT_ERROR_INVALID_THREAD;
}
-
+ inEmulator = isInEmulator();
+ if (inEmulator) {
+ pthread_mutex_lock(&s_writeMutex);
+ }
pthread_mutex_lock(&s_commandmutex);
for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) {
@@ -914,6 +930,9 @@ int at_handshake()
}
pthread_mutex_unlock(&s_commandmutex);
+ if (inEmulator) {
+ pthread_mutex_unlock(&s_writeMutex);
+ }
return err;
}