wait_queue_head_t & wait_queue_t使用
文件:Linux/drivers/mtd/mtdchar.c +526
case MEMERASE: //Nand擦除IOCTL
case MEMERASE64:
{
struct erase_info *erase;
if(!(file->f_mode & FMODE_WRITE))
return -EPERM;
erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
if (!erase)
ret = -ENOMEM;
else {
wait_queue_head_t waitq; //定义等待队列头
DECLARE_WAITQUEUE(wait, current); //声明等待队列
init_waitqueue_head(&waitq); //初始化等待队列头
if (cmd == MEMERASE64) {
struct erase_info_user64 einfo64;
if (copy_from_user(&einfo64, argp,
sizeof(struct erase_info_user64))) {
kfree(erase);
return -EFAULT;
}
erase->addr = einfo64.start;
erase->len = einfo64.length;
} else {
struct erase_info_user einfo32;
if (copy_from_user(&einfo32, argp,
sizeof(struct erase_info_user))) {
kfree(erase);
return -EFAULT;
}
erase->addr = einfo32.start;
erase->len = einfo32.length;
}
erase->mtd = mtd;
erase->callback = mtdchar_erase_callback; //定义擦除唤醒的callback函数
erase->priv = (unsigned long)&waitq; //将等待队列的地址作为参数传递
/*
FIXME: Allow INTERRUPTIBLE. Which means
not having the wait_queue head on the stack.
If the wq_head is on the stack, and we
leave because we got interrupted, then the
wq_head is no longer there when the
callback routine tries to wake us up.
*/
ret = mtd->erase(mtd, erase);
if (!ret) {
set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&waitq, &wait); //将当前进程加入等待队列
if (erase->state != MTD_ERASE_DONE &&
erase->state != MTD_ERASE_FAILED)
schedule(); //判断擦除是否完成,没有的话睡眠,知道callback函数唤醒该进程
remove_wait_queue(&waitq, &wait);
set_current_state(TASK_RUNNING);
ret = (erase->state == MTD_ERASE_FAILED)?-EIO:0;
}
kfree(erase);
}
break;
-------------------------------------------------------------------------------
static void mtdchar_erase_callback (struct erase_info *instr)
{
wake_up((wait_queue_head_t *)instr->priv);
}
文件:linux/drivers/mtd/nand/nand_base.c +2495
int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
int allowbbt)
{
......
/* Do call back function */
if (!ret)
mtd_erase_callback(instr); //唤醒睡眠进程
......
}
nanjing