Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932977AbcKVLRl (ORCPT ); Tue, 22 Nov 2016 06:17:41 -0500 Received: from mail-pf0-f193.google.com ([209.85.192.193]:35822 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932164AbcKVLRk (ORCPT ); Tue, 22 Nov 2016 06:17:40 -0500 From: Ganesh Mahendran To: gregkh@linuxfoundation.org, arve@android.com, riandrews@android.com Cc: linux-kernel@vger.kernel.org, Ganesh Mahendran Subject: [PATCH] binder: replace kzalloc with kmem_cache Date: Tue, 22 Nov 2016 19:17:30 +0800 Message-Id: <1479813450-4462-1-git-send-email-opensource.ganesh@gmail.com> X-Mailer: git-send-email 1.9.1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10460 Lines: 310 This patch use kmem_cache to allocate/free binder objects. It will have better memory efficiency. And we can also get object usage details in /sys/kernel/slab/* for futher analysis. Signed-off-by: Ganesh Mahendran --- drivers/android/binder.c | 127 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 104 insertions(+), 23 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 3c71b98..f1f8362 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -54,6 +54,14 @@ static HLIST_HEAD(binder_deferred_list); static HLIST_HEAD(binder_dead_nodes); +static struct kmem_cache *binder_proc_cachep; +static struct kmem_cache *binder_thread_cachep; +static struct kmem_cache *binder_node_cachep; +static struct kmem_cache *binder_ref_cachep; +static struct kmem_cache *binder_transaction_cachep; +static struct kmem_cache *binder_work_cachep; +static struct kmem_cache *binder_ref_death_cachep; + static struct dentry *binder_debugfs_dir_entry_root; static struct dentry *binder_debugfs_dir_entry_proc; static struct binder_node *binder_context_mgr_node; @@ -902,7 +910,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, return NULL; } - node = kzalloc(sizeof(*node), GFP_KERNEL); + node = kmem_cache_zalloc(binder_node_cachep, GFP_KERNEL); if (node == NULL) return NULL; binder_stats_created(BINDER_STAT_NODE); @@ -992,7 +1000,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal) "dead node %d deleted\n", node->debug_id); } - kfree(node); + kmem_cache_free(binder_node_cachep, node); binder_stats_deleted(BINDER_STAT_NODE); } } @@ -1043,7 +1051,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, else return ref; } - new_ref = kzalloc(sizeof(*ref), GFP_KERNEL); + new_ref = kmem_cache_zalloc(binder_ref_cachep, GFP_KERNEL); if (new_ref == NULL) return NULL; binder_stats_created(BINDER_STAT_REF); @@ -1108,10 +1116,10 @@ static void binder_delete_ref(struct binder_ref *ref) "%d delete ref %d desc %d has death notification\n", ref->proc->pid, ref->debug_id, ref->desc); list_del(&ref->death->work.entry); - kfree(ref->death); + kmem_cache_free(binder_ref_death_cachep, ref->death); binder_stats_deleted(BINDER_STAT_DEATH); } - kfree(ref); + kmem_cache_free(binder_ref_cachep, ref); binder_stats_deleted(BINDER_STAT_REF); } @@ -1183,7 +1191,7 @@ static void binder_pop_transaction(struct binder_thread *target_thread, t->need_reply = 0; if (t->buffer) t->buffer->transaction = NULL; - kfree(t); + kmem_cache_free(binder_transaction_cachep, t); binder_stats_deleted(BINDER_STAT_TRANSACTION); } @@ -1444,14 +1452,14 @@ static void binder_transaction(struct binder_proc *proc, e->to_proc = target_proc->pid; /* TODO: reuse incoming transaction for reply */ - t = kzalloc(sizeof(*t), GFP_KERNEL); + t = kmem_cache_zalloc(binder_transaction_cachep, GFP_KERNEL); if (t == NULL) { return_error = BR_FAILED_REPLY; goto err_alloc_t_failed; } binder_stats_created(BINDER_STAT_TRANSACTION); - tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL); + tcomplete = kmem_cache_zalloc(binder_work_cachep, GFP_KERNEL); if (tcomplete == NULL) { return_error = BR_FAILED_REPLY; goto err_alloc_tcomplete_failed; @@ -1742,10 +1750,10 @@ static void binder_transaction(struct binder_proc *proc, t->buffer->transaction = NULL; binder_free_buf(target_proc, t->buffer); err_binder_alloc_buf_failed: - kfree(tcomplete); + kmem_cache_free(binder_work_cachep, tcomplete); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); err_alloc_tcomplete_failed: - kfree(t); + kmem_cache_free(binder_transaction_cachep, t); binder_stats_deleted(BINDER_STAT_TRANSACTION); err_alloc_t_failed: err_bad_call_stack: @@ -2039,7 +2047,7 @@ static int binder_thread_write(struct binder_proc *proc, proc->pid, thread->pid); break; } - death = kzalloc(sizeof(*death), GFP_KERNEL); + death = kmem_cache_zalloc(binder_ref_death_cachep, GFP_KERNEL); if (death == NULL) { thread->return_error = BR_ERROR; binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, @@ -2282,7 +2290,7 @@ static int binder_thread_read(struct binder_proc *proc, proc->pid, thread->pid); list_del(&w->entry); - kfree(w); + kmem_cache_free(binder_work_cachep, w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); } break; case BINDER_WORK_NODE: { @@ -2342,7 +2350,7 @@ static int binder_thread_read(struct binder_proc *proc, (u64)node->ptr, (u64)node->cookie); rb_erase(&node->rb_node, &proc->nodes); - kfree(node); + kmem_cache_free(binder_node_cachep, node); binder_stats_deleted(BINDER_STAT_NODE); } else { binder_debug(BINDER_DEBUG_INTERNAL_REFS, @@ -2383,7 +2391,7 @@ static int binder_thread_read(struct binder_proc *proc, if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) { list_del(&w->entry); - kfree(death); + kmem_cache_free(binder_ref_death_cachep, death); binder_stats_deleted(BINDER_STAT_DEATH); } else list_move(&w->entry, &proc->delivered_death); @@ -2463,7 +2471,7 @@ static int binder_thread_read(struct binder_proc *proc, thread->transaction_stack = t; } else { t->buffer->transaction = NULL; - kfree(t); + kmem_cache_free(binder_transaction_cachep, t); binder_stats_deleted(BINDER_STAT_TRANSACTION); } break; @@ -2508,14 +2516,14 @@ static void binder_release_work(struct list_head *list) "undelivered transaction %d\n", t->debug_id); t->buffer->transaction = NULL; - kfree(t); + kmem_cache_free(binder_transaction_cachep, t); binder_stats_deleted(BINDER_STAT_TRANSACTION); } } break; case BINDER_WORK_TRANSACTION_COMPLETE: { binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, "undelivered TRANSACTION_COMPLETE\n"); - kfree(w); + kmem_cache_free(binder_work_cachep, w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); } break; case BINDER_WORK_DEAD_BINDER_AND_CLEAR: @@ -2526,7 +2534,7 @@ static void binder_release_work(struct list_head *list) binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, "undelivered death notification, %016llx\n", (u64)death->cookie); - kfree(death); + kmem_cache_free(binder_ref_death_cachep, death); binder_stats_deleted(BINDER_STAT_DEATH); } break; default: @@ -2556,7 +2564,7 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) break; } if (*p == NULL) { - thread = kzalloc(sizeof(*thread), GFP_KERNEL); + thread = kmem_cache_zalloc(binder_thread_cachep, GFP_KERNEL); if (thread == NULL) return NULL; binder_stats_created(BINDER_STAT_THREAD); @@ -2609,7 +2617,7 @@ static int binder_free_thread(struct binder_proc *proc, if (send_reply) binder_send_failed_reply(send_reply, BR_DEAD_REPLY); binder_release_work(&thread->todo); - kfree(thread); + kmem_cache_free(binder_thread_cachep, thread); binder_stats_deleted(BINDER_STAT_THREAD); return active_transactions; } @@ -2973,7 +2981,7 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n", current->group_leader->pid, current->pid); - proc = kzalloc(sizeof(*proc), GFP_KERNEL); + proc = kmem_cache_zalloc(binder_proc_cachep, GFP_KERNEL); if (proc == NULL) return -ENOMEM; get_task_struct(current); @@ -3053,7 +3061,7 @@ static int binder_node_release(struct binder_node *node, int refs) binder_release_work(&node->async_todo); if (hlist_empty(&node->refs)) { - kfree(node); + kmem_cache_free(binder_node_cachep, node); binder_stats_deleted(BINDER_STAT_NODE); return refs; @@ -3190,7 +3198,7 @@ static void binder_deferred_release(struct binder_proc *proc) __func__, proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count); - kfree(proc); + kmem_cache_free(binder_proc_cachep, proc); } static void binder_deferred_func(struct work_struct *work) @@ -3691,10 +3699,83 @@ static int binder_transaction_log_show(struct seq_file *m, void *unused) BINDER_DEBUG_ENTRY(transactions); BINDER_DEBUG_ENTRY(transaction_log); +static void binder_destroy_cache(void) +{ + if (binder_proc_cachep) + kmem_cache_destroy(binder_proc_cachep); + + if (binder_thread_cachep) + kmem_cache_destroy(binder_thread_cachep); + + if (binder_node_cachep) + kmem_cache_destroy(binder_node_cachep); + + if (binder_ref_cachep) + kmem_cache_destroy(binder_ref_cachep); + + if (binder_transaction_cachep) + kmem_cache_destroy(binder_transaction_cachep); + + if (binder_work_cachep) + kmem_cache_destroy(binder_work_cachep); + + if (binder_ref_death_cachep) + kmem_cache_destroy(binder_ref_death_cachep); +} + +static int __init binder_create_cache(void) +{ + binder_proc_cachep = kmem_cache_create("binder_proc", + sizeof(struct binder_proc), 0, 0, NULL); + if (!binder_proc_cachep) + goto fail; + + binder_thread_cachep = kmem_cache_create("binder_thread", + sizeof(struct binder_thread), 0, 0, NULL); + if (!binder_thread_cachep) + goto fail; + + binder_node_cachep = kmem_cache_create("binder_node", + sizeof(struct binder_node), 0, 0, NULL); + if (!binder_node_cachep) + goto fail; + + binder_ref_cachep = kmem_cache_create("binder_ref", + sizeof(struct binder_ref), 0, 0, NULL); + if (!binder_ref_cachep) + goto fail; + + binder_transaction_cachep = kmem_cache_create("binder_transaction", + sizeof(struct binder_transaction), 0, 0, NULL); + if (!binder_transaction_cachep) + goto fail; + + binder_work_cachep = kmem_cache_create("binder_work", + sizeof(struct binder_work), 0, 0, NULL); + if (!binder_work_cachep) + goto fail; + + binder_ref_death_cachep = kmem_cache_create("binder_ref_death", + sizeof(struct binder_ref_death), 0, 0, NULL); + if (!binder_ref_death_cachep) + goto fail; + + return 0; + +fail: + binder_destroy_cache(); + return -ENOMEM; +} + static int __init binder_init(void) { int ret; + if (binder_create_cache()) { + pr_err("binder cache creation failed\n"); + return -ENOMEM; + } + binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL); if (binder_debugfs_dir_entry_root) binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", -- 1.9.1