OSDN Git Service

soc: qcom: hab: add rx queue empty check after getting the lock
authorYong Ding <yongding@codeaurora.org>
Wed, 17 Oct 2018 12:08:35 +0000 (20:08 +0800)
committerYong Ding <yongding@codeaurora.org>
Tue, 23 Oct 2018 01:08:34 +0000 (09:08 +0800)
Need to do empty check again when we have the lock of the rx queue of
a given virtual channel. Without this check, it is possible that the
list head of the queue will be wrongly taken as a valid message node
if the valid message has already been fetched by some other thread.

Change-Id: I65f73acd86fe2fb709e2af2ffeaa42581b4168ca
Signed-off-by: Yong Ding <yongding@codeaurora.org>
drivers/soc/qcom/hab/hab_msg.c

index 61e6589..71010be 100644 (file)
@@ -64,9 +64,14 @@ hab_msg_dequeue(struct virtual_channel *vchan, struct hab_message **msg,
                }
        }
 
-       /* return all the received messages before the remote close */
-       if ((!ret || (ret == -ERESTARTSYS)) && !hab_rx_queue_empty(vchan)) {
-               spin_lock_bh(&vchan->rx_lock);
+       /*
+        * return all the received messages before the remote close,
+        * and need empty check again in case the list is empty now due to
+        * dequeue by other threads
+        */
+       spin_lock_bh(&vchan->rx_lock);
+
+       if ((!ret || (ret == -ERESTARTSYS)) && !list_empty(&vchan->rx_list)) {
                message = list_first_entry(&vchan->rx_list,
                                struct hab_message, node);
                if (message) {
@@ -84,11 +89,12 @@ hab_msg_dequeue(struct virtual_channel *vchan, struct hab_message **msg,
                                ret = -EOVERFLOW; /* come back again */
                        }
                }
-               spin_unlock_bh(&vchan->rx_lock);
        } else
                /* no message received, retain the original status */
                *rsize = 0;
 
+       spin_unlock_bh(&vchan->rx_lock);
+
        *msg = message;
        return ret;
 }