aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsongjinshi <songjinshi@xiaomi.com>2016-11-22 18:29:16 +0800
committerMister Oyster <oysterized@gmail.com>2017-06-28 11:47:47 +0200
commit0d181ba8872d14e1942140055d1816e6b4b94e1b (patch)
tree97b6f5c85be26ca9933ad179854be241f428d1b2
parent98c26880f3eb8115e6f870e328c7bf7e0fdeda25 (diff)
Incorrect the handling of async transactions.
Consider the following sequence of events: 1. Binder thread A1 receive an async transaction T1 and return to user space to execute 2. Another process's thread A2 request an async transaction T2, T2 and T1 belongs a same target_node, so it will be place to the async_todo of the target_node 3. A1 execute done the T1 and write a BC_FREE_BUFFER to mOut 4. A1 continue execute the processPendingDerefs and destruct a BBinder B1 5. B1's destruct function request a sync BC_TRANSACTION T3 and running into binder driver 6. The BC_FREE_BUFFER will be executed first, it move the T2 to A1's todo 7. Then the T3 will be executed, and it add a BR_TRANSACTION_COMPLETE to A1's todo 8. A1 will read the todo after write done, it will got T2 and return to user space to execute. 9. T3's BR_REPLY be place to A1's todo,now the A1's todo has two BR, first one is BR_TRANSACTION_COMPLETE,another one is BR_REPLY 10. T2 in execute process will request an async transaction T4 and running into binder driver 11. A1 will place the T4 to target list and add a BR_TRANSACTION_COMPLETE to the self's todo,now the A1's todo has three BR,first one is BR_TRANSACTION_COMPLETE,second one is BR_REPLY,the third one is BR_TRANSACTION_COMPLETE 12. A1 will read the todo after write done. it will got BR_TRANSACTION_COMPLETE and BR_REPLY,then return to the user space to execute,because the T4 is an async transaction so it will consume a BR_TRANSACTION_COMPLETE and exit the waitForResponse,then return to the T3's waitForResponse 13. T3 will consume a BR_REPLY and exit the waitForResponse,because it is a sync transaction, now the A1's todo still have a BR_TRANSACTION_COMPLETE 14. A1 continue execute the getAndExecuteCommand and talkWithDriver,it will got a BR_TRANSACTION_COMPLETE and return to user space to execute 15. A1 continue execute executeCommand, it will running into the default label of the switch and return an UNKNOWN_ERROR 16. A1 will check the results of the getAndExecuteCommand,if the UNKNOWN_ERROR occurs it will abort self. So we should move the async transaction to proc's todo when execute the BC_FREE_BUFFER to avoid the BAD CMD issue caused by sync transactions nested async transactions, move to the proc's todo will make the binder thread load balancing, and enhance the parallel capacity, the current binder thread will be execute it if the proc's todo have other transaction and the async transaction will be move to the tail of the proc's todo and waiting for execute of the other binder thread or current binder thread, so always only one binder thread to execute the async transactions, if another binder thread to got the async transaction to execute the current binder thread will idle, if no one another thread to got the async transction, the current thread will got it in the binder_thread_read after binder_thread_write execute done. https://code.google.com/p/android/issues/detail?id=228385 Signed-off-by: songjinshi <songjinshi@xiaomi.com>
-rw-r--r--drivers/android/binder.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 63af7b028..50b35874b 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2509,7 +2509,7 @@ static int binder_thread_write(struct binder_proc *proc,
if (list_empty(&buffer->target_node->async_todo))
buffer->target_node->has_async_transaction = 0;
else
- list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
+ list_move_tail(buffer->target_node->async_todo.next, &proc->todo);
}
trace_binder_transaction_buffer_release(buffer);
binder_transaction_buffer_release(proc, buffer, NULL);