Working with the 'task_finder' layer

Overview

The task_finder layer is supposed to do one thing - find "interesting" tasks. Currently, "interesting" is defined by matching either a pathname or pid. There are plans to add wildcard matching at some point in the future to the pathnames.

The task_finder layer is supposed to find "interesting" tasks for callers - what the caller does with the task after that is up to the caller.

Setup

First, callers need to declare a stap_task_finder_target for each process you are interested in. The stap_task_finder_target structure is defined at the top of task_finder.c, and it looks like this:

struct stap_task_finder_target {
/* private: */
        struct list_head list;          /* __stp_task_finder_list linkage */
        struct list_head callback_list_head;
        struct list_head callback_list;
        struct utrace_engine_ops ops;
        int engine_attached;
        size_t pathlen;

/* public: */
        const char *pathname;
        pid_t pid;
        stap_task_finder_callback callback;
        stap_task_finder_vm_callback vm_callback;
};

Callers are interested in the 4 public fields. If you are interested in a particular pid, set pathname to NULL and the pid to the correct pid. If you are interested in a path, set pathname appropriately and set pid to 0. In both cases you'll need to define a callback routine for the task_finder_target (which will be discussed a bit later). Ignore the vm_callback for now.

Once the stap_task_finder_target has been defined, you should pass it to a call to stap_register_task_finder_target().

Once all the stap_task_finder_target's have been registered, stap_start_task_finder() should be called to start everything up.

Operation

When the task_finder layer finds an interesting thread, it will call the associated callback. The callback's signature looks like this:

typedef int (*stap_task_finder_callback)(struct task_struct *tsk,
                                         int register_p,
                                         int process_p,
                                         struct stap_task_finder_target *tgt);

Here's a description of each parameter.

'tsk' identifies the interesting thread

'register_p' will be set to 1 if the task_finder has found a match. At this point the caller can do some setup on the thread, such as attaching a utrace engine, attaching a uprobe, etc. 'register_p' will be set to 0 if the thread is going away and the caller needs to cleanup anything attached to the thread.

'process_p' will be set to 1 if the thread is a process, 0 otherwise.

'tgt' is the associated stap_task_finder_target structure you passed to stap_register_task_finder_target()

Shutdown

At systemtap shutdown time, stap_stop_task_finder() must be called to allow the task_finder layer to disconnect from all the threads on the system.

Implementation

Internally the task_finder layer works by attaching a utrace engine to watch UTRACE_EVENT(CLONE) and UTRACE_EVENT(EXEC) events to every non-kernel thread in the system. It looks at existing threads and monitors all new threads (by following the CLONE/EXEC events), looking for pid/path matches. When it finds a match, it notifies the upper layer by calling the callback (and attaches a UTRACE_EVENT(DEATH) engine). When the matched thread dies, it notifies the upper layer by calling the callback.

None: TaskFinder (last edited 2008-07-02 20:49:47 by DavidSmith)