diff options
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/android/binder.c | 10 | ||||
-rw-r--r-- | drivers/staging/android/logger.c | 7 | ||||
-rw-r--r-- | drivers/staging/android/logger.h | 1 | ||||
-rw-r--r-- | drivers/staging/android/lowmemorykiller.c | 51 |
4 files changed, 68 insertions, 1 deletions
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 17d89a8124ad..da7c984b5641 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -43,6 +43,7 @@ static struct proc_dir_entry *binder_proc_dir_entry_proc; static struct hlist_head binder_dead_nodes; static HLIST_HEAD(binder_deferred_list); static DEFINE_MUTEX(binder_deferred_lock); +static struct workqueue_struct *binder_deferred_workqueue; static int binder_read_proc_proc(char *page, char **start, off_t off, int count, int *eof, void *data); @@ -2986,6 +2987,7 @@ static void binder_deferred_release(struct binder_proc *proc) int i; for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) { if (proc->pages[i]) { + void *page_addr = proc->buffer + i * PAGE_SIZE; if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC) printk(KERN_INFO @@ -2993,6 +2995,8 @@ static void binder_deferred_release(struct binder_proc *proc) "page %d at %p not freed\n", proc->pid, i, proc->buffer + i * PAGE_SIZE); + unmap_kernel_range((unsigned long)page_addr, + PAGE_SIZE); __free_page(proc->pages[i]); page_count++; } @@ -3062,7 +3066,7 @@ static void binder_defer_work(struct binder_proc *proc, int defer) if (hlist_unhashed(&proc->deferred_work_node)) { hlist_add_head(&proc->deferred_work_node, &binder_deferred_list); - schedule_work(&binder_deferred_work); + queue_work(binder_deferred_workqueue, &binder_deferred_work); } mutex_unlock(&binder_deferred_lock); } @@ -3690,6 +3694,10 @@ static int __init binder_init(void) { int ret; + binder_deferred_workqueue = create_singlethread_workqueue("binder"); + if (!binder_deferred_workqueue) + return -ENOMEM; + binder_proc_dir_entry_root = proc_mkdir("binder", NULL); if (binder_proc_dir_entry_root) binder_proc_dir_entry_proc = proc_mkdir("proc", diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index 6c10b456c6cc..7f64f8fb26b0 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -556,6 +556,7 @@ static struct logger_log VAR = { \ DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 64*1024) DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024) DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 64*1024) +DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 64*1024) static struct logger_log *get_log_from_minor(int minor) { @@ -565,6 +566,8 @@ static struct logger_log *get_log_from_minor(int minor) return &log_events; if (log_radio.misc.minor == minor) return &log_radio; + if (log_system.misc.minor == minor) + return &log_system; return NULL; } @@ -601,6 +604,10 @@ static int __init logger_init(void) if (unlikely(ret)) goto out; + ret = init_log(&log_system); + if (unlikely(ret)) + goto out; + out: return ret; } diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h index a562434d7419..2cb06e9d8f98 100644 --- a/drivers/staging/android/logger.h +++ b/drivers/staging/android/logger.h @@ -32,6 +32,7 @@ struct logger_entry { #define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */ #define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */ +#define LOGGER_LOG_SYSTEM "log_system" /* system/framework messages */ #define LOGGER_LOG_MAIN "log_main" /* everything else */ #define LOGGER_ENTRY_MAX_LEN (4*1024) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 803b891dc85e..572dc062759a 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -18,6 +18,9 @@ #include <linux/mm.h> #include <linux/oom.h> #include <linux/sched.h> +#include <linux/nodemask.h> +#include <linux/vmstat.h> +#include <linux/notifier.h> static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask); @@ -41,6 +44,8 @@ static size_t lowmem_minfree[6] = { }; static int lowmem_minfree_size = 4; +static struct task_struct *lowmem_deathpending; + #define lowmem_print(level, x...) \ do { \ if (lowmem_debug_level >= (level)) \ @@ -54,6 +59,24 @@ module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, S_IRUGO | S_IWUSR); module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR); +static int +task_notify_func(struct notifier_block *self, unsigned long val, void *data); + +static struct notifier_block task_nb = { + .notifier_call = task_notify_func, +}; + +static int +task_notify_func(struct notifier_block *self, unsigned long val, void *data) +{ + struct task_struct *task = data; + if (task == lowmem_deathpending) { + lowmem_deathpending = NULL; + task_free_unregister(&task_nb); + } + return NOTIFY_OK; +} + static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask) { struct task_struct *p; @@ -67,6 +90,24 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask) int array_size = ARRAY_SIZE(lowmem_adj); int other_free = global_page_state(NR_FREE_PAGES); int other_file = global_page_state(NR_FILE_PAGES); + int node; + + /* + * If we already have a death outstanding, then + * bail out right away; indicating to vmscan + * that we have nothing further to offer on + * this pass. + */ + if (lowmem_deathpending) + return 0; + + for_each_node_state(node, N_HIGH_MEMORY) { + struct zone *z = + &NODE_DATA(node)->node_zones[ZONE_DMA]; + + other_free -= zone_page_state(z, NR_FREE_PAGES); + other_file -= zone_page_state(z, NR_FILE_PAGES); + } if (lowmem_adj_size < array_size) array_size = lowmem_adj_size; @@ -128,9 +169,19 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask) p->pid, p->comm, oom_adj, tasksize); } if (selected) { + if (fatal_signal_pending(selected)) { + pr_warning("process %d is suffering a slow death\n", + selected->pid); + read_unlock(&tasklist_lock); + return rem; + } lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n", selected->pid, selected->comm, selected_oom_adj, selected_tasksize); + + lowmem_deathpending = selected; + task_free_register(&task_nb); + force_sig(SIGKILL, selected); rem -= selected_tasksize; } |