global_page_state(NR_INACTIVE_FILE);
}
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+static struct task_struct *pick_next_from_adj_tree(struct task_struct *task);
+static struct task_struct *pick_first_task(void);
+static struct task_struct *pick_last_task(void);
+#endif
+
static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
{
struct task_struct *tsk;
selected_oom_score_adj = min_score_adj;
rcu_read_lock();
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+ for (tsk = pick_first_task();
+ tsk != pick_last_task() && tsk != NULL;
+ tsk = pick_next_from_adj_tree(tsk)) {
+#else
for_each_process(tsk) {
+#endif
struct task_struct *p;
short oom_score_adj;
oom_score_adj = p->signal->oom_score_adj;
if (oom_score_adj < min_score_adj) {
task_unlock(p);
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+ break;
+#else
continue;
+#endif
}
tasksize = get_mm_rss(p->mm);
task_unlock(p);
return rem;
}
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+DEFINE_SPINLOCK(lmk_lock);
+struct rb_root tasks_scoreadj = RB_ROOT;
+/*
+ * Makesure to invoke the function with holding sighand->siglock
+ */
+void add_2_adj_tree(struct task_struct *task)
+{
+ struct rb_node **link;
+ struct rb_node *parent = NULL;
+ struct signal_struct *sig_entry;
+ s64 key = task->signal->oom_score_adj;
+
+ /*
+ * Find the right place in the rbtree:
+ */
+ spin_lock(&lmk_lock);
+ link = &tasks_scoreadj.rb_node;
+ while (*link) {
+ parent = *link;
+ sig_entry = rb_entry(parent, struct signal_struct, adj_node);
+
+ if (key < sig_entry->oom_score_adj)
+ link = &parent->rb_right;
+ else
+ link = &parent->rb_left;
+ }
+
+ rb_link_node(&task->signal->adj_node, parent, link);
+ rb_insert_color(&task->signal->adj_node, &tasks_scoreadj);
+ spin_unlock(&lmk_lock);
+}
+
+/*
+ * Makesure to invoke the function with holding sighand->siglock
+ */
+void delete_from_adj_tree(struct task_struct *task)
+{
+ spin_lock(&lmk_lock);
+ if (!RB_EMPTY_NODE(&task->signal->adj_node)) {
+ rb_erase(&task->signal->adj_node, &tasks_scoreadj);
+ RB_CLEAR_NODE(&task->signal->adj_node);
+ }
+ spin_unlock(&lmk_lock);
+}
+
+static struct task_struct *pick_next_from_adj_tree(struct task_struct *task)
+{
+ struct rb_node *next;
+ struct signal_struct *next_tsk_sig;
+
+ spin_lock(&lmk_lock);
+ next = rb_next(&task->signal->adj_node);
+ spin_unlock(&lmk_lock);
+
+ if (!next)
+ return NULL;
+
+ next_tsk_sig = rb_entry(next, struct signal_struct, adj_node);
+ return next_tsk_sig->curr_target->group_leader;
+}
+
+static struct task_struct *pick_first_task(void)
+{
+ struct rb_node *left;
+ struct signal_struct *first_tsk_sig;
+
+ spin_lock(&lmk_lock);
+ left = rb_first(&tasks_scoreadj);
+ spin_unlock(&lmk_lock);
+
+ if (!left)
+ return NULL;
+
+ first_tsk_sig = rb_entry(left, struct signal_struct, adj_node);
+ return first_tsk_sig->curr_target->group_leader;
+}
+static struct task_struct *pick_last_task(void)
+{
+ struct rb_node *right;
+ struct signal_struct *last_tsk_sig;
+
+ spin_lock(&lmk_lock);
+ right = rb_last(&tasks_scoreadj);
+ spin_unlock(&lmk_lock);
+
+ if (!right)
+ return NULL;
+
+ last_tsk_sig = rb_entry(right, struct signal_struct, adj_node);
+ return last_tsk_sig->curr_target->group_leader;
+}
+#endif
+
static struct shrinker lowmem_shrinker = {
.scan_objects = lowmem_scan,
.count_objects = lowmem_count,
current->comm, task_pid_nr(current), task_pid_nr(task),
task_pid_nr(task));
+ delete_from_adj_tree(task);
task->signal->oom_score_adj = oom_adj;
+ add_2_adj_tree(task);
trace_oom_score_adj_update(task);
err_sighand:
unlock_task_sighand(task, &flags);
goto err_sighand;
}
+ delete_from_adj_tree(task);
task->signal->oom_score_adj = (short)oom_score_adj;
+ add_2_adj_tree(task);
if (has_capability_noaudit(current, CAP_SYS_RESOURCE))
task->signal->oom_score_adj_min = (short)oom_score_adj;
trace_oom_score_adj_update(task);
short oom_score_adj; /* OOM kill score adjustment */
short oom_score_adj_min; /* OOM kill score adjustment min value.
* Only settable by CAP_SYS_RESOURCE. */
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+ struct rb_node adj_node;
+#endif
struct mutex cred_guard_mutex; /* guard against foreign influences on
* credential calculations
return task->group_leader->pids[PIDTYPE_PID].pid;
}
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+extern void add_2_adj_tree(struct task_struct *task);
+extern void delete_from_adj_tree(struct task_struct *task);
+#else
+static inline void add_2_adj_tree(struct task_struct *task) { }
+static inline void delete_from_adj_tree(struct task_struct *task) { }
+#endif
+
/*
* Without tasklist or rcu lock it is not safe to dereference
* the result of task_pgrp/task_session even if task == current,
sig->oom_score_adj = current->signal->oom_score_adj;
sig->oom_score_adj_min = current->signal->oom_score_adj_min;
+#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
+ RB_CLEAR_NODE(&sig->adj_node);
+#endif
sig->has_child_subreaper = current->signal->has_child_subreaper ||
current->signal->is_child_subreaper;
p->signal->tty = tty_kref_get(current->signal->tty);
list_add_tail(&p->sibling, &p->real_parent->children);
list_add_tail_rcu(&p->tasks, &init_task.tasks);
+ add_2_adj_tree(p);
attach_pid(p, PIDTYPE_PGID);
attach_pid(p, PIDTYPE_SID);
__this_cpu_inc(process_counts);