让程序跑在特定的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是一个空函数
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是一个空函数
相关文章推荐
- 【C语言】自己编写程序实现strrchr函数,即在给定字符串中找特定的字符并返回最后出现的位置
- JIT动态编译器的原理与实现之实现自己CPU的程序(二)
- 如何利用 任务计划程序 实现计算机重启后运行特定程序(网络方面)
- 编写查找一个单链表特定元素的程序。分别使用递归和非递归方法实现,并比较它们的运行时间。
- Linux下用程序实现统计cpu和内存的利用率
- 将网卡与特定的CPU绑定,提高程序的运行效率
- 写程序+控制cpu占用率-4+绘制CPU使用率的正弦曲线2+C#+实现
- wince系统下用arm汇编实现特定长度的memory拷贝函数,降低系统cpuloading
- windows下实现特定进程在指定的逻辑cpu下运行的方法.
- C# 实现的本地IP地址, 计算机名称, MAC地址 和 硬盘序列号 CPU序列号 的小程序
- C#实现测量程序运行时间及cpu使用时间
- 【C语言】自己编写程序实现strchr函数。即在给定字符串中找特定的字符并返回该处指针。
- java程序实现“搜索文件目录下特定类型的文件"
- C#实现测量程序运行时间及cpu使用时间
- 设置程序占用的CPU运行核数-可以实现别的程序流畅运行
- Parallel Python实现python程序的并行及多cpu多核利用
- C#实现测量程序运行时间及cpu使用时间(转载)
- Parallel Python实现程序的并行多cpu多核利用【pp模块】 推荐
- C#实现测量程序运行时间及cpu使用时间
- C#实现测量程序运行时间及cpu使用时间