]> sourceware.org Git - systemtap.git/commitdiff
Fixed PR14427 by handling old and new task_work interface.
authorDavid Smith <dsmith@redhat.com>
Thu, 2 Aug 2012 15:01:23 +0000 (10:01 -0500)
committerDavid Smith <dsmith@redhat.com>
Thu, 2 Aug 2012 15:01:23 +0000 (10:01 -0500)
* runtime/linux/autoconf-utrace-via-tracepoints.c: Just includes
  task_work.h to determine existence of task_work feature.
* runtime/linux/autoconf-task_work-struct.c: New file.
* buildrun.cxx (compile_pass): Add autoconf-task_work-struct test.
* runtime/linux/task_work_compatibility.h: New header that mask
  differences between old task_work interface and new one.
* runtime/linux/task_finder2.c: Handle removal of 'data' parameter from
  task_work struct by embedding stap_task_finder_target in
  __stp_tf_task_work structure.
* runtime/stp_task_work.c: Include task_work_compatibility.h instead of
  task_work.h.
* runtime/stp_utrace.c (utrace_task_alloc): Update init_task_work()
  function call to compatibility function call.

buildrun.cxx
runtime/linux/autoconf-task_work-struct.c [new file with mode: 0644]
runtime/linux/autoconf-utrace-via-tracepoints.c
runtime/linux/task_finder2.c
runtime/linux/task_work_compatibility.h [new file with mode: 0644]
runtime/stp_task_work.c
runtime/stp_utrace.c

index fbaf2c16fbbafd5f45c7f45a4983a3e576dd6767..8340f092df890333b9444b6d1f66f71b3ace7b0b 100644 (file)
@@ -344,6 +344,7 @@ compile_pass (systemtap_session& s)
   output_autoconf(s, o, "autoconf-module-sect-attrs.c", "STAPCONF_MODULE_SECT_ATTRS", NULL);
 
   output_autoconf(s, o, "autoconf-utrace-via-tracepoints.c", "STAPCONF_UTRACE_VIA_TRACEPOINTS", NULL);
+  output_autoconf(s, o, "autoconf-task_work-struct.c", "STAPCONF_TASK_WORK_STRUCT", NULL);
   output_autoconf(s, o, "autoconf-vm-area-pte.c", "STAPCONF_VM_AREA_PTE", NULL);
   output_autoconf(s, o, "autoconf-relay-umode_t.c", "STAPCONF_RELAY_UMODE_T", NULL);
   output_autoconf(s, o, "autoconf-fs_supers-hlist.c", "STAPCONF_FS_SUPERS_HLIST", NULL);
diff --git a/runtime/linux/autoconf-task_work-struct.c b/runtime/linux/autoconf-task_work-struct.c
new file mode 100644 (file)
index 0000000..b6dbf14
--- /dev/null
@@ -0,0 +1,10 @@
+#include <linux/task_work.h>
+
+/* Original task_work code used 'struct task_work' (and
+ * init_task_work() had 3 arguments). */
+void __autoconf_func(void)
+{
+       struct task_work work;
+
+       init_task_work(&work, NULL, NULL);
+}
index dc679134306708543a94f089d954040d903b3edb..e103ab4b0195d97e862bdd7823b6631bc1703928 100644 (file)
@@ -2,12 +2,8 @@
 #include <trace/events/syscalls.h>
 #include <linux/task_work.h>
 
-// The utrace-less task_finder needs either:
-// - 5 specific tracepoints
-// - 4 specific tracepoints and ftrace_set_filter()
-// Both scenarios need <linux/task_work.h>.
-// 
-// Check scenario #1.
+// The utrace-less task_finder needs 5 specific tracepoints and
+// <linux/task_work.h>.
 
 void __sched_process_fork(void *cb_data __attribute__((unused)),
                          struct task_struct *parent __attribute__((unused)),
@@ -46,12 +42,9 @@ void __sys_exit(void *cb_data __attribute__ ((unused)),
 
 void __autoconf_func(void)
 {
-       struct task_work work;
-
        (void) register_trace_sched_process_fork(__sched_process_fork, NULL);
        (void) register_trace_sched_process_exit(__sched_process_exit, NULL);
        (void) register_trace_sched_process_exec(__sched_process_exec, NULL);
        (void) register_trace_sys_enter(__sys_enter, NULL);
        (void) register_trace_sys_exit(__sys_exit, NULL);
-       init_task_work(&work, NULL, NULL);
 }
index 81cb04eb4a94232d4a57af44338f1dad8b4d5643..15a3c493d134cb2b8bf9e6fd6c5a93baa0650044 100644 (file)
@@ -95,6 +95,7 @@ static DEFINE_SPINLOCK(__stp_tf_task_work_list_lock);
 struct __stp_tf_task_work {
        struct list_head list;
        struct task_struct *task;
+       struct stap_task_finder_target *tgt;
        struct task_work work;
 };
 
@@ -108,7 +109,8 @@ struct __stp_tf_task_work {
  * a 'struct task_work' for a task that isn't current, we'll need a
  * __stp_tf_alloc_task_work_for_task(task) variant.
  */
-static struct task_work *__stp_tf_alloc_task_work(void)
+static struct task_work *
+__stp_tf_alloc_task_work(struct stap_task_finder_target *tgt)
 {
        struct __stp_tf_task_work *tf_work;
        unsigned long flags;
@@ -120,6 +122,7 @@ static struct task_work *__stp_tf_alloc_task_work(void)
        }
 
        tf_work->task = current;
+       tf_work->tgt = tgt;
 
        // Insert new item onto list.  This list could be a hashed
        // list for easier lookup, but as short as the list should be
@@ -1205,7 +1208,9 @@ __stp_call_mmap_callbacks_for_task(struct stap_task_finder_target *tgt,
 static void
 __stp_tf_quiesce_worker(struct task_work *work)
 {
-       struct stap_task_finder_target *tgt = work->data;
+       struct __stp_tf_task_work *tf_work = \
+               container_of(work, struct __stp_tf_task_work, work);
+       struct stap_task_finder_target *tgt = tf_work->tgt;
 
        might_sleep();
        __stp_tf_free_task_work(work);
@@ -1287,12 +1292,12 @@ __stp_utrace_task_finder_target_quiesce(u32 action,
 
                /* If we can't sleep, arrange for the task to truly
                 * stop so we can sleep. */
-               work = __stp_tf_alloc_task_work();
+               work = __stp_tf_alloc_task_work(tgt);
                if (work == NULL) {
                        _stp_error("Unable to allocate space for task_work");
                        return UTRACE_RESUME;
                }
-               init_task_work(work, &__stp_tf_quiesce_worker, tgt);
+               stp_init_task_work(work, &__stp_tf_quiesce_worker);
 
                rc = stp_task_work_add(tsk, work);
                /* stp_task_work_add() returns -ESRCH if the task has
@@ -1398,7 +1403,9 @@ __stp_utrace_task_finder_target_syscall_entry(u32 action,
 static void
 __stp_tf_mmap_worker(struct task_work *work)
 {
-       struct stap_task_finder_target *tgt = work->data;
+       struct __stp_tf_task_work *tf_work = \
+               container_of(work, struct __stp_tf_task_work, work);
+       struct stap_task_finder_target *tgt = tf_work->tgt;
        struct __stp_tf_map_entry *entry;
 
        might_sleep();
@@ -1499,14 +1506,14 @@ __stp_utrace_task_finder_target_syscall_exit(u32 action,
 
                /* If we can't sleep, arrange for the task to truly
                 * stop so we can sleep. */
-               work = __stp_tf_alloc_task_work();
+               work = __stp_tf_alloc_task_work(tgt);
                if (work == NULL) {
                        _stp_error("Unable to allocate space for task_work");
                        __stp_tf_remove_map_entry(entry);
                        __stp_tf_handler_end();
                        return UTRACE_RESUME;
                }
-               init_task_work(work, &__stp_tf_mmap_worker, tgt);
+               stp_init_task_work(work, &__stp_tf_mmap_worker);
                rc = stp_task_work_add(tsk, work);
                /* stp_task_work_add() returns -ESRCH if the task has
                 * already passed exit_task_work(). Just ignore this
diff --git a/runtime/linux/task_work_compatibility.h b/runtime/linux/task_work_compatibility.h
new file mode 100644 (file)
index 0000000..0a712db
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * task_work compatibility defines and inlines
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This file is part of systemtap, and is free software.  You can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+#ifndef _TASK_WORK_COMPATIBILITY_H_
+#define _TASK_WORK_COMPATIBILITY_H_
+
+#include <linux/task_work.h>
+
+/*
+ * Define all the old task_work stuff in terms of the new
+ * interface/names - except for the name of the structure
+ * itself. Originally the task_work stuff had a custom structure,
+ * called 'struct task_work'. The new interface uses a common
+ * structure, 'struct callback_head'.  If we define 'callback_head' to
+ * be a 'task_work', then we could never use the common structure on
+ * systems with the old interface.
+ */
+
+#ifdef STAPCONF_TASK_WORK_STRUCT
+
+static inline void
+stp_init_task_work(struct task_work *twork, task_work_func_t func)
+{
+       init_task_work(twork, func, NULL);
+}
+
+#else  /* !STAPCONF_TASK_WORK_STRUCT */
+
+#define task_work callback_head
+
+static inline void
+stp_init_task_work(struct task_work *twork, task_work_func_t func)
+{
+       init_task_work(twork, func);
+}
+
+#endif /* !STAPCONF_TASK_WORK_STRUCT */
+
+#endif /* _TASK_WORK_COMPATIBILITY_H_ */
index b99593e5162e09f531736e7dfc429469efc091af..0590e0c10b0b7054113d64565868df61245719fe 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _STP_TASK_WORK_C
 #define _STP_TASK_WORK_C
 
-#include <linux/task_work.h>
+#include "linux/task_work_compatibility.h"
 
 #if !defined(STAPCONF_TASK_WORK_ADD_EXPORTED)
 typedef int (*task_work_add_fn)(struct task_struct *task,
index face3f9f93827c2b4829e1676b947582c2e807f4..60609e9c3b75582fe706d124c7e90dcba8e4ba59 100644 (file)
@@ -322,7 +322,7 @@ static bool utrace_task_alloc(struct task_struct *task)
                kmem_cache_free(utrace_cachep, utrace);
        }
 
-       init_task_work(&utrace->work, &utrace_resume, NULL);
+       stp_init_task_work(&utrace->work, &utrace_resume);
        return true;
 }
 
This page took 0.104477 seconds and 5 git commands to generate.