Commit b3e68612 authored by Todd Kjos's avatar Todd Kjos Committed by Greg Kroah-Hartman

binder: use inner lock to protect thread accounting

Use the inner lock to protect thread accounting fields in
proc structure: max_threads, requested_threads,
requested_threads_started and ready_threads.
Signed-off-by: default avatarTodd Kjos <tkjos@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0b89d69a
...@@ -498,11 +498,15 @@ enum binder_deferred_state { ...@@ -498,11 +498,15 @@ enum binder_deferred_state {
* @delivered_death: list of delivered death notification * @delivered_death: list of delivered death notification
* (protected by @inner_lock) * (protected by @inner_lock)
* @max_threads: cap on number of binder threads * @max_threads: cap on number of binder threads
* (protected by @inner_lock)
* @requested_threads: number of binder threads requested but not * @requested_threads: number of binder threads requested but not
* yet started. In current implementation, can * yet started. In current implementation, can
* only be 0 or 1. * only be 0 or 1.
* (protected by @inner_lock)
* @requested_threads_started: number binder threads started * @requested_threads_started: number binder threads started
* (protected by @inner_lock)
* @ready_threads: number of threads waiting for proc work * @ready_threads: number of threads waiting for proc work
* (protected by @inner_lock)
* @tmp_ref: temporary reference to indicate proc is in use * @tmp_ref: temporary reference to indicate proc is in use
* (protected by @inner_lock) * (protected by @inner_lock)
* @default_priority: default scheduler priority * @default_priority: default scheduler priority
...@@ -3234,6 +3238,7 @@ static int binder_thread_write(struct binder_proc *proc, ...@@ -3234,6 +3238,7 @@ static int binder_thread_write(struct binder_proc *proc,
binder_debug(BINDER_DEBUG_THREADS, binder_debug(BINDER_DEBUG_THREADS,
"%d:%d BC_REGISTER_LOOPER\n", "%d:%d BC_REGISTER_LOOPER\n",
proc->pid, thread->pid); proc->pid, thread->pid);
binder_inner_proc_lock(proc);
if (thread->looper & BINDER_LOOPER_STATE_ENTERED) { if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
thread->looper |= BINDER_LOOPER_STATE_INVALID; thread->looper |= BINDER_LOOPER_STATE_INVALID;
binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n", binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n",
...@@ -3247,6 +3252,7 @@ static int binder_thread_write(struct binder_proc *proc, ...@@ -3247,6 +3252,7 @@ static int binder_thread_write(struct binder_proc *proc,
proc->requested_threads_started++; proc->requested_threads_started++;
} }
thread->looper |= BINDER_LOOPER_STATE_REGISTERED; thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
binder_inner_proc_unlock(proc);
break; break;
case BC_ENTER_LOOPER: case BC_ENTER_LOOPER:
binder_debug(BINDER_DEBUG_THREADS, binder_debug(BINDER_DEBUG_THREADS,
...@@ -3523,11 +3529,11 @@ static int binder_thread_read(struct binder_proc *proc, ...@@ -3523,11 +3529,11 @@ static int binder_thread_read(struct binder_proc *proc,
binder_inner_proc_lock(proc); binder_inner_proc_lock(proc);
wait_for_proc_work = thread->transaction_stack == NULL && wait_for_proc_work = thread->transaction_stack == NULL &&
binder_worklist_empty_ilocked(&thread->todo); binder_worklist_empty_ilocked(&thread->todo);
if (wait_for_proc_work)
proc->ready_threads++;
binder_inner_proc_unlock(proc); binder_inner_proc_unlock(proc);
thread->looper |= BINDER_LOOPER_STATE_WAITING; thread->looper |= BINDER_LOOPER_STATE_WAITING;
if (wait_for_proc_work)
proc->ready_threads++;
binder_unlock(__func__); binder_unlock(__func__);
...@@ -3558,8 +3564,10 @@ static int binder_thread_read(struct binder_proc *proc, ...@@ -3558,8 +3564,10 @@ static int binder_thread_read(struct binder_proc *proc,
binder_lock(__func__); binder_lock(__func__);
binder_inner_proc_lock(proc);
if (wait_for_proc_work) if (wait_for_proc_work)
proc->ready_threads--; proc->ready_threads--;
binder_inner_proc_unlock(proc);
thread->looper &= ~BINDER_LOOPER_STATE_WAITING; thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
if (ret) if (ret)
...@@ -3849,19 +3857,22 @@ static int binder_thread_read(struct binder_proc *proc, ...@@ -3849,19 +3857,22 @@ static int binder_thread_read(struct binder_proc *proc,
done: done:
*consumed = ptr - buffer; *consumed = ptr - buffer;
binder_inner_proc_lock(proc);
if (proc->requested_threads + proc->ready_threads == 0 && if (proc->requested_threads + proc->ready_threads == 0 &&
proc->requested_threads_started < proc->max_threads && proc->requested_threads_started < proc->max_threads &&
(thread->looper & (BINDER_LOOPER_STATE_REGISTERED | (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */ BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
/*spawn a new thread if we leave this out */) { /*spawn a new thread if we leave this out */) {
proc->requested_threads++; proc->requested_threads++;
binder_inner_proc_unlock(proc);
binder_debug(BINDER_DEBUG_THREADS, binder_debug(BINDER_DEBUG_THREADS,
"%d:%d BR_SPAWN_LOOPER\n", "%d:%d BR_SPAWN_LOOPER\n",
proc->pid, thread->pid); proc->pid, thread->pid);
if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer)) if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
return -EFAULT; return -EFAULT;
binder_stat_br(proc, thread, BR_SPAWN_LOOPER); binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
} } else
binder_inner_proc_unlock(proc);
return 0; return 0;
} }
...@@ -4241,12 +4252,19 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -4241,12 +4252,19 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (ret) if (ret)
goto err; goto err;
break; break;
case BINDER_SET_MAX_THREADS: case BINDER_SET_MAX_THREADS: {
if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) { int max_threads;
if (copy_from_user(&max_threads, ubuf,
sizeof(max_threads))) {
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
binder_inner_proc_lock(proc);
proc->max_threads = max_threads;
binder_inner_proc_unlock(proc);
break; break;
}
case BINDER_SET_CONTEXT_MGR: case BINDER_SET_CONTEXT_MGR:
ret = binder_ioctl_set_ctx_mgr(filp); ret = binder_ioctl_set_ctx_mgr(filp);
if (ret) if (ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment