diff options
| author | songjinshi <songjinshi@xiaomi.com> | 2016-11-22 18:29:16 +0800 |
|---|---|---|
| committer | Mister Oyster <oysterized@gmail.com> | 2017-06-28 11:47:47 +0200 |
| commit | 0d181ba8872d14e1942140055d1816e6b4b94e1b (patch) | |
| tree | 97b6f5c85be26ca9933ad179854be241f428d1b2 | |
| parent | 98c26880f3eb8115e6f870e328c7bf7e0fdeda25 (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.c | 2 |
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); |
