#include <linux/configfs.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <asm/hardirq.h>
/*
* The timer example follows
*/
/* This data structure used as "data" for the timer and tasklet functions */
struct jit_data {
struct timer_list timer;
struct tasklet_struct tlet;
int hi; /* tasklet or tasklet_hi */
wait_queue_head_t wait;
unsigned long prevjiffies;
unsigned char *buf;
int loops;
};
#define JIT_ASYNC_LOOPS 10000
void jit_tasklet_fn(unsigned long arg)
{
struct jit_data *data = (struct jit_data *)arg;
unsigned long j = jiffies;
data->buf += sprintf(data->buf, "%9li %3li %i %6i %i %s\n",
j, j - data->prevjiffies, in_interrupt() ? 1 : 0,
current->pid, smp_processor_id(), current->comm);
printk("%9li %3li %i %6i %i %s\n",
j, j - data->prevjiffies, in_interrupt() ? 1 : 0,
current->pid, smp_processor_id(), current->comm);
if (--data->loops) {
data->prevjiffies = j;
if (data->hi)
tasklet_hi_schedule(&data->tlet);
else
tasklet_schedule(&data->tlet);
} else {
kfree(data);
//wake_up_interruptible(&data->wait);
}
}
/* the /proc function: allocate everything to allow concurrency */
int jit_tasklet(char *buf, char **start, off_t offset,
int len, int *eof, void *arg)
{
struct jit_data *data;
char *buf2 = buf;
unsigned long j = jiffies;
long hi = (long)arg;
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
init_waitqueue_head (&data->wait);
/* write the first lines in the buffer */
buf2 += sprintf(buf2, " time delta inirq pid cpu command\n");
buf2 += sprintf(buf2, "%9li %3li %i %6i %i %s\n",
j, 0L, in_interrupt() ? 1 : 0,
current->pid, smp_processor_id(), current->comm);
/* fill the data for our tasklet function */
data->prevjiffies = j;
data->buf = buf2;
data->loops = JIT_ASYNC_LOOPS;
/* register the tasklet */
tasklet_init(&data->tlet, jit_tasklet_fn, (unsigned long)data);
data->hi = hi;
if (hi)
tasklet_hi_schedule(&data->tlet);
else
tasklet_schedule(&data->tlet);
/* wait for the buffer to fill */
//wait_event_interruptible(data->wait, !data->loops);
if (signal_pending(current))
return -ERESTARTSYS;
buf2 = data->buf;
//kfree(data);
*eof = 1;
return buf2 - buf;
}
int __init jit_init(void)
{
create_proc_read_entry("jitasklet", 0, NULL, jit_tasklet, NULL);
create_proc_read_entry("jitasklethi", 0, NULL, jit_tasklet, (void *)1);
return 0; /* success */
}
void __exit jit_cleanup(void)
{
remove_proc_entry("jitasklet", NULL);
remove_proc_entry("jitasklethi", NULL);
}
module_init(jit_init);
module_exit(jit_cleanup);
insmod test.ko
[root@localhost test]# cat /proc/jitasklet
time delta inirq pid cpu command
271843 0 0 3276 1 cat
[root@localhost test]#
[root@localhost test]# cat /proc/kmsg
<4>[ 571.844503] 271844 1 1 7 1 ksoftirqd/1
<4>[ 571.844560] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844570] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844651] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844685] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844694] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844702] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844710] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844718] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844726] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844740] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844748] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844756] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844763] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844771] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844779] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844786] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844794] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844802] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844810] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844818] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844826] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844834] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844842] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844849] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844857] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844865] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844872] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844880] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844888] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844895] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844903] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844911] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844918] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844926] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844934] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844942] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844949] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844957] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844965] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844973] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844980] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844988] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.844996] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845003] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845011] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845018] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845026] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845034] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845042] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845049] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845057] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845065] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845072] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845080] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845087] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845095] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845103] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845111] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845118] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845126] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845134] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845141] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845149] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845214] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845223] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845231] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845239] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845246] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845254] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845263] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845270] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845276] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845276] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845276] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845276] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845276] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845276] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845276] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845276] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845276] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845435] 271844 0 1 7 1 ksoftirqd/1
<4>[ 571.845463] 271845 1 1 7 1 ksoftirqd/1
<4>[ 571.845480] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845488] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845496] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845504] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845511] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845519] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845527] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845535] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845543] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845550] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845558] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845566] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845573] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845581] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845589] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845596] 271845 0 1 7 1 ksoftirqd/1
<4>[ 571.845604] 271845 0 1 7 1 ksoftirqd/1
1.和读进程无关
2.延后执行,延后到什么时间,要看kernel什么时候有空,但最迟也会在下一个时钟滴答里执行(2.6即1ms内)
3.除了执行时间稍微不确定外,和用定时器实现延后执行没多大区
7.5. Tasklets
Tasklets may be run immediately if the system is not under heavy load but never later than the next timer tick.
...
the tasklet is run at the next timer tick as long as the CPU is busy running a process, but it is run immediately when the CPU is otherwise idle.
内核的一个基本原则就是:在中断或者说原子上下文中,内核不能访问用户空间,而且内核是不能睡眠的。 也就是说在这种情况下,内核是不能调用有可能引起睡眠的任何函数。 一般来讲原子上下文指的是在中断或软中断中,以及在持有自旋锁的时候。
refer to
http://hi.baidu.com/juventus/blog/item/ac0e7bec26fc32d42f2e2144.html
于是有个问题,tasklet函数执行在原子上下文,但可以被硬件中断打断,而硬件的中断处理也处于原子上下文,这说明了原子上下文有优先级还是怎么回事呢?
答:tasklet处于原子上下文,但是可以响应中断,但不能被阻塞,即除了因响应中断之外不会有任何理由放弃cpu
但是,
tasklet响应了另外一个中断后,内核怎么调度其返回到原处继续执行呢?