runtime/stp_task_work.c - systemtap
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
#ifndef _STP_TASK_WORK_C
#define _STP_TASK_WORK_C
#include "linux/task_work_compatibility.h"
#if !defined(STAPCONF_TASK_WORK_ADD_EXPORTED)
typedef typeof(&task_work_add) task_work_add_fn;
#define task_work_add (* (task_work_add_fn)kallsyms_task_work_add)
typedef typeof(&task_work_cancel) task_work_cancel_fn;
#define task_work_cancel (* (task_work_cancel_fn)kallsyms_task_work_cancel)
#endif
static atomic_t stp_task_work_callbacks = ATOMIC_INIT(0);
static int
stp_task_work_init(void)
{
#if !defined(STAPCONF_TASK_WORK_ADD_EXPORTED)
kallsyms_task_work_add = (void *)kallsyms_lookup_name("task_work_add");
if (kallsyms_task_work_add == NULL) {
_stp_error("Can't resolve task_work_add!");
return -ENOENT;
}
kallsyms_task_work_cancel = (void *)kallsyms_lookup_name("task_work_cancel");
if (kallsyms_task_work_cancel == NULL) {
_stp_error("Can't resolve task_work_cancel!");
return -ENOENT;
}
#endif
return 0;
}
static void
stp_task_work_exit(void)
{
while (atomic_read(&stp_task_work_callbacks))
schedule_timeout_uninterruptible(1);
return;
}
static int
stp_task_work_add(struct task_struct *task, struct task_work *twork)
{
int rc;
rc = task_work_add(task, twork, true);
if (rc == 0)
atomic_inc(&stp_task_work_callbacks);
return rc;
}
static struct task_work *
stp_task_work_cancel(struct task_struct *task, task_work_func_t func)
{
struct task_work *twork;
twork = task_work_cancel(task, func);
if (twork != NULL)
atomic_dec(&stp_task_work_callbacks);
return twork;
}
static void
stp_task_work_func_done(void)
{
atomic_dec(&stp_task_work_callbacks);
}
#endif