wait_event可以从不同线程中唤醒两个wake_up_interruptable吗?

时间:2017-06-24 02:10:47

标签: linux kernel

我有从两个来源唤醒一个线程的问题。我的想法是在主线程中,我有一个读取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;
}

感谢。

0 个答案:

没有答案