From 9b0e84ac672845689861120bbb58b33788f7f6a3 Mon Sep 17 00:00:00 2001 From: Hong-Mei Li Date: Wed, 3 Jun 2015 14:33:43 -0700 Subject: lowmemorykiller: maintain LMK rbtree with signal->adj_node Currently, we maintain LMK rbtree with task->adj_node. However, when handling oom_score_adj change case, we may del/add a non-leader task to the RB tree, which is not as expected. This patch we maintain the LMK rbtree with task->signal->adj_node. Since signal_struct is shared between main task and threads, we can avoid non-leader thread adding to tree. Change-Id: I3ba9e740e03ab04c25497a1cc2c870f051bd5b07 Signed-off-by: Hong-Mei Li Reviewed-on: http://gerrit.mot.com/754225 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhi-Ming Yuan Reviewed-by: Yi-Wei Zhao Submit-Approved: Jira Key (cherry picked from commit b40634023f9152c6232de9acb80108e0af7e4075) Signed-off-by: Abdul Salam Reviewed-on: http://gerrit.mot.com/766107 Reviewed-by: Sudharsan Yettapu Reviewed-by: Ravikumar Vembu (cherry picked from commit f3abd37ce3b4d36ae05cfc1c5cd10e5a3f584e7f) Reviewed-on: http://gerrit.mot.com/768302 --- drivers/staging/android/lowmemorykiller.c | 36 ++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index c6ee61c..f68459a 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -420,11 +420,14 @@ static const struct kparam_array __param_arr_adj = { #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 task_struct *task_entry; + struct signal_struct *sig_entry; s64 key = task->signal->oom_score_adj; /* @@ -434,25 +437,28 @@ void add_2_adj_tree(struct task_struct *task) link = &tasks_scoreadj.rb_node; while (*link) { parent = *link; - task_entry = rb_entry(parent, struct task_struct, adj_node); + sig_entry = rb_entry(parent, struct signal_struct, adj_node); - if (key < task_entry->signal->oom_score_adj) + if (key < sig_entry->oom_score_adj) link = &parent->rb_right; else link = &parent->rb_left; } - rb_link_node(&task->adj_node, parent, link); - rb_insert_color(&task->adj_node, &tasks_scoreadj); + 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->adj_node)) { - rb_erase(&task->adj_node, &tasks_scoreadj); - RB_CLEAR_NODE(&task->adj_node); + 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); } @@ -461,20 +467,23 @@ void delete_from_adj_tree(struct task_struct *task) 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->adj_node); + next = rb_next(&task->signal->adj_node); spin_unlock(&lmk_lock); if (!next) return NULL; - return rb_entry(next, struct task_struct, adj_node); + 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); @@ -483,12 +492,14 @@ static struct task_struct *pick_first_task(void) if (!left) return NULL; - return rb_entry(left, struct task_struct, adj_node); + 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); @@ -497,7 +508,8 @@ static struct task_struct *pick_last_task(void) if (!right) return NULL; - return rb_entry(right, struct task_struct, adj_node); + last_tsk_sig = rb_entry(right, struct signal_struct, adj_node); + return last_tsk_sig->curr_target->group_leader; } #endif -- cgit v1.1