From patchwork Wed Sep 5 06:44:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhangfei Gao X-Patchwork-Id: 11184 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 4C03B23F26 for ; Wed, 5 Sep 2012 06:45:47 +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 53374A1883F for ; Wed, 5 Sep 2012 06:44:54 +0000 (UTC) Received: by mail-ie0-f180.google.com with SMTP id k11so364312iea.11 for ; Tue, 04 Sep 2012 23:45:46 -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=CUudEicMPyt7DbdjfKuklXfG8iVkqXvzPpddfSZXjXw=; b=fV+eo3HZhn1suksbHoo5Ns0Vus8uamM18cn2c5KTnoyauddcs+0U0drmzCygLA3l7f IYeyr+rVaya95d2GKm6S3HP+qF1P6WbRE59mL2zcyWwWqI1D2lH1yd+NUnqGMI5zYu6p sNl2e+o8UQKb2tZUr212IHCi1Xt9HFzIkazzQ40rNOZvNjSGu3oWCOSffilJV6K3sMof hcxFK5OF2NlgoKEQSM4JivU659L3OxrXjKMI7/PHIbAz9BOTpI+vTVKvpkYLKDTi+3xW vaM8Ra/7YCSpeeK88AA5ERuQRHjKS2E3jyfW9cJBW+gQWUHZOFm2r+NjfQZYh3EFzzKl zcJw== Received: by 10.42.84.69 with SMTP id k5mr20309230icl.5.1346827546443; Tue, 04 Sep 2012 23:45:46 -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 ex8csp236087igc; Tue, 4 Sep 2012 23:45:45 -0700 (PDT) Received: by 10.205.134.139 with SMTP id ic11mr9113794bkc.40.1346827545154; Tue, 04 Sep 2012 23:45:45 -0700 (PDT) Received: from mombin.canonical.com (mombin.canonical.com. [91.189.95.16]) by mx.google.com with ESMTP id ig20si168398bkc.13.2012.09.04.23.45.43; Tue, 04 Sep 2012 23:45:45 -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 1T99Ml-0003vW-2z; Wed, 05 Sep 2012 06:45:36 +0000 Received: from na3sys009aog131.obsmtp.com ([74.125.149.247]) by mombin.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1T99Mj-0003v1-9e for linaro-mm-sig@lists.linaro.org; Wed, 05 Sep 2012 06:45:33 +0000 Received: from MSI-MTA.marvell.com ([65.219.4.132]) (using TLSv1) by na3sys009aob131.postini.com ([74.125.148.12]) with SMTP ID DSNKUEb1CpXro21bbm08pfC+mgci6LgYgVqg@postini.com; Tue, 04 Sep 2012 23:45:33 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 23:44:38 -0700 Received: from localhost (unknown [10.26.128.111]) by maili.marvell.com (Postfix) with ESMTP id 722D84E510; Tue, 4 Sep 2012 23:44:38 -0700 (PDT) From: Zhangfei Gao To: Rebecca Schultz Zavin , "linaro-mm-sig@lists.linaro.org" , Haojian Zhuang , Nishanth Peethambaran Date: Wed, 5 Sep 2012 14:44:34 +0800 Message-Id: <1346827474-19709-3-git-send-email-zhangfei.gao@marvell.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1346827474-19709-1-git-send-email-zhangfei.gao@marvell.com> References: <1346827474-19709-1-git-send-email-zhangfei.gao@marvell.com> X-OriginalArrivalTime: 05 Sep 2012 06:44:38.0808 (UTC) FILETIME=[EBB99980:01CD8B31] Cc: Zhangfei Gao Subject: [Linaro-mm-sig] [PATCH v3 2/2] 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: ALoCoQljxpF2wlEK621SCcWL7iIbGg/Vj9xqz6wh4/BEsfR9TjUPYNz9thVe6EMA0tni2nX5NXNg 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 | 117 +++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 114 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c index 96f9cd7..383f588 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_found = NULL; pr_debug("%s: len %d align %d heap_mask %u flags %x\n", __func__, len, align, heap_mask, flags); @@ -389,6 +394,7 @@ 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); @@ -398,12 +404,18 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, /* if the caller didn't specify this heap type */ if (!((1 << heap->id) & heap_mask)) continue; + heap_found = heap; buffer = ion_buffer_create(heap, dev, len, align, flags); if (!IS_ERR_OR_NULL(buffer)) break; } mutex_unlock(&dev->lock); + if ((buffer == ERR_PTR(-ENOMEM) && heap_found)) { + if (!ion_shrink(heap_found, 0)) + goto retry; + } + if (buffer == NULL) return ERR_PTR(-ENODEV); @@ -1178,7 +1190,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 +1204,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 +1241,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->id); + 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;