summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzzy <zhenye@broadcom.com>2012-09-20 21:19:10 -0700
committerThe Android Automerger <android-build@android.com>2012-09-21 15:43:02 -0700
commitea634cea46f9dc34eed1fc4c7c95cf46dd70f375 (patch)
treee2304a192f7dcfbae7f7c0c46eda330eb5bf2a71
parent5d79d92af3d2ceb60194f36a608f1702c6d717d4 (diff)
downloadexternal_bluetooth_bluedroid-ea634cea46f9dc34eed1fc4c7c95cf46dd70f375.zip
external_bluetooth_bluedroid-ea634cea46f9dc34eed1fc4c7c95cf46dd70f375.tar.gz
external_bluetooth_bluedroid-ea634cea46f9dc34eed1fc4c7c95cf46dd70f375.tar.bz2
bluedroid: add mutex lock when enumerating the hci tx queue
Bug: 7167816 Bug: 7136940 This could be fix for most of the hci timeout issues. The root cause seemed like the while loop for sending hci message messed up when another thread try to enque/deque a hci message at same time. Change-Id: Ib7f6a68b49b700b0d575326cafae41a158483b27 Signed-off-by: Iliyan Malchev <malchev@google.com>
-rw-r--r--hci/include/utils.h23
-rw-r--r--hci/src/bt_hci_bdroid.c16
-rw-r--r--hci/src/utils.c46
3 files changed, 68 insertions, 17 deletions
diff --git a/hci/include/utils.h b/hci/include/utils.h
index be4406b..0f1517c 100644
--- a/hci/include/utils.h
+++ b/hci/include/utils.h
@@ -111,6 +111,17 @@ void *utils_dequeue (BUFFER_Q *p_q);
/*******************************************************************************
**
+** Function utils_dequeue_unlocked
+**
+** Description Dequeues a buffer from the head of the given queue without lock
+**
+** Returns NULL if queue is empty, else buffer
+**
+*******************************************************************************/
+void *utils_dequeue_unlocked (BUFFER_Q *p_q);
+
+/*******************************************************************************
+**
** Function utils_getnext
**
** Description Return a pointer to the next buffer linked to the given buffer
@@ -134,6 +145,18 @@ void *utils_remove_from_queue (BUFFER_Q *p_q, void *p_buf);
/*******************************************************************************
**
+** Function utils_remove_from_queue_unlocked
+**
+** Description Dequeue the given buffer from the middle of the given queue without lock
+**
+** Returns NULL if the given queue is empty, else the given buffer
+**
+*******************************************************************************/
+void *utils_remove_from_queue_unlocked (BUFFER_Q *p_q, void *p_buf);
+
+
+/*******************************************************************************
+**
** Function utils_delay
**
** Description sleep unconditionally for timeout milliseconds
diff --git a/hci/src/bt_hci_bdroid.c b/hci/src/bt_hci_bdroid.c
index e8a8411..27d190e 100644
--- a/hci/src/bt_hci_bdroid.c
+++ b/hci/src/bt_hci_bdroid.c
@@ -410,9 +410,12 @@ static void *bt_hc_worker_thread(void *arg)
* Fine to clear tx_cmd_pkts_pending.
*/
tx_cmd_pkts_pending = FALSE;
-
+ HC_BT_HDR * sending_msg_que[64];
+ int sending_msg_count = 0;
+ utils_lock();
p_next_msg = tx_q.p_first;
- while (p_next_msg)
+ while (p_next_msg && sending_msg_count <
+ (int)sizeof(sending_msg_que)/sizeof(sending_msg_que[0]))
{
if ((p_next_msg->event & MSG_EVT_MASK)==MSG_STACK_TO_HC_HCI_CMD)
{
@@ -434,10 +437,13 @@ static void *bt_hc_worker_thread(void *arg)
p_msg = p_next_msg;
p_next_msg = utils_getnext(p_msg);
- utils_remove_from_queue(&tx_q, p_msg);
- p_hci_if->send(p_msg);
+ utils_remove_from_queue_unlocked(&tx_q, p_msg);
+ sending_msg_que[sending_msg_count++] = p_msg;
}
-
+ utils_unlock();
+ int i;
+ for(i = 0; i < sending_msg_count; i++)
+ p_hci_if->send(sending_msg_que[i]);
if (tx_cmd_pkts_pending == TRUE)
BTHCDBG("Used up Tx Cmd credits");
diff --git a/hci/src/utils.c b/hci/src/utils.c
index 318c985..bfcf724 100644
--- a/hci/src/utils.c
+++ b/hci/src/utils.c
@@ -116,7 +116,6 @@ void utils_enqueue (BUFFER_Q *p_q, void *p_buf)
pthread_mutex_unlock(&utils_mutex);
}
-
/*******************************************************************************
**
** Function utils_dequeue
@@ -128,13 +127,28 @@ void utils_enqueue (BUFFER_Q *p_q, void *p_buf)
*******************************************************************************/
void *utils_dequeue (BUFFER_Q *p_q)
{
+ pthread_mutex_lock(&utils_mutex);
+ void* p_buf = utils_dequeue_unlocked(p_q);
+ pthread_mutex_unlock(&utils_mutex);
+ return p_buf;
+}
+
+/*******************************************************************************
+**
+** Function utils_dequeue_unlocked
+**
+** Description Dequeues a buffer from the head of the given queue without lock
+**
+** Returns NULL if queue is empty, else buffer
+**
+*******************************************************************************/
+void *utils_dequeue_unlocked (BUFFER_Q *p_q)
+{
HC_BUFFER_HDR_T *p_hdr;
- pthread_mutex_lock(&utils_mutex);
if (!p_q || !p_q->count)
{
- pthread_mutex_unlock(&utils_mutex);
return (NULL);
}
@@ -151,9 +165,6 @@ void *utils_dequeue (BUFFER_Q *p_q)
p_q->count--;
p_hdr->p_next = NULL;
-
- pthread_mutex_unlock(&utils_mutex);
-
return ((uint8_t *)p_hdr + BT_HC_BUFFER_HDR_SIZE);
}
@@ -191,15 +202,29 @@ void *utils_getnext (void *p_buf)
*******************************************************************************/
void *utils_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
{
+ pthread_mutex_lock(&utils_mutex);
+ p_buf = utils_remove_from_queue_unlocked(p_q, p_buf);
+ pthread_mutex_unlock(&utils_mutex);
+ return p_buf;
+}
+/*******************************************************************************
+**
+** Function utils_remove_from_queue_unlocked
+**
+** Description Dequeue the given buffer from the middle of the given queue
+**
+** Returns NULL if the given queue is empty, else the given buffer
+**
+*******************************************************************************/
+void *utils_remove_from_queue_unlocked (BUFFER_Q *p_q, void *p_buf)
+{
HC_BUFFER_HDR_T *p_prev;
HC_BUFFER_HDR_T *p_buf_hdr;
- pthread_mutex_lock(&utils_mutex);
if (p_buf == p_q->p_first)
{
- pthread_mutex_unlock(&utils_mutex);
- return (utils_dequeue (p_q));
+ return (utils_dequeue_unlocked (p_q));
}
p_buf_hdr = (HC_BUFFER_HDR_T *)((uint8_t *)p_buf - BT_HC_BUFFER_HDR_SIZE);
@@ -222,12 +247,9 @@ void *utils_remove_from_queue (BUFFER_Q *p_q, void *p_buf)
/* The buffer is now unlinked */
p_buf_hdr->p_next = NULL;
- pthread_mutex_unlock(&utils_mutex);
return (p_buf);
}
}
-
- pthread_mutex_unlock(&utils_mutex);
return (NULL);
}