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: Todd Kjos <tkjos@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
0b89d69a96
commit
b3e6861283
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue