diff options
author | Todd Kjos <tkjos@android.com> | 2017-06-29 15:01:49 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-07-17 08:47:29 -0400 |
commit | 08dabceefee0eddace493fc16da172c93402187f (patch) | |
tree | 2adeda656687f13b4238936377b6328a8444b4ee | |
parent | ccae6f676001d00efd1a4626773d1577e53188f7 (diff) |
binder: don't modify thread->looper from other threads
The looper member of struct binder_thread is a bitmask
of control bits. All of the existing bits are modified
by the affected thread except for BINDER_LOOPER_STATE_NEED_RETURN
which can be modified in binder_deferred_flush() by
another thread.
To avoid adding a spinlock around all read-mod-writes to
modify a bit, the BINDER_LOOPER_STATE_NEED_RETURN flag
is replaced by a separate field in struct binder_thread.
Signed-off-by: Todd Kjos <tkjos@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/android/binder.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 71faf548482d..3c1129d91825 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c | |||
@@ -334,14 +334,14 @@ enum { | |||
334 | BINDER_LOOPER_STATE_EXITED = 0x04, | 334 | BINDER_LOOPER_STATE_EXITED = 0x04, |
335 | BINDER_LOOPER_STATE_INVALID = 0x08, | 335 | BINDER_LOOPER_STATE_INVALID = 0x08, |
336 | BINDER_LOOPER_STATE_WAITING = 0x10, | 336 | BINDER_LOOPER_STATE_WAITING = 0x10, |
337 | BINDER_LOOPER_STATE_NEED_RETURN = 0x20 | ||
338 | }; | 337 | }; |
339 | 338 | ||
340 | struct binder_thread { | 339 | struct binder_thread { |
341 | struct binder_proc *proc; | 340 | struct binder_proc *proc; |
342 | struct rb_node rb_node; | 341 | struct rb_node rb_node; |
343 | int pid; | 342 | int pid; |
344 | int looper; | 343 | int looper; /* only modified by this thread */ |
344 | bool looper_need_return; /* can be written by other thread */ | ||
345 | struct binder_transaction *transaction_stack; | 345 | struct binder_transaction *transaction_stack; |
346 | struct list_head todo; | 346 | struct list_head todo; |
347 | uint32_t return_error; /* Write failed, return error code in read buf */ | 347 | uint32_t return_error; /* Write failed, return error code in read buf */ |
@@ -2276,14 +2276,13 @@ static void binder_stat_br(struct binder_proc *proc, | |||
2276 | static int binder_has_proc_work(struct binder_proc *proc, | 2276 | static int binder_has_proc_work(struct binder_proc *proc, |
2277 | struct binder_thread *thread) | 2277 | struct binder_thread *thread) |
2278 | { | 2278 | { |
2279 | return !list_empty(&proc->todo) || | 2279 | return !list_empty(&proc->todo) || thread->looper_need_return; |
2280 | (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); | ||
2281 | } | 2280 | } |
2282 | 2281 | ||
2283 | static int binder_has_thread_work(struct binder_thread *thread) | 2282 | static int binder_has_thread_work(struct binder_thread *thread) |
2284 | { | 2283 | { |
2285 | return !list_empty(&thread->todo) || thread->return_error != BR_OK || | 2284 | return !list_empty(&thread->todo) || thread->return_error != BR_OK || |
2286 | (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); | 2285 | thread->looper_need_return; |
2287 | } | 2286 | } |
2288 | 2287 | ||
2289 | static int binder_put_node_cmd(struct binder_proc *proc, | 2288 | static int binder_put_node_cmd(struct binder_proc *proc, |
@@ -2412,8 +2411,7 @@ retry: | |||
2412 | entry); | 2411 | entry); |
2413 | } else { | 2412 | } else { |
2414 | /* no data added */ | 2413 | /* no data added */ |
2415 | if (ptr - buffer == 4 && | 2414 | if (ptr - buffer == 4 && !thread->looper_need_return) |
2416 | !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) | ||
2417 | goto retry; | 2415 | goto retry; |
2418 | break; | 2416 | break; |
2419 | } | 2417 | } |
@@ -2727,7 +2725,7 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) | |||
2727 | INIT_LIST_HEAD(&thread->todo); | 2725 | INIT_LIST_HEAD(&thread->todo); |
2728 | rb_link_node(&thread->rb_node, parent, p); | 2726 | rb_link_node(&thread->rb_node, parent, p); |
2729 | rb_insert_color(&thread->rb_node, &proc->threads); | 2727 | rb_insert_color(&thread->rb_node, &proc->threads); |
2730 | thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN; | 2728 | thread->looper_need_return = true; |
2731 | thread->return_error = BR_OK; | 2729 | thread->return_error = BR_OK; |
2732 | thread->return_error2 = BR_OK; | 2730 | thread->return_error2 = BR_OK; |
2733 | } | 2731 | } |
@@ -2983,7 +2981,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
2983 | ret = 0; | 2981 | ret = 0; |
2984 | err: | 2982 | err: |
2985 | if (thread) | 2983 | if (thread) |
2986 | thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN; | 2984 | thread->looper_need_return = false; |
2987 | binder_unlock(__func__); | 2985 | binder_unlock(__func__); |
2988 | wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); | 2986 | wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); |
2989 | if (ret && ret != -ERESTARTSYS) | 2987 | if (ret && ret != -ERESTARTSYS) |
@@ -3138,7 +3136,7 @@ static void binder_deferred_flush(struct binder_proc *proc) | |||
3138 | for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { | 3136 | for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) { |
3139 | struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); | 3137 | struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node); |
3140 | 3138 | ||
3141 | thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN; | 3139 | thread->looper_need_return = true; |
3142 | if (thread->looper & BINDER_LOOPER_STATE_WAITING) { | 3140 | if (thread->looper & BINDER_LOOPER_STATE_WAITING) { |
3143 | wake_up_interruptible(&thread->wait); | 3141 | wake_up_interruptible(&thread->wait); |
3144 | wake_count++; | 3142 | wake_count++; |
@@ -3399,7 +3397,9 @@ static void print_binder_thread(struct seq_file *m, | |||
3399 | size_t start_pos = m->count; | 3397 | size_t start_pos = m->count; |
3400 | size_t header_pos; | 3398 | size_t header_pos; |
3401 | 3399 | ||
3402 | seq_printf(m, " thread %d: l %02x\n", thread->pid, thread->looper); | 3400 | seq_printf(m, " thread %d: l %02x need_return %d\n", |
3401 | thread->pid, thread->looper, | ||
3402 | thread->looper_need_return); | ||
3403 | header_pos = m->count; | 3403 | header_pos = m->count; |
3404 | t = thread->transaction_stack; | 3404 | t = thread->transaction_stack; |
3405 | while (t) { | 3405 | while (t) { |