Hi folks, I am running stable kernel v4.4.110 with preempt-rt patch rt125 on a AM335x non-SMP system. There is one thread with hard realtime requirements running on this system. This thread is scheduled by a hardware interrupt (either AM335x PRUSS or external FPGA). Latencies from interrupt into process are as expected. Interrupt thread prio has been bumped to 90. But I want/need even shorter latencies. So I tried to use IRQF_NO_THREAD in my uio driver to get rid of the scheduling detour through over the interrupt thread. The interrupt handling should be quiet fast - most handling is done in userspace. Here comes the problem. The uio framework uses wake_up_interruptible() in the isr which does not work from hard interrupt handlers. I tried to modify uio.c to use wake_up_process() with a limitation to support a single process having opened the device. This works fine in most cases :-( Userspace uses select() on the device with timeouts. Sometimes my process is woken by interrupt event and sometimes by timeout - fine. But it looks like I am missing some interrupts. I expect some issue with uio poll/waitqueue handling. Any idea how to fix this? It would be fine to stay with poll in the uio drivers. I already thought about a special hrtimer handling in my situation. But I hope about something more pretty. BTW, latencies are shorter with this approach! Matthias diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index bcc1fc0..7eb8257 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -394,8 +394,12 @@ void uio_event_notify(struct uio_info *info) struct uio_device *idev = info->uio_dev; atomic_inc(&idev->event); - wake_up_interruptible(&idev->wait); - kill_fasync(&idev->async_queue, SIGIO, POLL_IN); + if (idev->rt_consumer) { + wake_up_process(idev->rt_consumer); + } else { + wake_up_interruptible(&idev->wait); + kill_fasync(&idev->async_queue, SIGIO, POLL_IN); + } } EXPORT_SYMBOL_GPL(uio_event_notify); @@ -439,6 +443,17 @@ static int uio_open(struct inode *inode, struct file *filep) goto out; } + if (idev->rt_consumer) { + ret = -EBUSY; + goto err_alloc_listener; + } + +#ifdef CONFIG_PREEMPT_RT_FULL + if (idev->info->irq_flags & IRQF_NO_THREAD) { + idev->rt_consumer = current; + } +#endif + listener = kmalloc(sizeof(*listener), GFP_KERNEL); if (!listener) { ret = -ENOMEM; @@ -480,6 +495,7 @@ static int uio_release(struct inode *inode, struct file *filep) struct uio_listener *listener = filep->private_data; struct uio_device *idev = listener->dev; + idev->rt_consumer = NULL; if (idev->info->release) ret = idev->info->release(idev->info, inode); diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h index 32c0e83..cf314da 100644 --- a/include/linux/uio_driver.h +++ b/include/linux/uio_driver.h @@ -73,6 +73,7 @@ struct uio_device { struct uio_info *info; struct kobject *map_dir; struct kobject *portio_dir; + struct task_struct *rt_consumer; }; -- To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html