OSDN Git Service

lmk: import rbtree changes from Motorola
authorPark Ju Hyung <qkrwngud825@gmail.com>
Wed, 17 Jul 2019 17:43:50 +0000 (02:43 +0900)
committer0ranko0P <ranko0p@outlook.com>
Sat, 7 Dec 2019 10:22:21 +0000 (18:22 +0800)
Signed-off-by: Park Ju Hyung <qkrwngud825@gmail.com>
Signed-off-by: Julian Liu <wlootlxt123@gmail.com>
[@wloot: backport to k4.4]

drivers/staging/android/Kconfig
drivers/staging/android/lowmemorykiller.c
fs/exec.c
fs/proc/base.c
include/linux/sched.h
kernel/exit.c
kernel/fork.c

index daba109..aa5fd43 100644 (file)
@@ -47,6 +47,14 @@ config ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
          /sys/module/lowmemorykiller/parameters/adj and convert them
          to oom_score_adj values.
 
+config ANDROID_LMK_ADJ_RBTREE
+       bool "Use RBTREE for Android Low Memory Killer"
+       depends on ANDROID_LOW_MEMORY_KILLER
+       default N
+       ---help---
+         Use oom_score_adj rbtree to select the best proecss to kill
+         when system in low memory status.
+
 config SYNC
        bool "Synchronization framework"
        default n
index 75483df..4b5ab1a 100644 (file)
@@ -81,6 +81,12 @@ static unsigned long lowmem_count(struct shrinker *s,
                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;
@@ -124,7 +130,13 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
        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;
 
@@ -144,7 +156,11 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
                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);
@@ -195,6 +211,100 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
        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,
index 83b58dd..ceb8609 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1019,6 +1019,15 @@ static int de_thread(struct task_struct *tsk)
                leader->group_leader = tsk;
 
                tsk->exit_signal = SIGCHLD;
+               /*
+                * need to delete leader from adj tree, because it will not be
+                * group leader (exit_signal = -1) soon. release_task(leader)
+                * can't delete it.
+                */
+               spin_lock_irq(lock);
+               delete_from_adj_tree(leader);
+               add_2_adj_tree(tsk);
+               spin_unlock_irq(lock);
                leader->exit_signal = -1;
 
                BUG_ON(leader->exit_state != EXIT_ZOMBIE);
index ae5350d..4562b8c 100644 (file)
@@ -1144,7 +1144,9 @@ static ssize_t oom_adj_write(struct file *file, const char __user *buf,
                  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);
@@ -1230,7 +1232,9 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf,
                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);
index b46fd66..e316830 100644 (file)
@@ -885,6 +885,9 @@ struct signal_struct {
        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
@@ -2190,6 +2193,14 @@ static inline struct pid *task_tgid(struct task_struct *task)
        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,
index 3cf6037..a960e3e 100644 (file)
@@ -73,6 +73,7 @@ static void __unhash_process(struct task_struct *p, bool group_dead)
                detach_pid(p, PIDTYPE_SID);
 
                list_del_rcu(&p->tasks);
+               delete_from_adj_tree(p);
                list_del_init(&p->sibling);
                __this_cpu_dec(process_counts);
        }
index 29b6083..379036e 100644 (file)
@@ -1228,6 +1228,9 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 
        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;
@@ -1682,6 +1685,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
                        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);