我有从两个来源唤醒一个线程的问题。我的想法是在主线程中,我有一个读取sysfs条目的函数。这是一个块读。读取功能如下:
static bool read_wait;
static ssize_t mode_read(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct st_data *st = (struct st_data *)dev_get_drvdata(dev);
wait_event(st->pollq, read_wait);
read_wait = false;
init_waitqueue_head(&st->pollq);
return snprintf(buf, 100, "%d\n", st->source);
}
在中断处理程序中,我有这段代码:
static irqreturn_t irq_handler(int irq, void *dev_id)
{
struct st_data *st = (struct st_data *)dev_id;
read_wait = true;
st->source = 1;
wake_up_interruptible(&st->pollq);
return IRQ_HANDLED;
}
然后我有另一个sysfs条目,它有一个像这样的写函数:
static ssize_t wakeup_mode_write(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct st_data *st = (struct st_data *)dev_get_drvdata(dev);
read_wait = true;
st->source = 2;
wake_up_interruptible(&st->pollq);
return len;
}
这个想法是在线程正在读取并等待读取sysfs函数mode_read时,有两个线程可以将其唤醒。它可能是中断。中断可以将其唤醒。或者可以从上层发出命令。此命令将写入sysfs条目并将其唤醒。
但是,我发现只有irq可以唤醒它。如果我通过sysfs条目向wakeup_mode_write
发出命令,它不会将其唤醒并挂在那里。任何人都可以帮我解决这个问题吗?
以下是探测功能:
static DEVICE_ATTR(_curr_mode, S_IRUGO, mode_read, NULL);
static DEVICE_ATTR(_wakeup_mode, S_IWUSR, NULL, wakeup_mode_write);
static struct attribute *inv_fp_attributes[] = {
&dev_attr__curr_mode.attr,
&dev_attr__wakeup_mode.attr,
NULL,
};
static struct attribute_group inv_fp_group = {
.name = NULL, /* put in device directory */
.attrs = inv_fp_attributes,
};
static int inv_fp_probe(struct platform_device *pdev)
{
struct st_data *st;
int error = 0;
st = kzalloc(sizeof(struct st_data), GFP_KERNEL);
if (!st) {
return -ENOMEM;
}
platform_set_drvdata(pdev, st);
st->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
error = request_threaded_irq(st->irq, inv_irq_handler,
NULL,
IRQF_TRIGGER_RISING | IRQF_SHARED, "inv_fp_irq",
st);
if (error) {
goto err_class_create;
}
st->class = class_create(THIS_MODULE, DRV_CLASS_NAME);
if (IS_ERR(st->class)) {
error = PTR_ERR(inv_fp->class);
goto err_class_create;
}
error = alloc_chrdev_region(&st->devno, 0, 1, DRV_NAME);
if (error < 0) {
goto err_alloc_chrdev;
}
st->device = device_create(st->class, NULL, st->devno,
NULL, "%s", DRV_NAME);
if (IS_ERR(st->device)) {
error = PTR_ERR(st->device);
goto err_device_create;
}
cdev_init(&st->cdev, &inv_fp_fops);
st->cdev.owner = THIS_MODULE;
error = cdev_add(&st->cdev, st->devno, 1);
if (error) {
goto err_inv_fp_init_instance;
}
dev_set_drvdata(st->device, inv_fp);
error = sysfs_create_group(&st->device->kobj, &inv_fp_group);
if (error < 0) {
pr_err("add_sysfs_interfaces failed.\n");
goto err_inv_fp_init_instance;
}
st->new_data = 0;
st->enabled = 0;
init_waitqueue_head(&st->pollq);
st->dev = &pdev->dev;
return 0;
}
感谢。