PERCPU: allocation failed, size=256 align=256, failed to allocate new chunk.
Is The amount of space for per CPU allocations limited?
How much percpu-space can I use in Linux kernel module programming?
Now I'm trying to create as many workqueue_struct
as possible. My kernel is 3.10.
My result: I can create about 100000 workqueue_struct
s, then I find error info (same as in the title) when I use the dmesg
command.
My code:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/kthread.h>//kthread_create is_err
#include <linux/slab.h>//kfree
#include <linux/sched.h>//schedule
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/workqueue.h>
u64 i = 0;
static LIST_HEAD(myworkqueuehead);
static struct task_struct *task;
struct MyworkqueueType {
struct list_head entry;
struct workqueue_struct *wq;
u64 number;
};
void myfree(void)
{
struct MyworkqueueType *tempwqtype,*n;
list_for_each_entry_safe(tempwqtype, n, &myworkqueuehead, entry)
{
if(tempwqtype)
{
if(tempwqtype->wq){
//printk("myfree():number=%lld\n",tempwqtype->number);
//printk("list_del()\n");
list_del(&(tempwqtype->entry));
//printk("destroy_workqueue()\n");
destroy_workqueue(tempwqtype->wq);
//printk("free tempwqtypetype:kfree(tempwqtype)\n");
kfree(tempwqtype);
//printk("after free tempwqtypetype\n");
}else{
printk("tempwqtype->wq is null\n");
}
}else{
printk("tempwqtype is null\n");
}
}
printk("has freed all the workqueue space...\n");
}
static int test(void *data)
{
printk("kthread create_wq start to run test()...\n");
while(1)
{
struct MyworkqueueType *myworkqueue;
if(kthread_should_stop())
{
printk("create_wq kthread begin to do myfree()...\n");
myfree();
printk("create_wq kthread stop...\n");
return 0;
}
myworkqueue = kzalloc(sizeof(*myworkqueue), GFP_KERNEL);
if(myworkqueue){
struct workqueue_struct *wq = alloc_workqueue("myworkqueue",0,0);
//struct workqueue_struct *wq = create_workqueue("myworkqueue");
if(!wq)
{
struct MyworkqueueType *mytype;
kfree(myworkqueue);
printk("\ncreate workqueue fail...\n");
mytype = list_entry(myworkqueuehead.prev, struct MyworkqueueType, entry);
printk("current workqueue number=%lld.start to sleep...\n",mytype->number);
msleep(5000);
schedule();
continue;
}
++i;
myworkqueue->number = i;
myworkqueue->wq = wq;
INIT_LIST_HEAD(&myworkqueue->entry);
list_add_tail(&myworkqueue->entry,&myworkqueuehead);
printk("%lld ",i);
}
else
{
printk("\nalloc struct MyworkqueueType fail...\n");
printk("current workqueuenum = %lld",i);
kfree(myworkqueue);
msleep(5000);
schedule();
continue;
}
}
}
static int __init maxwqnum_init(void)
{
printk("-----------maxwqnum-------------\n");
task=kthread_create(test,NULL,"create_wq");
if(IS_ERR(task))
{
printk("create task_struct create_wq fail...\n");
kfree(task);
return 0;
}
printk("create task_struct create_wq success...\n");
wake_up_process(task);
return 0;
}
static void __exit maxwqnum_cleanup(void)
{
kthread_stop(task);
printk("-----------leaving maxwqnum-------------\n");
}
module_init(maxwqnum_init);
module_exit(maxwqnum_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("mjq");
MODULE_DESCRIPTION("just a test!");
MODULE_SUPPORTED_DEVICE("WORKQUEUE");