summaryrefslogtreecommitdiff
path: root/drivers/staging/android
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/android')
-rw-r--r--drivers/staging/android/binder.c10
-rw-r--r--drivers/staging/android/logger.c7
-rw-r--r--drivers/staging/android/logger.h1
-rw-r--r--drivers/staging/android/lowmemorykiller.c51
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;
}