From patchwork Tue Sep 4 08:22:15 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhangfei Gao X-Patchwork-Id: 11162 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id E25A823E54 for ; Tue, 4 Sep 2012 08:23:11 +0000 (UTC) Received: from mail-ie0-f180.google.com (mail-ie0-f180.google.com [209.85.223.180]) by fiordland.canonical.com (Postfix) with ESMTP id D8A2BA18800 for ; Tue, 4 Sep 2012 08:22:21 +0000 (UTC) Received: by mail-ie0-f180.google.com with SMTP id k11so4142129iea.11 for ; Tue, 04 Sep 2012 01:23:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to :date:message-id:x-mailer:in-reply-to:references :x-originalarrivaltime:cc:subject:x-beenthere:x-mailman-version :precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:mime-version:content-type :content-transfer-encoding:sender:errors-to:x-gm-message-state; bh=z2YCc4PdRxlWgtmrmLvTEqiAv2sGlE36fC5K2H3UgME=; b=aHeYpMZzAlcQ8n6qZN9nTVPuEhjwi/nbEtu6fQ1fVcsjGFQ0EyeLS7i7pZ+IT85Q0G 8YSOs3tugjWukRj6vuSgkqGBGywQexyoyxfjR17VK/QzP8e3mg/nMTLYAvyiTKxo6iJX eMaTjjscdtJgppBtER3Up0b3IeIcmqzV1Qho9WZ4Urn+7GL/IlY6weXMKGPxuERh1MeE FIVZXoVoMFXy36jaZ5KtcFkWqMWZexFsiGZtLGfWGfjCZOu9hh3BGTimdnIewHss6Y8C YS/oQxWcczrhpPSzDwrljAivNipfI+NO3D010I2/xSlT1MW1hSyybY9MK3Tf8zmiMobf Od4Q== Received: by 10.50.180.129 with SMTP id do1mr13164845igc.28.1346746991231; Tue, 04 Sep 2012 01:23:11 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.184.232 with SMTP id ex8csp175929igc; Tue, 4 Sep 2012 01:23:10 -0700 (PDT) Received: by 10.180.20.11 with SMTP id j11mr29042202wie.12.1346746989676; Tue, 04 Sep 2012 01:23:09 -0700 (PDT) Received: from mombin.canonical.com (mombin.canonical.com. [91.189.95.16]) by mx.google.com with ESMTP id n8si20162260wea.37.2012.09.04.01.23.08; Tue, 04 Sep 2012 01:23:09 -0700 (PDT) Received-SPF: neutral (google.com: 91.189.95.16 is neither permitted nor denied by best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org) client-ip=91.189.95.16; Authentication-Results: mx.google.com; spf=neutral (google.com: 91.189.95.16 is neither permitted nor denied by best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org) smtp.mail=linaro-mm-sig-bounces@lists.linaro.org Received: from localhost ([127.0.0.1] helo=mombin.canonical.com) by mombin.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1T8oPb-0005Ki-CY; Tue, 04 Sep 2012 08:23:07 +0000 Received: from na3sys009aog111.obsmtp.com ([74.125.149.205]) by mombin.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1T8oPa-0005K9-8J for linaro-mm-sig@lists.linaro.org; Tue, 04 Sep 2012 08:23:06 +0000 Received: from MSI-MTA.marvell.com ([65.219.4.132]) (using TLSv1) by na3sys009aob111.postini.com ([74.125.148.12]) with SMTP ID DSNKUEW6Zwl98ukdhR46Cu9GYDDTDglNYWGf@postini.com; Tue, 04 Sep 2012 01:23:06 PDT Received: from maili.marvell.com ([10.68.76.210]) by MSI-MTA.marvell.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 4 Sep 2012 01:22:21 -0700 Received: from localhost (unknown [10.26.128.111]) by maili.marvell.com (Postfix) with ESMTP id 77A2C4E510; Tue, 4 Sep 2012 01:22:21 -0700 (PDT) From: Zhangfei Gao To: Rebecca Schultz Zavin , "linaro-mm-sig@lists.linaro.org" , Haojian Zhuang Date: Tue, 4 Sep 2012 16:22:15 +0800 Message-Id: <1346746935-1149-4-git-send-email-zhangfei.gao@marvell.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1346746935-1149-1-git-send-email-zhangfei.gao@marvell.com> References: <1346746935-1149-1-git-send-email-zhangfei.gao@marvell.com> X-OriginalArrivalTime: 04 Sep 2012 08:22:21.0897 (UTC) FILETIME=[67FC3B90:01CD8A76] Cc: Zhangfei Gao Subject: [Linaro-mm-sig] [PATCH v2 3/3] gpu: ion: oom killer X-BeenThere: linaro-mm-sig@lists.linaro.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Unified memory management interest group." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linaro-mm-sig-bounces@lists.linaro.org Errors-To: linaro-mm-sig-bounces@lists.linaro.org X-Gm-Message-State: ALoCoQkB4YZIYobOztOxODHlF5/KOApP+cYC9fgiYzvofwCnwWvDDUd1JHtjbfs/3cyb3hF99/51 ion_shrink is called when ION_CARVEOUT_ALLOCATE_FAIL How to test: mount -t debugfs none /mnt cat /mnt/ion/carveout_heap echo adj > /mnt/ion/carveout_heap send_sig SIGKILL to the task with higher adj and using ion buffer Also kill all others tasks refered the buffers, in case using empty buffer Example: cat /mnt/ion/carveout_heap client pid size oom_score_adj ion_test 191 4096 0 ion_test 192 4096 0 ion_test 193 4096 0 echo -1 > /mnt/ion/carveout_heap [ 1333.689318] SIGKILL pid: 191 [ 1333.692192] SIGKILL pid: 192 [ 1333.695436] SIGKILL pid: 193 [ 1333.698312] SIGKILL pid: 193 size: 4096 adj: 0 [1]+ Killed ./ion_test 2 cat /mnt/ion/carveout_heap client pid size oom_score_adj Signed-off-by: Zhangfei Gao --- drivers/gpu/ion/ion.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 114 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c index 207d00f..5ead74c 100644 --- a/drivers/gpu/ion/ion.c +++ b/drivers/gpu/ion/ion.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "ion_priv.h" @@ -367,6 +369,8 @@ static void ion_handle_add(struct ion_client *client, struct ion_handle *handle) rb_insert_color(&handle->node, &client->handles); } +static int ion_shrink(struct ion_heap *heap, int kill_adj); + struct ion_handle *ion_alloc(struct ion_client *client, size_t len, size_t align, unsigned int heap_mask, unsigned int flags) @@ -375,6 +379,7 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, struct ion_handle *handle; struct ion_device *dev = client->dev; struct ion_buffer *buffer = NULL; + struct ion_heap *heap = NULL; pr_debug("%s: len %d align %d heap_mask %u flags %x\n", __func__, len, align, heap_mask, flags); @@ -389,9 +394,10 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, len = PAGE_ALIGN(len); +retry: mutex_lock(&dev->lock); for (n = rb_first(&dev->heaps); n != NULL; n = rb_next(n)) { - struct ion_heap *heap = rb_entry(n, struct ion_heap, node); + heap = rb_entry(n, struct ion_heap, node); /* if the client doesn't support this heap type */ if (!((1 << heap->type) & client->heap_mask)) continue; @@ -404,6 +410,11 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, } mutex_unlock(&dev->lock); + if (buffer == ERR_PTR(-ENOMEM)) { + if (!ion_shrink(heap, 0)) + goto retry; + } + if (buffer == NULL) return ERR_PTR(-ENODEV); @@ -1178,7 +1189,8 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) size_t total_size = 0; size_t total_orphaned_size = 0; - seq_printf(s, "%16.s %16.s %16.s\n", "client", "pid", "size"); + seq_printf(s, "%16.s %16.s %16.s %16.s\n", + "client", "pid", "size", "oom_score_adj"); seq_printf(s, "----------------------------------------------------\n"); for (n = rb_first(&dev->clients); n; n = rb_next(n)) { @@ -1191,8 +1203,9 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) char task_comm[TASK_COMM_LEN]; get_task_comm(task_comm, client->task); - seq_printf(s, "%16.s %16u %16u\n", task_comm, - client->pid, size); + seq_printf(s, "%16.s %16u %16u %16d\n", task_comm, + client->pid, size, + client->task->signal->oom_score_adj); } else { seq_printf(s, "%16.s %16u %16u\n", client->name, client->pid, size); @@ -1227,13 +1240,110 @@ static int ion_debug_heap_open(struct inode *inode, struct file *file) return single_open(file, ion_debug_heap_show, inode->i_private); } +static ssize_t +ion_debug_heap_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct ion_heap *heap = + ((struct seq_file *)file->private_data)->private; + char buf[16]; + long kill_adj, ret; + + memset(buf, 0, sizeof(buf)); + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + ret = kstrtol(buf, 10, &kill_adj); + if (ret) + return ret; + + ion_shrink(heap, kill_adj); + + return count; +} static const struct file_operations debug_heap_fops = { .open = ion_debug_heap_open, + .write = ion_debug_heap_write, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; +/* + * ion_shrink + * kill all tasks referd the buffer by selected task + */ +static int ion_shrink(struct ion_heap *heap, int kill_adj) +{ + struct rb_node *n; + struct ion_client *client = NULL; + struct ion_device *dev = heap->dev; + struct task_struct *selected = NULL; + int selected_size = 0; + int selected_oom_score_adj = 0; + + for (n = rb_first(&dev->clients); n; n = rb_next(n)) { + size_t size; + struct task_struct *p; + + client = rb_entry(n, struct ion_client, node); + if (!client->task) + continue; + + p = client->task; + + if ((p->signal->oom_score_adj <= kill_adj) || + (p->signal->oom_score_adj < selected_oom_score_adj)) + continue; + + size = ion_debug_heap_total(client, heap->type); + if (!size) + continue; + if (size < selected_size) + continue; + + selected = p; + selected_size = size; + selected_oom_score_adj = p->signal->oom_score_adj; + } + + if (selected) { + /* kill all proeces refer buffer shared with this client */ + mutex_lock(&client->lock); + for (n = rb_first(&client->handles); n; n = rb_next(n)) { + struct rb_node *r; + struct ion_client *c; + struct ion_handle *handle = rb_entry(n, + struct ion_handle, + node); + + for (r = rb_first(&dev->clients); r; r = rb_next(r)) { + struct ion_handle *h; + + c = rb_entry(r, struct ion_client, node); + h = ion_handle_lookup(c, handle->buffer); + if (!IS_ERR_OR_NULL(h)) { + send_sig(SIGKILL, c->task, 0); + pr_info("SIGKILL pid: %u\n", + c->task->pid); + } + + } + } + mutex_unlock(&client->lock); + + send_sig(SIGKILL, selected, 0); + set_tsk_thread_flag(selected, TIF_MEMDIE); + pr_info("SIGKILL pid: %u size: %u adj: %u\n", + selected->pid, selected_size, + selected_oom_score_adj); + msleep(20); + return 0; + } + return -EAGAIN; +} + void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) { struct rb_node **p = &dev->heaps.rb_node;