diff options
author | zzy <zhenye@broadcom.com> | 2012-09-20 21:19:10 -0700 |
---|---|---|
committer | Iliyan Malchev <malchev@google.com> | 2012-09-21 13:07:45 -0700 |
commit | 751c3ccf7c79a717c4f812c613f8911c1b7dee0b (patch) | |
tree | e2304a192f7dcfbae7f7c0c46eda330eb5bf2a71 | |
parent | c5af211f3758c7c94d9ca9b36dc106eb815cb67d (diff) | |
download | external_bluetooth_bluedroid-751c3ccf7c79a717c4f812c613f8911c1b7dee0b.zip external_bluetooth_bluedroid-751c3ccf7c79a717c4f812c613f8911c1b7dee0b.tar.gz external_bluetooth_bluedroid-751c3ccf7c79a717c4f812c613f8911c1b7dee0b.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.h | 23 | ||||
-rw-r--r-- | hci/src/bt_hci_bdroid.c | 16 | ||||
-rw-r--r-- | hci/src/utils.c | 46 |
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); } |