您的位置:首页 > 其它

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

2017-01-24 09:50 330 查看
如果需要将程序跑在特定的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是一个空函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐