让程序跑在特定的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是一个空函数
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
- 让程序跑在特定的cpu上在kernel space的实现
- 让Console程序在退出时,调用特定的函数
- linux下让进程运行在指定的cpu上
- linux下让进程运行在指定的cpu上
- linux下让进程运行在指定的cpu上
- linux下让进程运行在指定的cpu上
- 如何让进程运行在指定的cpu上
- windows下实现特定进程在指定的逻辑cpu下运行的方法.
- 在kernel space调用系统调用的例子
- 我在MSN Live 上的Space
- 在VB中如何让线程或进程在指定的CPU上运行
- 让进程运行在指定的CPU
- 为什么要在kernel space 和 user space, 提供一套相同接口的驱动函数
- 如何在kernel中得到cpu的电压和频率
- Windows设置进程在特定CPU上运行
- ajax让返回的内容显示在特定div里
- jquery让返回的内容显示在特定div里
- 让窗口总是出现在某个窗口的特定坐标
- 数据分析分类
- linux设置静态ip
- Leetcode 5. Longest Palindromic Substring
- IL指令汇总
- UML之类图与对象图
- 让程序跑在特定的cpu上在kernel space的实现
- 应用正则表达式判断IP/MAC/DNS合法性
- 为什么有时候在Eclipse中使用ctrl+H搜索,却没有输入框?
- HBase 常用Shell命令
- 我的Python学习路径
- 计算机是如何启动的?
- Axis2 Web服务配置文件services.xml详解
- sqoop1.4.6的安装和配置
- 模式和原则