让程序跑在特定的cpu上在kernel space的实现

来源:互联网 发布:广州海关数据分中心 编辑:程序博客网 时间:2024/05/16 10:38
如果需要将程序跑在特定的cpu上,可以参考下面的code实现in_interrupt
int my_func_on_cpu(int cpu)
{
int err;
get_online_cpus();
if (!cpu_online(cpu))
err = -EINVAL;
else
if(in_interrupt())
err = work_on_cpu(cpu, __my_func_on_cpu, NULL);
else
smp_call_function_single(cpu, __my_func_on_cpu, &err,
true);
endif
put_online_cpus();
return err;
}
如果确定你的code 是在interrupt context 就用smp_call_function_single。如果跑在thread context就用work_on_cpu,因为work_on_cpu
可能会sleep,所以不能用在interrupt context中.
如果两种环境都有可能跑到就用上面这种方式就可以,即用in_interrupt()函数来确定是否在interrupt context 中.
long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
{
struct work_for_cpu wfc = { .fn = fn, .arg = arg };


INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
schedule_work_on(cpu, &wfc.work);
flush_work(&wfc.work);
destroy_work_on_stack(&wfc.work);
return wfc.ret;
}


work_on_cpu 首先在stack上建议一个work_struct。
#define INIT_WORK_ONSTACK(_work, _func) \
__INIT_WORK((_work), (_func), 1)
我们没有定义CONFIG_LOCKDEP。所以我们走的是else的case
#ifdef CONFIG_LOCKDEP
#define __INIT_WORK(_work, _func, _onstack) \
do { \
static struct lock_class_key __key;\
\
__init_work((_work), _onstack);\
(_work)->data = (atomic_long_t) WORK_DATA_INIT();\
lockdep_init_map(&(_work)->lockdep_map, #_work, &__key, 0); \
INIT_LIST_HEAD(&(_work)->entry);\
(_work)->func = (_func);\
} while (0)
#else
#define __INIT_WORK(_work, _func, _onstack) \
do { \
__init_work((_work), _onstack);\
(_work)->data = (atomic_long_t) WORK_DATA_INIT();\
INIT_LIST_HEAD(&(_work)->entry);\
(_work)->func = (_func);\
} while (0)
#endif


这个workqueue的回调函数是
static void work_for_cpu_fn(struct work_struct *work)
{
struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work);


wfc->ret = wfc->fn(wfc->arg);
}


也就是直接调用用户注册的函数.
其次调用schedule_work_on(cpu, &wfc.work);来运行workqueue
static inline bool schedule_work_on(int cpu, struct work_struct *work)
{
return queue_work_on(cpu, system_wq, work);
}
schedule_work_on 是将我们前面在stack上建立的work_struct 放到system_wq 这个系统已经定义好的workqueue_struct 中来运行.
最后调用flush_work(&wfc.work);来等待wfc.work 执行完成.
由于我们的work_struct是建立在stack上的,因此work_on_cpu 函数返回的时候work_struct 就会被自动销毁
因此在没有定义CONFIG_DEBUG_OBJECTS_WORK来debug的时候destroy_work_on_stack是一个空函数



0 0
原创粉丝点击