From: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
To: akpm@linux-foundation.org, linux-kernel@vger.kernel.org
Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Subject: [patch 2/9] Conditional Calls - Hash Table
Date: Wed, 30 May 2007 10:00:27 -0400 [thread overview]
Message-ID: <20070530140227.398040643@polymtl.ca> (raw)
In-Reply-To: 20070530140025.917261793@polymtl.ca
[-- Attachment #1: conditional-calls-hash-table.patch --]
[-- Type: text/plain, Size: 10654 bytes --]
Reimplementation of the cond calls which uses a hash table to hold the active
cond_calls. It permits to first arm a cond_call and then load supplementary
modules that contain this cond_call.
Without this, the order of loading a module containing a cond_call and arming a
cond_call matters and there is no symbol dependency to check this.
At module load time, each cond_call checks if it is enabled in the hash table
and is set accordingly.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
---
include/linux/condcall.h | 2
kernel/module.c | 205 +++++++++++++++++++++++++++++------------------
2 files changed, 129 insertions(+), 78 deletions(-)
Index: linux-2.6-lttng/kernel/module.c
===================================================================
--- linux-2.6-lttng.orig/kernel/module.c 2007-05-17 01:42:50.000000000 -0400
+++ linux-2.6-lttng/kernel/module.c 2007-05-17 01:46:42.000000000 -0400
@@ -33,6 +33,8 @@
#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/condcall.h>
+#include <linux/jhash.h>
+#include <linux/list.h>
#include <linux/err.h>
#include <linux/vermagic.h>
#include <linux/notifier.h>
@@ -71,6 +73,20 @@
static BLOCKING_NOTIFIER_HEAD(module_notify_list);
+#ifdef CONFIG_COND_CALL
+/* Conditional call hash table, containing the active cond_calls.
+ * Protected by module_mutex. */
+#define COND_CALL_HASH_BITS 6
+#define COND_CALL_TABLE_SIZE (1 << COND_CALL_HASH_BITS)
+
+struct cond_call_entry {
+ struct hlist_node hlist;
+ char name[0];
+};
+
+static struct hlist_head cond_call_table[COND_CALL_TABLE_SIZE];
+#endif //CONFIG_COND_CALL
+
int register_module_notifier(struct notifier_block * nb)
{
return blocking_notifier_chain_register(&module_notify_list, nb);
@@ -305,6 +321,68 @@
}
#ifdef CONFIG_COND_CALL
+/* Check if the cond_call is present in the hash table.
+ * Returns 1 if present, 0 if not. */
+static int hash_check_cond_call(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct cond_call_entry *e;
+ size_t len = strlen(name);
+ u32 hash = jhash(name, len, 0);
+
+ head = &cond_call_table[hash & ((1 << COND_CALL_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist)
+ if (!strcmp(name, e->name))
+ return 1;
+ return 0;
+}
+
+/* Add the cond_call to the hash table. Must be called with mutex_lock held. */
+static int hash_add_cond_call(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct cond_call_entry *e;
+ size_t len = strlen(name);
+ u32 hash = jhash(name, len, 0);
+
+ head = &cond_call_table[hash & ((1 << COND_CALL_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist)
+ if (!strcmp(name, e->name))
+ return 0; /* Already there */
+ /* Using kmalloc here to allocate a variable length element. Could
+ * cause some memory fragmentation if overused. */
+ e = kmalloc(sizeof(struct cond_call_entry) + len + 1, GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
+ memcpy(&e->name[0], name, len + 1);
+ hlist_add_head(&e->hlist, head);
+ return 0;
+}
+
+/* Remove the cond_call from the hash table. Must be called with mutex_lock
+ * held. */
+static void hash_remove_cond_call(const char *name)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct cond_call_entry *e;
+ int found = 0;
+ size_t len = strlen(name);
+ u32 hash = jhash(name, len, 0);
+
+ head = &cond_call_table[hash & ((1 << COND_CALL_HASH_BITS)-1)];
+ hlist_for_each_entry(e, node, head, hlist)
+ if (!strcmp(name, e->name)) {
+ found = 1;
+ break;
+ }
+ if (found) {
+ hlist_del(&e->hlist);
+ kfree(e);
+ }
+}
/* Set the enable bit of the cond_call, choosing the generic or architecture
* specific functions depending on the cond_call's flags.
@@ -317,59 +395,53 @@
return cond_call_generic_set_enable(address, enable);
}
-/* Query the state of a cond_calls range. */
-static int _cond_call_query_range(const char *name,
- const struct __cond_call_struct *begin,
- const struct __cond_call_struct *end)
+static int cond_call_get_enable(void *address, int flags)
+{
+ if (flags & CF_OPTIMIZED)
+ return COND_CALL_OPTIMIZED_ENABLE(address);
+ else
+ return COND_CALL_GENERIC_ENABLE(address);
+}
+
+/* Setup the cond_call according to the data present in the cond_call hash
+ * upon module load. */
+void module_cond_call_setup(struct module *mod)
{
const struct __cond_call_struct *iter;
- int ret = 0;
+ int enable;
- for (iter = begin; iter < end; iter++) {
- if (strcmp(name, iter->name) != 0)
- continue;
- if (iter->flags & CF_OPTIMIZED)
- ret = COND_CALL_OPTIMIZED_ENABLE(iter->enable);
- else
- ret = COND_CALL_GENERIC_ENABLE(iter->enable);
- if (ret)
- break;
+ for (iter = mod->cond_calls;
+ iter < mod->cond_calls+mod->num_cond_calls; iter++) {
+ enable = hash_check_cond_call(iter->name);
+ if (enable != cond_call_get_enable(iter->enable, iter->flags))
+ cond_call_set_enable(iter->enable, enable, iter->flags);
}
- return ret;
}
/* Sets a range of cond_calls to a enabled state : set the enable bit. */
-static int _cond_call_arm_range(const char *name,
+static void _cond_call_arm_range(const char *name,
const struct __cond_call_struct *begin,
const struct __cond_call_struct *end)
{
const struct __cond_call_struct *iter;
- int found = 0;
for (iter = begin; iter < end; iter++) {
- if (strcmp(name, iter->name) != 0)
- continue;
- cond_call_set_enable(iter->enable, 1, iter->flags);
- found++;
+ if (!strcmp(name, iter->name))
+ cond_call_set_enable(iter->enable, 1, iter->flags);
}
- return found;
}
/* Sets a range of cond_calls to a disabled state : unset the enable bit. */
-static int _cond_call_disarm_range(const char *name,
+static void _cond_call_disarm_range(const char *name,
const struct __cond_call_struct *begin,
const struct __cond_call_struct *end)
{
const struct __cond_call_struct *iter;
- int found = 0;
for (iter = begin; iter < end; iter++) {
- if (strcmp(name, iter->name) != 0)
- continue;
- cond_call_set_enable(iter->enable, 0, iter->flags);
- found++;
+ if (!strcmp(name, iter->name))
+ cond_call_set_enable(iter->enable, 0, iter->flags);
}
- return found;
}
/* Provides a listing of the cond_calls present in the kernel with their type
@@ -397,105 +469,79 @@
return found;
}
-/* Calls _cond_call_query_range for the core cond_calls and modules cond_calls.
- */
-static int _cond_call_query(const char *name)
-{
- struct module *mod;
- int ret = 0;
-
- /* Core kernel cond_calls */
- ret = _cond_call_query_range(name,
- __start___cond_call, __stop___cond_call);
- if (ret)
- return ret;
- /* Cond_calls in modules. */
- list_for_each_entry(mod, &modules, list) {
- if (mod->taints)
- continue;
- ret = _cond_call_query_range(name,
- mod->cond_calls, mod->cond_calls+mod->num_cond_calls);
- if (ret)
- break;
- }
- return ret;
-}
-
/* Cond_call enabling/disabling use the module_mutex to synchronize.
- * Returns 1 if enabled, 0 if disabled or not present. */
+ * Returns 1 if enabled, 0 if disabled. */
int cond_call_query(const char *name)
{
- int ret = 0;
+ int ret;
mutex_lock(&module_mutex);
- ret = _cond_call_query(name);
+ ret = hash_check_cond_call(name);
mutex_unlock(&module_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(cond_call_query);
-/* Calls _cond_call_arm_range for the core cond_calls and modules cond_calls.
- * FIXME : cond_call will not be active on modules loaded later than the
- * cond_call_arm. */
+/* Calls _cond_call_arm_range for the core cond_calls and modules cond_calls. */
static int _cond_call_arm(const char *name)
{
struct module *mod;
- int found = 0;
+ int ret;
+
+ ret = hash_add_cond_call(name);
+ if (ret)
+ return ret;
/* Core kernel cond_calls */
- found += _cond_call_arm_range(name,
+ _cond_call_arm_range(name,
__start___cond_call, __stop___cond_call);
/* Cond_calls in modules. */
list_for_each_entry(mod, &modules, list) {
if (mod->taints)
continue;
- found += _cond_call_arm_range(name,
+ _cond_call_arm_range(name,
mod->cond_calls, mod->cond_calls+mod->num_cond_calls);
}
- return found;
+ return ret;
}
/* Cond_call enabling/disabling use the module_mutex to synchronize. */
int cond_call_arm(const char *name)
{
- int found = 0;
+ int ret;
mutex_lock(&module_mutex);
- found = _cond_call_arm(name);
+ ret = _cond_call_arm(name);
mutex_unlock(&module_mutex);
- return found;
+ return ret;
}
EXPORT_SYMBOL_GPL(cond_call_arm);
/* Calls _cond_call_disarm_range for the core cond_calls and modules cond_calls.
*/
-static int _cond_call_disarm(const char *name)
+static void _cond_call_disarm(const char *name)
{
struct module *mod;
- int found = 0;
/* Core kernel cond_calls */
- found += _cond_call_disarm_range(name,
+ _cond_call_disarm_range(name,
__start___cond_call, __stop___cond_call);
/* Cond_calls in modules. */
list_for_each_entry(mod, &modules, list) {
if (mod->taints)
continue;
- found += _cond_call_disarm_range(name,
+ _cond_call_disarm_range(name,
mod->cond_calls, mod->cond_calls+mod->num_cond_calls);
}
- return found;
+ hash_remove_cond_call(name);
}
/* Cond_call enabling/disabling use the module_mutex to synchronize. */
-int cond_call_disarm(const char *name)
+void cond_call_disarm(const char *name)
{
- int found = 0;
-
mutex_lock(&module_mutex);
- found = _cond_call_disarm(name);
+ _cond_call_disarm(name);
mutex_unlock(&module_mutex);
- return found;
}
EXPORT_SYMBOL_GPL(cond_call_disarm);
@@ -525,7 +571,10 @@
return found;
}
EXPORT_SYMBOL_GPL(cond_call_list);
-
+#else
+static void module_cond_call_setup(struct module *mod)
+{
+}
#endif
#ifdef CONFIG_SMP
@@ -2211,6 +2260,8 @@
add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
+ module_cond_call_setup(mod);
+
err = module_finalize(hdr, sechdrs, mod);
if (err < 0)
goto cleanup;
Index: linux-2.6-lttng/include/linux/condcall.h
===================================================================
--- linux-2.6-lttng.orig/include/linux/condcall.h 2007-05-17 01:42:50.000000000 -0400
+++ linux-2.6-lttng/include/linux/condcall.h 2007-05-17 01:46:42.000000000 -0400
@@ -81,7 +81,7 @@
#define COND_CALL_MAX_FORMAT_LEN 1024
extern int cond_call_arm(const char *name);
-extern int cond_call_disarm(const char *name);
+extern void cond_call_disarm(const char *name);
/* cond_call_query : Returns 1 if enabled, 0 if disabled or not present */
extern int cond_call_query(const char *name);
--
Mathieu Desnoyers
Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
next prev parent reply other threads:[~2007-05-30 14:04 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-30 14:00 [patch 0/9] Conditional Calls - for 2.6.22-rc2-mm1 Mathieu Desnoyers
2007-05-30 14:00 ` [patch 1/9] Conditional Calls - Architecture Independent Code Mathieu Desnoyers
2007-05-30 20:32 ` Andrew Morton
2007-05-31 16:34 ` Mathieu Desnoyers
2007-05-31 13:47 ` Andi Kleen
2007-06-05 18:40 ` Mathieu Desnoyers
2007-06-04 19:01 ` Adrian Bunk
2007-06-13 15:57 ` Mathieu Desnoyers
2007-06-13 21:51 ` Adrian Bunk
2007-06-14 16:02 ` Mathieu Desnoyers
2007-06-14 21:06 ` Adrian Bunk
2007-06-20 21:59 ` Mathieu Desnoyers
2007-06-21 13:00 ` Adrian Bunk
2007-06-21 13:55 ` Mathieu Desnoyers
2007-05-30 14:00 ` Mathieu Desnoyers [this message]
2007-05-30 20:32 ` [patch 2/9] Conditional Calls - Hash Table Andrew Morton
2007-05-31 13:42 ` Andi Kleen
2007-06-01 16:08 ` Matt Mackall
2007-06-01 16:46 ` Mathieu Desnoyers
2007-06-01 17:07 ` Matt Mackall
2007-06-01 17:45 ` Andi Kleen
2007-06-01 18:06 ` Mathieu Desnoyers
2007-06-01 18:49 ` Matt Mackall
2007-06-01 19:35 ` Andi Kleen
2007-06-01 20:33 ` Mathieu Desnoyers
2007-06-01 20:44 ` Andi Kleen
2007-06-04 22:26 ` Mathieu Desnoyers
2007-06-01 18:03 ` Mathieu Desnoyers
2007-05-30 14:00 ` [patch 3/9] Conditional Calls - Non Optimized Architectures Mathieu Desnoyers
2007-05-30 14:00 ` [patch 4/9] Conditional Calls - Add kconfig menus Mathieu Desnoyers
2007-05-30 14:00 ` [patch 5/9] Conditional Calls - i386 Optimization Mathieu Desnoyers
2007-05-30 20:33 ` Andrew Morton
2007-05-31 13:54 ` Andi Kleen
2007-06-05 19:02 ` Mathieu Desnoyers
2007-05-30 14:00 ` [patch 6/9] Conditional Calls - PowerPC Optimization Mathieu Desnoyers
2007-05-30 14:00 ` [patch 7/9] Conditional Calls - Documentation Mathieu Desnoyers
2007-05-30 14:00 ` [patch 8/9] F00F bug fixup for i386 - use conditional calls Mathieu Desnoyers
2007-05-30 20:33 ` Andrew Morton
2007-05-31 21:07 ` Mathieu Desnoyers
2007-05-31 21:21 ` Andrew Morton
2007-05-31 21:38 ` Mathieu Desnoyers
2007-05-30 14:00 ` [patch 9/9] Scheduler profiling - Use " Mathieu Desnoyers
2007-05-30 20:34 ` Andrew Morton
2007-06-01 15:54 ` Mathieu Desnoyers
2007-06-01 16:19 ` Andrew Morton
2007-06-01 16:33 ` Mathieu Desnoyers
2007-05-30 20:59 ` William Lee Irwin III
2007-05-31 21:12 ` Mathieu Desnoyers
2007-05-31 23:41 ` William Lee Irwin III
2007-06-04 22:20 ` Mathieu Desnoyers
2007-05-30 21:44 ` Matt Mackall
2007-05-31 21:36 ` Mathieu Desnoyers
2007-05-31 13:39 ` Andi Kleen
2007-05-31 22:07 ` Mathieu Desnoyers
2007-05-31 22:33 ` Andi Kleen
2007-06-04 22:20 ` Mathieu Desnoyers
-- strict thread matches above, loose matches on Subject: below --
2007-05-29 18:33 [patch 0/9] Conditional Calls Mathieu Desnoyers
2007-05-29 18:33 ` [patch 2/9] Conditional Calls - Hash Table Mathieu Desnoyers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070530140227.398040643@polymtl.ca \
--to=mathieu.desnoyers@polymtl.ca \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.