summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Smith <dsmith@redhat.com>2009-12-02 15:16:10 -0600
committerDavid Smith <dsmith@redhat.com>2009-12-02 15:16:10 -0600
commit4a0ae64c47b159d4dd0ea471f1f8044503843a7f (patch)
treeec5733d43362d0302138e69130f95c3b677f0de7
parentc10fce7d6aaa57a4f94f9d7aeea906597456f7ce (diff)
downloadsystemtap-steved-4a0ae64c47b159d4dd0ea471f1f8044503843a7f.tar.gz
systemtap-steved-4a0ae64c47b159d4dd0ea471f1f8044503843a7f.tar.xz
systemtap-steved-4a0ae64c47b159d4dd0ea471f1f8044503843a7f.zip
Fix PR 11034 by directly allocating per-cpu context data.
* translate.cxx (emit_common_header): Change type of 'contexts' to an array of struct context pointers. (emit_module_init): Allocate a context structure for each possible cpu. Free each if an error occurs. (emit_module_exit): Update contexts reference. Free each possible cpu's context structure. * tapsets.cxx (common_probe_entryfn_prologue): Use array instead of percpu data for context structure.
-rw-r--r--tapsets.cxx2
-rw-r--r--translate.cxx36
2 files changed, 29 insertions, 9 deletions
diff --git a/tapsets.cxx b/tapsets.cxx
index 7bae4615..51f1ccc9 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -100,7 +100,7 @@ common_probe_entryfn_prologue (translator_output* o, string statestr,
o->newline(1) << "goto probe_epilogue;";
o->indent(-1);
- o->newline() << "c = per_cpu_ptr (contexts, smp_processor_id());";
+ o->newline() << "c = contexts[smp_processor_id()];";
o->newline() << "if (atomic_inc_return (& c->busy) != 1) {";
o->newline(1) << "#if !INTERRUPTIBLE";
o->newline() << "atomic_inc (& skipped_count);";
diff --git a/translate.cxx b/translate.cxx
index 03f7c86a..4b006159 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -1028,7 +1028,7 @@ c_unparser::emit_common_header ()
o->newline() << "#endif";
o->newline(-1) << "};\n";
- o->newline() << "static void *contexts = NULL; /* alloc_percpu */\n";
+ o->newline() << "static struct context *contexts[NR_CPUS] = { NULL };\n";
emit_map_type_instantiations ();
@@ -1124,6 +1124,7 @@ c_unparser::emit_module_init ()
o->newline();
o->newline() << "static int systemtap_module_init (void) {";
o->newline(1) << "int rc = 0;";
+ o->newline() << "int cpu;";
o->newline() << "int i=0, j=0;"; // for derived_probe_group use
o->newline() << "const char *probe_point = \"\";";
@@ -1186,13 +1187,16 @@ c_unparser::emit_module_init ()
// terminate. These may set STAP_SESSION_ERROR!
// per-cpu context
- o->newline() << "if (sizeof (struct context) <= 131072)";
- o->newline(1) << "contexts = alloc_percpu (struct context);";
- o->newline(-1) << "if (contexts == NULL) {";
- o->newline(1) << "_stp_error (\"percpu context (size %lu) allocation failed\", (unsigned long) sizeof (struct context));";
+ o->newline() << "for_each_possible_cpu(cpu) {";
+ o->indent(1);
+ o->newline() << "contexts[cpu] = _stp_kzalloc(sizeof(struct context));";
+ o->newline() << "if (contexts[cpu] == NULL) {";
+ o->indent(1);
+ o->newline() << "_stp_error (\"context (size %lu) allocation failed\", (unsigned long) sizeof (struct context));";
o->newline() << "rc = -ENOMEM;";
o->newline() << "goto out;";
o->newline(-1) << "}";
+ o->newline(-1) << "}";
for (unsigned i=0; i<session->globals.size(); i++)
{
@@ -1290,7 +1294,14 @@ c_unparser::emit_module_init ()
o->newline() << "#endif";
// Free up the context memory after an error too
- o->newline() << "free_percpu (contexts);";
+ o->newline() << "for_each_possible_cpu(cpu) {";
+ o->indent(1);
+ o->newline() << "if (contexts[cpu] != NULL) {";
+ o->indent(1);
+ o->newline() << "_stp_kfree(contexts[cpu]);";
+ o->newline() << "contexts[cpu] = NULL;";
+ o->newline(-1) << "}";
+ o->newline(-1) << "}";
o->newline() << "return rc;";
o->newline(-1) << "}\n";
@@ -1304,6 +1315,7 @@ c_unparser::emit_module_exit ()
// rc?
o->newline(1) << "int holdon;";
o->newline() << "int i=0, j=0;"; // for derived_probe_group use
+ o->newline() << "int cpu;";
o->newline() << "(void) i;";
o->newline() << "(void) j;";
@@ -1346,7 +1358,8 @@ c_unparser::emit_module_exit ()
o->newline() << "holdon = 0;";
o->newline() << "for (i=0; i < NR_CPUS; i++)";
o->newline(1) << "if (cpu_possible (i) && "
- << "atomic_read (& ((struct context *)per_cpu_ptr(contexts, i))->busy)) "
+ << "contexts[i] != NULL && "
+ << "atomic_read (& contexts[i]->busy)) "
<< "holdon = 1;";
// NB: we run at least one of these during the shutdown sequence:
o->newline () << "yield ();"; // aka schedule() and then some
@@ -1369,7 +1382,14 @@ c_unparser::emit_module_exit ()
o->newline() << getvar (v).fini();
}
- o->newline() << "free_percpu (contexts);";
+ o->newline() << "for_each_possible_cpu(cpu) {";
+ o->indent(1);
+ o->newline() << "if (contexts[cpu] != NULL) {";
+ o->indent(1);
+ o->newline() << "_stp_kfree(contexts[cpu]);";
+ o->newline() << "contexts[cpu] = NULL;";
+ o->newline(-1) << "}";
+ o->newline(-1) << "}";
// print probe timing statistics
{