Linux - KernelThis forum is for all discussion relating to the Linux kernel.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I am working on an embedded Linux project. In the project, I wish to get a GPIO interrupt in my user-space program. I read about using UIO to get kernel interrupt from user-space. However, it seems that I will have to do a blocking call, such as read(), poll(), to wait for interrupt happens. But I don't want to block and wait. Is there a solution would let my program act like a bare-metal project, where I attach an interrupt handler to the system and free to preform other tasks until an interrupt happens and the program jumps to the ISR?
User programs are living in a different address space than the kernel and are not guaranteed to be memory-resident. How would the interrupt handler transfer control to your program except through a system call?
@smallpond thaks for the reply.
Yes I understand the dilemma here. Since event is common in embedded system, how should we usually deal with this situation? Is polling (or similar mechanism) from the user-space program the only way to discover a hardware interrupt? I have read some article about using the UIO subsystem, but it seems to rely on a blocking call ( read(), poll() or select()), but I don't want to block my program, I want to be able to do something else and gets notified about an interrupt real time.
@smallpond thaks for the reply.
Yes I understand the dilemma here. Since event is common in embedded system, how should we usually deal with this situation? Is polling (or similar mechanism) from the user-space program the only way to discover a hardware interrupt? I have read some article about using the UIO subsystem, but it seems to rely on a blocking call ( read(), poll() or select()), but I don't want to block my program, I want to be able to do something else and gets notified about an interrupt real time.
Thanks,
Wei
I think it will depend on the driver. Normal drivers don't do that. They handle the interrupt and dismiss it. It also depends on the platform (x86 has ways to map the device registers into userspace, but that doesn't guarantee interrupts).
If you are writing the driver, it may be possible to get the driver to pass the interrupt as a signal... but note: signals are SLOW as compaired to a wakeup.
It usually much more efficient (and safer) to use threads, then have a thread wait for the interrupt via a blocking read. After all, this is equivalent to what the interrupt service routine has to do anyway - to respond to an interrupt requires the system to allocate a context frame on the interrupt stack, then go to the interupt. The thread just sets up that context ahead of time and then waits for the interrupt...
The advantage for threads is that the processing of the interrupt can be MUCH larger (it also has a variable sized stack, can easily allocate gobs of memory - much more than the kernel).
I think it will depend on the driver. Normal drivers don't do that. They handle the interrupt and dismiss it. It also depends on the platform (x86 has ways to map the device registers into userspace, but that doesn't guarantee interrupts).
If you are writing the driver, it may be possible to get the driver to pass the interrupt as a signal... but note: signals are SLOW as compaired to a wakeup.
It usually much more efficient (and safer) to use threads, then have a thread wait for the interrupt via a blocking read. After all, this is equivalent to what the interrupt service routine has to do anyway - to respond to an interrupt requires the system to allocate a context frame on the interrupt stack, then go to the interupt. The thread just sets up that context ahead of time and then waits for the interrupt...
The advantage for threads is that the processing of the interrupt can be MUCH larger (it also has a variable sized stack, can easily allocate gobs of memory - much more than the kernel).
Hi @jpollard,
Thank you for the reply.
If I create a thread (call it thread_1) and implement a blocking read, the program flow would be like:
>>context switching to thread_1, wait for interrupt for a time slice.
>>context switching to other threads.
>>context switching to thread_1, wait for interrupt for a time slice.
>>context switching to other threads.
>>context switching to thread_1, wait for interrupt for a time slice.
>>context switching to other threads.
:
:
:
To me, even though within thread_1 it looks like 'real time' (waiting for interrupt), but overall the context switching makes it look like polling to me. Isn't it somewhat contradict the concept of interrupt? It might be the most efficient way to get interrupt in user-space, but it seems a bit awkward to me. Please correct me if I am wrong.
The interrupt is "the ringing telephone." The interrupt handler doesn't have to "pick up the phone and talk," and it usually doesn't. Instead, the interrupt handler causes the appropriate user-space (or kernel) process/thread to become runnable. (So, it consumes no CPU time until the interrupt comes in, and yet, "it can't miss it.") The user-space program might read from the device or what-have-you.
The interrupt is "the ringing telephone." The interrupt handler doesn't have to "pick up the phone and talk," and it usually doesn't. Instead, the interrupt handler causes the appropriate user-space (or kernel) process/thread to become runnable. (So, it consumes no CPU time until the interrupt comes in, and yet, "it can't miss it.") The user-space program might read from the device or what-have-you.
@sundialsvcs
Agree. Having said that, in embedded system we often require "real time" response ("pick up the phone and talk"), correct? I understand that I may put all the code with real-time requirement in driver, but the GPL policy is my major concern. I was hoping to find the fastest way for user-space program to respond to an interrupt, so I don't have to put my proprietary code in the kernel.
So to you, is creating a blocking read thread the most efficient way?
Thank you for the reply.
If I create a thread (call it thread_1) and implement a blocking read, the program flow would be like:
>>context switching to thread_1, wait for interrupt for a time slice.
>>context switching to other threads.
>>context switching to thread_1, wait for interrupt for a time slice.
>>context switching to other threads.
>>context switching to thread_1, wait for interrupt for a time slice.
>>context switching to other threads.
:
:
:
To me, even though within thread_1 it looks like 'real time' (waiting for interrupt), but overall the context switching makes it look like polling to me. Isn't it somewhat contradict the concept of interrupt? It might be the most efficient way to get interrupt in user-space, but it seems a bit awkward to me. Please correct me if I am wrong.
Thank you !
Wei
Wrong approach.
This is what was done with lightweight threads - all context control done by the application. and that causes multiple context switches - one for process itself, plus another for the lightweight switch...
With threads:
Code:
>context switching to thread_1, wait for completion
>alternate threads processing...
>>thread 1 wakes from sleep and resumes
>alternate threads continues...
>>thread 1 waits for completion
>alternate threads continue
And if you have a multi-core processor, even the compute activity between threads is done in parallel.
With your lightweight thread, you only get ONE context, which you then have to switch around to whichever task you want processed. Slow (been there done that).
This is what was done with lightweight threads - all context control done by the application. and that causes multiple context switches - one for process itself, plus another for the lightweight switch...
With threads:
Code:
>context switching to thread_1, wait for completion
>alternate threads processing...
>>thread 1 wakes from sleep and resumes
>alternate threads continues...
>>thread 1 waits for completion
>alternate threads continue
And if you have a multi-core processor, even the compute activity between threads is done in parallel.
With your lightweight thread, you only get ONE context, which you then have to switch around to whichever task you want processed. Slow (been there done that).
Hi @jpollard,
Thank you for your reply. However, there are a few places I found a bit confusing, which might due to ambiguous terminologies. Let me re-phase my implementation description, please again see if I am taking the correct approach.
>I create my Main_application.c user-space program.
>Within Main_application.c, I create, let's say, two threads, thread_1 and thread_2. (I guess a user-space thread is equivalent to a light-weight process (LWP) from a kernel perspective, again please correct me if I am wrong).
>In thread_1, all it does is doing a blocking read call to wait for interrupt from a specific hardware peripheral, let's say a button(utilize the UIO subsystem).
>In thread_2, I implement other system tasks, such as changing display, blinking LEDs.
>If someone press the button, thread_1 needs to come back from the blocking read call and perform certain action (let's say displaying a special screen).
So I guess the flow of my Main_application.c user-space program would be:
>>Main_application.c start exectuing
>>thread_1 is created.
>>thread_2 is created.
>>context switching to thread_1, wait for interrupt for a time slice.
>>Time slice for thread_1 is up, context switching to thread_2.
>>Time slice for thread_2 is up, context switching to thread_1, wait for interrupt for a time slice.
>>Time slice for thread_1 is up, context switching to thread_2.
>>Time slice for thread_2 is up, context switching to thread_1, wait for interrupt for a time slice.
>>Time slice for thread_1 is up, context switching to thread_2.
>>Time slice for thread_2 is up, context switching to thread_1, wait for interrupt for a time slice.
:
:
:
>>Time slice for thread_1 is up, context switching to thread_2.
>>During the time slice for thread_2, someone presses the button. Kernel driver code handles the interrupt, and inform user-space code about the interrupt through UIO subsystem.
>>Time slice for thread_2 is up, context switching to thread_1, wait for interrupt for a time slice.
>>thread_1 gets the interrupt and gets out of the blocking read call. It calls its handler to display a special screen. After task done, rearm interrupt.
>>Time slice for thread_1 is up, context switching to thread_2.
>>Time slice for thread_2 is up, context switching to thread_1, wait for interrupt for a time slice.
:
:
:
This is, I guess, as you mentioned, the context switching is handled by the application and it's 'leightweight', since the program stays within the same memory space.
Thank you for your reply. However, there are a few places I found a bit confusing, which might due to ambiguous terminologies. Let me re-phase my implementation description, please again see if I am taking the correct approach.
>I create my Main_application.c user-space program.
>Within Main_application.c, I create, let's say, two threads, thread_1 and thread_2. (I guess a user-space thread is equivalent to a light-weight process (LWP) from a kernel perspective, again please correct me if I am wrong).
>In thread_1, all it does is doing a blocking read call to wait for interrupt from a specific hardware peripheral, let's say a button(utilize the UIO subsystem).
>In thread_2, I implement other system tasks, such as changing display, blinking LEDs.
>If someone press the button, thread_1 needs to come back from the blocking read call and perform certain action (let's say displaying a special screen).
So I guess the flow of my Main_application.c user-space program would be:
>>Main_application.c start exectuing
>>thread_1 is created.
>>thread_2 is created.
>>context switching to thread_1, wait for interrupt for a time slice.
>>Time slice for thread_1 is up, context switching to thread_2.
>>Time slice for thread_2 is up, context switching to thread_1, wait for interrupt for a time slice.
>>Time slice for thread_1 is up, context switching to thread_2.
>>Time slice for thread_2 is up, context switching to thread_1, wait for interrupt for a time slice.
>>Time slice for thread_1 is up, context switching to thread_2.
>>Time slice for thread_2 is up, context switching to thread_1, wait for interrupt for a time slice.
:
:
:
>>Time slice for thread_1 is up, context switching to thread_2.
>>During the time slice for thread_2, someone presses the button. Kernel driver code handles the interrupt, and inform user-space code about the interrupt through UIO subsystem.
>>Time slice for thread_2 is up, context switching to thread_1, wait for interrupt for a time slice.
>>thread_1 gets the interrupt and gets out of the blocking read call. It calls its handler to display a special screen. After task done, rearm interrupt.
>>Time slice for thread_1 is up, context switching to thread_2.
>>Time slice for thread_2 is up, context switching to thread_1, wait for interrupt for a time slice.
:
:
:
This is, I guess, as you mentioned, the context switching is handled by the application and it's 'leightweight', since the program stays within the same memory space.
Please provide with your feedback.
Thank you very much.
Wei
Not quite.
If you are using the pthread library (as you should), each thread is a process - they just happen to share the code, heap, and bss. The stack space is unique for each one.
As a full thread, there is no designated context switching required. Especially in a multi-core environment. When the interrupt is handled, the corresponding task is resumed... and without other activity, the same CPU will resume executing the task.
And none of that affects how the other thread is being processed. As long as the other thread has computation to do, it will not be disturbed.
There is no "switch context and wait for interrupt...". There is no purpose to changing the context just to wait. That does nothing but waste CPU time.
If you are using the pthread library (as you should), each thread is a process - they just happen to share the code, heap, and bss. The stack space is unique for each one.
As a full thread, there is no designated context switching required. Especially in a multi-core environment. When the interrupt is handled, the corresponding task is resumed... and without other activity, the same CPU will resume executing the task.
And none of that affects how the other thread is being processed. As long as the other thread has computation to do, it will not be disturbed.
There is no "switch context and wait for interrupt...". There is no purpose to changing the context just to wait. That does nothing but waste CPU time.
"There is no "switch context and wait for interrupt...". There is no purpose to changing the context just to wait. That does nothing but waste CPU time."
--- if the blocking read is in thread_1, doesn't the user-space program have to first go back to thread_1 before the blocking read gets the interrupt? If the program doesn't do context switching constantly, how does thread_1 gets the interrupt?
Not necessarily. That would depend on the other loads on the system. If the general load on the system is sufficient to use the CPU, then a context switch to that other load would occur - after all, the CPU is idle.
But that does not have to involve thread_2/main thread at all.
The only time a context MUST change is in a since CPU core situation. Even in that case, it is more efficient for the kernel to do the context changes than it is for the application to have to manage it.
u can make thread_1 (lwp) wait in kernel space by making a blocking read/ioctl call. In that read/ioctl, use wake_event_interruptible(waitqueue) to put the thread_1 into waiting queue, and from ISR u can wake_up_interruptible(waitqueue).
This standard approach works like charm.
there wont be any polling kinda with thread_1 as it would be in WAITING state.
Not necessarily. That would depend on the other loads on the system. If the general load on the system is sufficient to use the CPU, then a context switch to that other load would occur - after all, the CPU is idle.
But that does not have to involve thread_2/main thread at all.
The only time a context MUST change is in a since CPU core situation. Even in that case, it is more efficient for the kernel to do the context changes than it is for the application to have to manage it.
@jpollard
Hi, Let's discuss in the context of a single core CPU because the system I am working on is a single core. So in a single core case if I create thread_1 and thread_2, the context switching would happen (managed by kernel) as I described, correct?
Thanks,
Wei
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.