kthread/waitqueue/tasklet/set_bit

Softirq 是中断下半部的处理方式 ( 可以在不同 cpu 上同时运行 )
tasklet 是基于 softirq 实现的 , 使用比 softirq 简单 . 能在不同 cpu 上同时运行,但是不同 cpu 可以运行不同的 tasklet .
vk_tasklet_init (& pstDecObj -> stDecTasklet , pstDecObj -> pfnHandleDecodeDone , (unsigned long ) ( pstDecObj -> pstAPUClass ) );
vk_tasklet_kill (& pstDecObj -> stDecTasklet );
vk_tasklet_schedule (& pstDecObj -> stDecTasklet );
void  tasklet_disable ( struct   tasklet_struct  *t);   
/* 函数暂时禁止给定的  tasklet 被  tasklet_schedule   调度,直到这个  tasklet   被再次被 enable ;若这个  tasklet   当前在运行 这个函数忙等待直到这个 tasklet 退出* /  
void  tasklet_disable_nosync ( struct   tasklet_struct  *t);   
/* tasklet_disable 类似,但是 tasklet 可能仍然运行在另一个  CPU */  
void  tasklet_enable ( struct   tasklet_struct  *t);   
/* 使能一个之前被 disable 的  tasklet ; 若这个  tasklet   已经被调度 它会很快运行。  tasklet_enable   tasklet_disable 必须匹配调用 因为内核跟踪每个  tasklet   " 禁止次数 "*/   
void  tasklet_schedule ( struct   tasklet_struct  *t);   
/* 调度  tasklet   执行,如果 tasklet 在运行中被调度 它在完成后会再次运行 这保证了在其他事件被处理当中发生的事件受到应有的注意 这个做法也允许一个  tasklet   重新调度它自己* /  
void  tasklet_hi_schedule ( struct   tasklet_struct  *t);   
/* tasklet_schedule 类似,只是在更高优先级执行。当软中断处理运行时 它处理高优先级  tasklet   在其他软中断之前,只有具有低响应周期要求的驱动才应使用这个函数 可避免其他软件中断处理引入的附加周期* /  
void  tasklet_kill ( struct   tasklet_struct  *t);   
/* 确保了  tasklet   不会被再次调度来运行,通常当一个设备正被关闭或者模块卸载时被调用。如果  tasklet   正在运行 这个函数等待直到它执行完毕。若  tasklet   重新调度它自己,则必须阻止在调用  tasklet_kill   前它重新调度它自己,如同使用  del_timer_sync */


Kthread :
pstClass ->thread= vk_kthread_create ( _ APU_DEC_ProcRoutine , pstClass ," aud_handleProc " );
status= vk_kthread_stop ( pstClass ->thread );
vk_kthread_should_stop ()
vk_wake_up_process ( pstClass ->thread ); 
Kthread 状态:
运行态 ,
可被打断的睡眠状态,
不可被打断的睡眠状态(信号发生时,不会被重新放到运行队列)
停止状态 
僵死状态(进程已经终止,父进程未等待他完成, ( 异常了 )
追踪状态(比如 debug


Linux 内核的等待队列是以双循环链表为基础数据结构,与进程调度机制紧密结合,能够用于实现核心的异步事件通知机制
vk_init_waitqueue_head (&( pstClass -> stWaitQueue ) );

该函数初始化一个已经存在的等待队列头,它将整个队列设置为"未上锁"状态,并将链表指针prevnext指向它自身

if( vk_waitqueue_active (&( pstClass -> stWaitQueue ) ) )       

查看队列中是否有等待线

vk_wake_up_interruptible (&( pstClass -> stWaitQueue ) );

wake_up_interruptible只负责唤醒状态为TASK_INTERRUPTIBLE的进

wake_up函数不仅可以唤醒状态为TASK_UNINTERRUPTIBLE的进程,而且可以唤醒状态为TASK_INTERRUPTIBLE的进

vk_wait_event_interruptible_timeout

vk_wait_event_interruptible( pstClass->stWaitQueue, ( pstClass->u32PermitMask& u32BitMask ) == u32BitMask ); 阻塞等待condition满足

        wait_event_interruptible () 中首先判断 conditon 是不是已经满足,如果是则直接返回 0 ,否则调用 __ wait_event_interruptible () ,并用 __ret 来存放返回值。 __ wait_event_interruptible () 首先将定义并初始化一个 wait_queue_t 变量 __wait ,其中数据为当前进程状态 current struct task_struct ),并把 __wait 加入等待队列。在无限循环中, __ wait_event_interruptible () 将本进程置为可中断的挂起状态,反复检查 condition 是否成 立如 果成立则退出,如果不成立则继续休眠;条件满足后,即把本进程运行状态置为运行态,并把 __wait 从等待队列中清除,从而进程能够调度运行。


挂起的进程并不会自动转入运行的,因此,还需要一个唤醒动作,这个动作由
wake_up_interruptible()完成,它将遍历作为参数传入的lock_wait等待队列,将其中所有的元素(通常都是task_struct)置为运行态,从而可被调度。

       // 与之类似的还有wait_event(),不同点在于wait_event_interruptible()可以被信号唤醒。



__inline__  int   set_bit ( int   nr,int  *  addr

//addr的第nr(nr0-31)位置值置为1;  

__inline__  int   clear_bit ( int  nr,  int  *  addr )  

 //addr的第nr(nr0-31)位置值置为0;   

__inline__  int   test_bit ( int  nr,  int  *  addr
// 判断 addr 的第 nr(nr 0-31) 位置的值是否为 1;  

线程函数里就是 wait + test_bit   

中断Notify set_bit

到之后再clear_bit

test_and_set_bit(int nr, volatilevoid *addr)

test_and_clear_bit




你可能感兴趣的:(kthread/waitqueue/tasklet/set_bit)