| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Martijn Coenen <maco@google.com> |
| Date: Tue, 6 Jun 2017 17:04:42 -0700 |
| Subject: ONHOLD: ANDROID: binder: add support for RT prio inheritance. |
| |
| Adds support for SCHED_BATCH/SCHED_FIFO/SCHED_RR |
| priority inheritance. |
| |
| [CPNOTE: 27/05/21] Lee: Requested latest status on the bug report |
| [CPNOTE: 04/08/21] Lee: Depends on 'proxy execution' |
| |
| Bug: 34461621 |
| Bug: 37293077 |
| Bug: 120446518 |
| Change-Id: I71f356e476be2933713a0ecfa2cc31aa141e2dc6 |
| Signed-off-by: Martijn Coenen <maco@google.com> |
| Co-developed-by: Todd Kjos <tkjos@google.com> |
| Signed-off-by: Todd Kjos <tkjos@google.com> |
| [AmitP: Include <uapi/linux/sched/types.h> for struct sched_param] |
| Signed-off-by: Amit Pundir <amit.pundir@linaro.org> |
| [adelva: Folded the following changes into this patch: |
| 69308b3b07dd ("ANDROID: binder: add min sched_policy to node.") |
| 7a6edeb62d86 ("ANDROID: binder: improve priority inheritance.") |
| 22b061b17679 ("ANDROID: binder: don't check prio permissions on restore.") |
| 67cf97141d81 ("ANDROID: binder: Add tracing for binder priority inheritance.") |
| fb92c34f7ba3 ("ANDROID: binder: add RT inheritance flag to node.") |
| c847b48f8cda ("ANDROID: binder: init desired_prio.sched_policy before use it")] |
| Signed-off-by: Alistair Delva <adelva@google.com> |
| Signed-off-by: Matthias Maennich <maennich@google.com> |
| [ebiggers: Folded the following changes into this patch: |
| 547ee338cd3c ("ANDROID: binder: fix up use of MAX_USER_RT_PRIO")] |
| Signed-off-by: Eric Biggers <ebiggers@google.com> |
| --- |
| drivers/android/binder.c | 213 ++++++++++++++++++++++++---- |
| drivers/android/binder_internal.h | 30 +++- |
| drivers/android/binder_trace.h | 24 ++++ |
| include/uapi/linux/android/binder.h | 50 ++++++- |
| 4 files changed, 284 insertions(+), 33 deletions(-) |
| |
| diff --git a/drivers/android/binder.c b/drivers/android/binder.c |
| --- a/drivers/android/binder.c |
| +++ b/drivers/android/binder.c |
| @@ -67,6 +67,7 @@ |
| #include <linux/task_work.h> |
| #include <linux/sizes.h> |
| |
| +#include <uapi/linux/sched/types.h> |
| #include <uapi/linux/android/binder.h> |
| |
| #include <asm/cacheflush.h> |
| @@ -612,22 +613,145 @@ static void binder_wakeup_proc_ilocked(struct binder_proc *proc) |
| binder_wakeup_thread_ilocked(proc, thread, /* sync = */false); |
| } |
| |
| -static void binder_set_nice(long nice) |
| +static bool is_rt_policy(int policy) |
| { |
| - long min_nice; |
| + return policy == SCHED_FIFO || policy == SCHED_RR; |
| +} |
| + |
| +static bool is_fair_policy(int policy) |
| +{ |
| + return policy == SCHED_NORMAL || policy == SCHED_BATCH; |
| +} |
| + |
| +static bool binder_supported_policy(int policy) |
| +{ |
| + return is_fair_policy(policy) || is_rt_policy(policy); |
| +} |
| + |
| +static int to_userspace_prio(int policy, int kernel_priority) |
| +{ |
| + if (is_fair_policy(policy)) |
| + return PRIO_TO_NICE(kernel_priority); |
| + else |
| + return MAX_RT_PRIO - 1 - kernel_priority; |
| +} |
| + |
| +static int to_kernel_prio(int policy, int user_priority) |
| +{ |
| + if (is_fair_policy(policy)) |
| + return NICE_TO_PRIO(user_priority); |
| + else |
| + return MAX_RT_PRIO - 1 - user_priority; |
| +} |
| |
| - if (can_nice(current, nice)) { |
| - set_user_nice(current, nice); |
| +static void binder_do_set_priority(struct task_struct *task, |
| + struct binder_priority desired, |
| + bool verify) |
| +{ |
| + int priority; /* user-space prio value */ |
| + bool has_cap_nice; |
| + unsigned int policy = desired.sched_policy; |
| + |
| + if (task->policy == policy && task->normal_prio == desired.prio) |
| return; |
| + |
| + has_cap_nice = has_capability_noaudit(task, CAP_SYS_NICE); |
| + |
| + priority = to_userspace_prio(policy, desired.prio); |
| + |
| + if (verify && is_rt_policy(policy) && !has_cap_nice) { |
| + long max_rtprio = task_rlimit(task, RLIMIT_RTPRIO); |
| + |
| + if (max_rtprio == 0) { |
| + policy = SCHED_NORMAL; |
| + priority = MIN_NICE; |
| + } else if (priority > max_rtprio) { |
| + priority = max_rtprio; |
| + } |
| + } |
| + |
| + if (verify && is_fair_policy(policy) && !has_cap_nice) { |
| + long min_nice = rlimit_to_nice(task_rlimit(task, RLIMIT_NICE)); |
| + |
| + if (min_nice > MAX_NICE) { |
| + binder_user_error("%d RLIMIT_NICE not set\n", |
| + task->pid); |
| + return; |
| + } else if (priority < min_nice) { |
| + priority = min_nice; |
| + } |
| + } |
| + |
| + if (policy != desired.sched_policy || |
| + to_kernel_prio(policy, priority) != desired.prio) |
| + binder_debug(BINDER_DEBUG_PRIORITY_CAP, |
| + "%d: priority %d not allowed, using %d instead\n", |
| + task->pid, desired.prio, |
| + to_kernel_prio(policy, priority)); |
| + |
| + trace_binder_set_priority(task->tgid, task->pid, task->normal_prio, |
| + to_kernel_prio(policy, priority), |
| + desired.prio); |
| + |
| + /* Set the actual priority */ |
| + if (task->policy != policy || is_rt_policy(policy)) { |
| + struct sched_param params; |
| + |
| + params.sched_priority = is_rt_policy(policy) ? priority : 0; |
| + |
| + sched_setscheduler_nocheck(task, |
| + policy | SCHED_RESET_ON_FORK, |
| + ¶ms); |
| } |
| - min_nice = rlimit_to_nice(rlimit(RLIMIT_NICE)); |
| - binder_debug(BINDER_DEBUG_PRIORITY_CAP, |
| - "%d: nice value %ld not allowed use %ld instead\n", |
| - current->pid, nice, min_nice); |
| - set_user_nice(current, min_nice); |
| - if (min_nice <= MAX_NICE) |
| + if (is_fair_policy(policy)) |
| + set_user_nice(task, priority); |
| +} |
| + |
| +static void binder_set_priority(struct task_struct *task, |
| + struct binder_priority desired) |
| +{ |
| + binder_do_set_priority(task, desired, /* verify = */ true); |
| +} |
| + |
| +static void binder_restore_priority(struct task_struct *task, |
| + struct binder_priority desired) |
| +{ |
| + binder_do_set_priority(task, desired, /* verify = */ false); |
| +} |
| + |
| +static void binder_transaction_priority(struct task_struct *task, |
| + struct binder_transaction *t, |
| + struct binder_priority node_prio, |
| + bool inherit_rt) |
| +{ |
| + struct binder_priority desired_prio = t->priority; |
| + |
| + if (t->set_priority_called) |
| return; |
| - binder_user_error("%d RLIMIT_NICE not set\n", current->pid); |
| + |
| + t->set_priority_called = true; |
| + t->saved_priority.sched_policy = task->policy; |
| + t->saved_priority.prio = task->normal_prio; |
| + |
| + if (!inherit_rt && is_rt_policy(desired_prio.sched_policy)) { |
| + desired_prio.prio = NICE_TO_PRIO(0); |
| + desired_prio.sched_policy = SCHED_NORMAL; |
| + } |
| + |
| + if (node_prio.prio < t->priority.prio || |
| + (node_prio.prio == t->priority.prio && |
| + node_prio.sched_policy == SCHED_FIFO)) { |
| + /* |
| + * In case the minimum priority on the node is |
| + * higher (lower value), use that priority. If |
| + * the priority is the same, but the node uses |
| + * SCHED_FIFO, prefer SCHED_FIFO, since it can |
| + * run unbounded, unlike SCHED_RR. |
| + */ |
| + desired_prio = node_prio; |
| + } |
| + |
| + binder_set_priority(task, desired_prio); |
| } |
| |
| static struct binder_node *binder_get_node_ilocked(struct binder_proc *proc, |
| @@ -680,6 +804,7 @@ static struct binder_node *binder_init_node_ilocked( |
| binder_uintptr_t ptr = fp ? fp->binder : 0; |
| binder_uintptr_t cookie = fp ? fp->cookie : 0; |
| __u32 flags = fp ? fp->flags : 0; |
| + s8 priority; |
| |
| assert_spin_locked(&proc->inner_lock); |
| |
| @@ -712,8 +837,12 @@ static struct binder_node *binder_init_node_ilocked( |
| node->ptr = ptr; |
| node->cookie = cookie; |
| node->work.type = BINDER_WORK_NODE; |
| - node->min_priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK; |
| + priority = flags & FLAT_BINDER_FLAG_PRIORITY_MASK; |
| + node->sched_policy = (flags & FLAT_BINDER_FLAG_SCHED_POLICY_MASK) >> |
| + FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT; |
| + node->min_priority = to_kernel_prio(node->sched_policy, priority); |
| node->accept_fds = !!(flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); |
| + node->inherit_rt = !!(flags & FLAT_BINDER_FLAG_INHERIT_RT); |
| node->txn_security_ctx = !!(flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX); |
| spin_lock_init(&node->lock); |
| INIT_LIST_HEAD(&node->work.entry); |
| @@ -2354,11 +2483,15 @@ static int binder_proc_transaction(struct binder_transaction *t, |
| struct binder_thread *thread) |
| { |
| struct binder_node *node = t->buffer->target_node; |
| + struct binder_priority node_prio; |
| bool oneway = !!(t->flags & TF_ONE_WAY); |
| bool pending_async = false; |
| |
| BUG_ON(!node); |
| binder_node_lock(node); |
| + node_prio.prio = node->min_priority; |
| + node_prio.sched_policy = node->sched_policy; |
| + |
| if (oneway) { |
| BUG_ON(thread); |
| if (node->has_async_transaction) |
| @@ -2383,12 +2516,15 @@ static int binder_proc_transaction(struct binder_transaction *t, |
| if (!thread && !pending_async) |
| thread = binder_select_thread_ilocked(proc); |
| |
| - if (thread) |
| + if (thread) { |
| + binder_transaction_priority(thread->task, t, node_prio, |
| + node->inherit_rt); |
| binder_enqueue_thread_work_ilocked(thread, &t->work); |
| - else if (!pending_async) |
| + } else if (!pending_async) { |
| binder_enqueue_work_ilocked(&t->work, &proc->todo); |
| - else |
| + } else { |
| binder_enqueue_work_ilocked(&t->work, &node->async_todo); |
| + } |
| |
| if (!pending_async) |
| binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); |
| @@ -2510,7 +2646,6 @@ static void binder_transaction(struct binder_proc *proc, |
| } |
| thread->transaction_stack = in_reply_to->to_parent; |
| binder_inner_proc_unlock(proc); |
| - binder_set_nice(in_reply_to->saved_priority); |
| target_thread = binder_get_txn_from_and_acq_inner(in_reply_to); |
| if (target_thread == NULL) { |
| /* annotation for sparse */ |
| @@ -2715,7 +2850,15 @@ static void binder_transaction(struct binder_proc *proc, |
| t->to_thread = target_thread; |
| t->code = tr->code; |
| t->flags = tr->flags; |
| - t->priority = task_nice(current); |
| + if (!(t->flags & TF_ONE_WAY) && |
| + binder_supported_policy(current->policy)) { |
| + /* Inherit supported policies for synchronous transactions */ |
| + t->priority.sched_policy = current->policy; |
| + t->priority.prio = current->normal_prio; |
| + } else { |
| + /* Otherwise, fall back to the default priority */ |
| + t->priority = target_proc->default_priority; |
| + } |
| |
| if (target_node && target_node->txn_security_ctx) { |
| u32 secid; |
| @@ -3048,6 +3191,7 @@ static void binder_transaction(struct binder_proc *proc, |
| target_proc->outstanding_txns++; |
| binder_inner_proc_unlock(target_proc); |
| wake_up_interruptible_sync(&target_thread->wait); |
| + binder_restore_priority(current, in_reply_to->saved_priority); |
| binder_free_transaction(in_reply_to); |
| } else if (!(t->flags & TF_ONE_WAY)) { |
| BUG_ON(t->buffer->async_transaction != 0); |
| @@ -3162,6 +3306,7 @@ static void binder_transaction(struct binder_proc *proc, |
| |
| BUG_ON(thread->return_error.cmd != BR_OK); |
| if (in_reply_to) { |
| + binder_restore_priority(current, in_reply_to->saved_priority); |
| thread->return_error.cmd = BR_TRANSACTION_COMPLETE; |
| binder_enqueue_thread_work(thread, &thread->return_error.work); |
| binder_send_failed_reply(in_reply_to, return_error); |
| @@ -3839,7 +3984,7 @@ static int binder_thread_read(struct binder_proc *proc, |
| wait_event_interruptible(binder_user_error_wait, |
| binder_stop_on_user_error < 2); |
| } |
| - binder_set_nice(proc->default_priority); |
| + binder_restore_priority(current, proc->default_priority); |
| } |
| |
| if (non_block) { |
| @@ -4066,16 +4211,14 @@ static int binder_thread_read(struct binder_proc *proc, |
| BUG_ON(t->buffer == NULL); |
| if (t->buffer->target_node) { |
| struct binder_node *target_node = t->buffer->target_node; |
| + struct binder_priority node_prio; |
| |
| trd->target.ptr = target_node->ptr; |
| trd->cookie = target_node->cookie; |
| - t->saved_priority = task_nice(current); |
| - if (t->priority < target_node->min_priority && |
| - !(t->flags & TF_ONE_WAY)) |
| - binder_set_nice(t->priority); |
| - else if (!(t->flags & TF_ONE_WAY) || |
| - t->saved_priority > target_node->min_priority) |
| - binder_set_nice(target_node->min_priority); |
| + node_prio.sched_policy = target_node->sched_policy; |
| + node_prio.prio = target_node->min_priority; |
| + binder_transaction_priority(current, t, node_prio, |
| + target_node->inherit_rt); |
| cmd = BR_TRANSACTION; |
| } else { |
| trd->target.ptr = 0; |
| @@ -4293,6 +4436,8 @@ static struct binder_thread *binder_get_thread_ilocked( |
| binder_stats_created(BINDER_STAT_THREAD); |
| thread->proc = proc; |
| thread->pid = current->pid; |
| + get_task_struct(current); |
| + thread->task = current; |
| atomic_set(&thread->tmp_ref, 0); |
| init_waitqueue_head(&thread->wait); |
| INIT_LIST_HEAD(&thread->todo); |
| @@ -4354,6 +4499,7 @@ static void binder_free_thread(struct binder_thread *thread) |
| BUG_ON(!list_empty(&thread->todo)); |
| binder_stats_deleted(BINDER_STAT_THREAD); |
| binder_proc_dec_tmpref(thread->proc); |
| + put_task_struct(thread->task); |
| kfree(thread); |
| } |
| |
| @@ -5047,7 +5193,14 @@ static int binder_open(struct inode *nodp, struct file *filp) |
| proc->cred = get_cred(filp->f_cred); |
| INIT_LIST_HEAD(&proc->todo); |
| init_waitqueue_head(&proc->freeze_wait); |
| - proc->default_priority = task_nice(current); |
| + if (binder_supported_policy(current->policy)) { |
| + proc->default_priority.sched_policy = current->policy; |
| + proc->default_priority.prio = current->normal_prio; |
| + } else { |
| + proc->default_priority.sched_policy = SCHED_NORMAL; |
| + proc->default_priority.prio = NICE_TO_PRIO(0); |
| + } |
| + |
| /* binderfs stashes devices in i_private */ |
| if (is_binderfs_device(nodp)) { |
| binder_dev = nodp->i_private; |
| @@ -5372,13 +5525,14 @@ static void print_binder_transaction_ilocked(struct seq_file *m, |
| spin_lock(&t->lock); |
| to_proc = t->to_proc; |
| seq_printf(m, |
| - "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d", |
| + "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %d:%d r%d", |
| prefix, t->debug_id, t, |
| t->from ? t->from->proc->pid : 0, |
| t->from ? t->from->pid : 0, |
| to_proc ? to_proc->pid : 0, |
| t->to_thread ? t->to_thread->pid : 0, |
| - t->code, t->flags, t->priority, t->need_reply); |
| + t->code, t->flags, t->priority.sched_policy, |
| + t->priority.prio, t->need_reply); |
| spin_unlock(&t->lock); |
| |
| if (proc != to_proc) { |
| @@ -5496,8 +5650,9 @@ static void print_binder_node_nilocked(struct seq_file *m, |
| hlist_for_each_entry(ref, &node->refs, node_entry) |
| count++; |
| |
| - seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d tr %d", |
| + seq_printf(m, " node %d: u%016llx c%016llx pri %d:%d hs %d hw %d ls %d lw %d is %d iw %d tr %d", |
| node->debug_id, (u64)node->ptr, (u64)node->cookie, |
| + node->sched_policy, node->min_priority, |
| node->has_strong_ref, node->has_weak_ref, |
| node->local_strong_refs, node->local_weak_refs, |
| node->internal_strong_refs, count, node->tmp_refs); |
| diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h |
| --- a/drivers/android/binder_internal.h |
| +++ b/drivers/android/binder_internal.h |
| @@ -237,10 +237,13 @@ struct binder_error { |
| * and by @lock) |
| * @has_async_transaction: async transaction to node in progress |
| * (protected by @lock) |
| + * @sched_policy: minimum scheduling policy for node |
| + * (invariant after initialized) |
| * @accept_fds: file descriptor operations supported for node |
| * (invariant after initialized) |
| * @min_priority: minimum scheduling priority |
| * (invariant after initialized) |
| + * @inherit_rt: inherit RT scheduling policy from caller |
| * @txn_security_ctx: require sender's security context |
| * (invariant after initialized) |
| * @async_todo: list of async work items |
| @@ -278,6 +281,8 @@ struct binder_node { |
| /* |
| * invariant after initialization |
| */ |
| + u8 sched_policy:2; |
| + u8 inherit_rt:1; |
| u8 accept_fds:1; |
| u8 txn_security_ctx:1; |
| u8 min_priority; |
| @@ -346,6 +351,22 @@ struct binder_ref { |
| struct binder_ref_death *death; |
| }; |
| |
| +/** |
| + * struct binder_priority - scheduler policy and priority |
| + * @sched_policy scheduler policy |
| + * @prio [100..139] for SCHED_NORMAL, [0..99] for FIFO/RT |
| + * |
| + * The binder driver supports inheriting the following scheduler policies: |
| + * SCHED_NORMAL |
| + * SCHED_BATCH |
| + * SCHED_FIFO |
| + * SCHED_RR |
| + */ |
| +struct binder_priority { |
| + unsigned int sched_policy; |
| + int prio; |
| +}; |
| + |
| /** |
| * struct binder_proc - binder process bookkeeping |
| * @proc_node: element for binder_procs list |
| @@ -446,7 +467,7 @@ struct binder_proc { |
| int requested_threads; |
| int requested_threads_started; |
| int tmp_ref; |
| - long default_priority; |
| + struct binder_priority default_priority; |
| struct dentry *debugfs_entry; |
| struct binder_alloc alloc; |
| struct binder_context *context; |
| @@ -489,6 +510,7 @@ struct binder_proc { |
| * @is_dead: thread is dead and awaiting free |
| * when outstanding transactions are cleaned up |
| * (protected by @proc->inner_lock) |
| + * @task: struct task_struct for this thread |
| * |
| * Bookkeeping structure for binder threads. |
| */ |
| @@ -508,6 +530,7 @@ struct binder_thread { |
| struct binder_stats stats; |
| atomic_t tmp_ref; |
| bool is_dead; |
| + struct task_struct *task; |
| }; |
| |
| /** |
| @@ -541,8 +564,9 @@ struct binder_transaction { |
| struct binder_buffer *buffer; |
| unsigned int code; |
| unsigned int flags; |
| - long priority; |
| - long saved_priority; |
| + struct binder_priority priority; |
| + struct binder_priority saved_priority; |
| + bool set_priority_called; |
| kuid_t sender_euid; |
| struct list_head fd_fixups; |
| binder_uintptr_t security_ctx; |
| diff --git a/drivers/android/binder_trace.h b/drivers/android/binder_trace.h |
| --- a/drivers/android/binder_trace.h |
| +++ b/drivers/android/binder_trace.h |
| @@ -76,6 +76,30 @@ DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_ioctl_done); |
| DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_write_done); |
| DEFINE_BINDER_FUNCTION_RETURN_EVENT(binder_read_done); |
| |
| +TRACE_EVENT(binder_set_priority, |
| + TP_PROTO(int proc, int thread, unsigned int old_prio, |
| + unsigned int desired_prio, unsigned int new_prio), |
| + TP_ARGS(proc, thread, old_prio, new_prio, desired_prio), |
| + |
| + TP_STRUCT__entry( |
| + __field(int, proc) |
| + __field(int, thread) |
| + __field(unsigned int, old_prio) |
| + __field(unsigned int, new_prio) |
| + __field(unsigned int, desired_prio) |
| + ), |
| + TP_fast_assign( |
| + __entry->proc = proc; |
| + __entry->thread = thread; |
| + __entry->old_prio = old_prio; |
| + __entry->new_prio = new_prio; |
| + __entry->desired_prio = desired_prio; |
| + ), |
| + TP_printk("proc=%d thread=%d old=%d => new=%d desired=%d", |
| + __entry->proc, __entry->thread, __entry->old_prio, |
| + __entry->new_prio, __entry->desired_prio) |
| +); |
| + |
| TRACE_EVENT(binder_wait_for_work, |
| TP_PROTO(bool proc_work, bool transaction_stack, bool thread_todo), |
| TP_ARGS(proc_work, transaction_stack, thread_todo), |
| diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h |
| --- a/include/uapi/linux/android/binder.h |
| +++ b/include/uapi/linux/android/binder.h |
| @@ -38,10 +38,58 @@ enum { |
| BINDER_TYPE_PTR = B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE), |
| }; |
| |
| -enum { |
| +/** |
| + * enum flat_binder_object_shifts: shift values for flat_binder_object_flags |
| + * @FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT: shift for getting scheduler policy. |
| + * |
| + */ |
| +enum flat_binder_object_shifts { |
| + FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT = 9, |
| +}; |
| + |
| +/** |
| + * enum flat_binder_object_flags - flags for use in flat_binder_object.flags |
| + */ |
| +enum flat_binder_object_flags { |
| + /** |
| + * @FLAT_BINDER_FLAG_PRIORITY_MASK: bit-mask for min scheduler priority |
| + * |
| + * These bits can be used to set the minimum scheduler priority |
| + * at which transactions into this node should run. Valid values |
| + * in these bits depend on the scheduler policy encoded in |
| + * @FLAT_BINDER_FLAG_SCHED_POLICY_MASK. |
| + * |
| + * For SCHED_NORMAL/SCHED_BATCH, the valid range is between [-20..19] |
| + * For SCHED_FIFO/SCHED_RR, the value can run between [1..99] |
| + */ |
| FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff, |
| + /** |
| + * @FLAT_BINDER_FLAG_ACCEPTS_FDS: whether the node accepts fds. |
| + */ |
| FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, |
| |
| + /** |
| + * @FLAT_BINDER_FLAG_SCHED_POLICY_MASK: bit-mask for scheduling policy |
| + * |
| + * These two bits can be used to set the min scheduling policy at which |
| + * transactions on this node should run. These match the UAPI |
| + * scheduler policy values, eg: |
| + * 00b: SCHED_NORMAL |
| + * 01b: SCHED_FIFO |
| + * 10b: SCHED_RR |
| + * 11b: SCHED_BATCH |
| + */ |
| + FLAT_BINDER_FLAG_SCHED_POLICY_MASK = |
| + 3U << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT, |
| + |
| + /** |
| + * @FLAT_BINDER_FLAG_INHERIT_RT: whether the node inherits RT policy |
| + * |
| + * Only when set, calls into this node will inherit a real-time |
| + * scheduling policy from the caller (for synchronous transactions). |
| + */ |
| + FLAT_BINDER_FLAG_INHERIT_RT = 0x800, |
| + |
| /** |
| * @FLAT_BINDER_FLAG_TXN_SECURITY_CTX: request security contexts |
| * |