Skip to content

Commit

Permalink
LMK: Import RB Tree optimization from Motorola
Browse files Browse the repository at this point in the history
Signed-off-by: Paul Reioux <[email protected]>
  • Loading branch information
faux123 committed Dec 27, 2014
1 parent 8e2b591 commit ff5702a
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 0 deletions.
8 changes: 8 additions & 0 deletions drivers/staging/android/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,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 "Android Low Memory Killer: Red-Black Tree search"
depends on ANDROID_LOW_MEMORY_KILLER
default y
---help---
Utilize RB Tree for walking the tasklist.. O(log n) vs O(n)
much speedier for long task list!

source "drivers/staging/android/switch/Kconfig"

config ANDROID_INTF_ALARM_DEV
Expand Down
99 changes: 99 additions & 0 deletions drivers/staging/android/lowmemorykiller.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc)
}
}

#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 DEFINE_MUTEX(scan_mutex);

static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
Expand Down Expand Up @@ -310,7 +316,13 @@ static int lowmem_shrink(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 = pick_next_from_adj_tree(tsk)) {
#else
for_each_process(tsk) {
#endif
struct task_struct *p;
int oom_score_adj;

Expand Down Expand Up @@ -338,15 +350,23 @@ static int lowmem_shrink(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);
if (tasksize <= 0)
continue;
if (selected) {
if (oom_score_adj < selected_oom_score_adj)
#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
break;
#else
continue;
#endif
if (oom_score_adj == selected_oom_score_adj &&
tasksize <= selected_tasksize)
continue;
Expand Down Expand Up @@ -498,6 +518,85 @@ static const struct kparam_array __param_arr_adj = {
};
#endif

#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
DEFINE_SPINLOCK(lmk_lock);
struct rb_root tasks_scoreadj = RB_ROOT;
void add_2_adj_tree(struct task_struct *task)
{
struct rb_node **link = &tasks_scoreadj.rb_node;
struct rb_node *parent = NULL;
struct task_struct *task_entry;
s64 key = task->signal->oom_score_adj;
/*
* * Find the right place in the rbtree:
* */
spin_lock(&lmk_lock);
while (*link) {
parent = *link;
task_entry = rb_entry(parent, struct task_struct, adj_node);

if (key < task_entry->signal->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);
spin_unlock(&lmk_lock);
}

void delete_from_adj_tree(struct task_struct *task)
{
spin_lock(&lmk_lock);
rb_erase(&task->adj_node, &tasks_scoreadj);
spin_unlock(&lmk_lock);
}


static struct task_struct *pick_next_from_adj_tree(struct task_struct *task)
{
struct rb_node *next;

spin_lock(&lmk_lock);
next = rb_next(&task->adj_node);
spin_unlock(&lmk_lock);

if (!next)
return NULL;

return rb_entry(next, struct task_struct, adj_node);
}

static struct task_struct *pick_first_task(void)
{
struct rb_node *left;

spin_lock(&lmk_lock);
left = rb_first(&tasks_scoreadj);
spin_unlock(&lmk_lock);

if (!left)
return NULL;

return rb_entry(left, struct task_struct, adj_node);
}

static struct task_struct *pick_last_task(void)
{
struct rb_node *right;

spin_lock(&lmk_lock);
right = rb_last(&tasks_scoreadj);
spin_unlock(&lmk_lock);

if (!right)
return NULL;

return rb_entry(right, struct task_struct, adj_node);
}
#endif

module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
__module_param_call(MODULE_PARAM_PREFIX, adj,
Expand Down
11 changes: 11 additions & 0 deletions include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -1324,6 +1324,9 @@ struct task_struct {
#endif

struct list_head tasks;
#ifdef CONFIG_ANDROID_LMK_ADJ_RBTREE
struct rb_node adj_node;
#endif
#ifdef CONFIG_SMP
struct plist_node pushable_tasks;
#endif
Expand Down Expand Up @@ -1671,6 +1674,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,
Expand Down

0 comments on commit ff5702a

Please sign in to comment.