LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices


Reply
  Search this Thread
Old 07-29-2015, 06:36 PM   #1
david_8274
Member
 
Registered: Jun 2013
Location: California
Distribution: Ubuntu, Fedora
Posts: 75

Rep: Reputation: Disabled
Getting hardware interrupt in user-space program


Hi,

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?

Thanks,
Wei Xu
 
Old 07-30-2015, 12:56 PM   #2
smallpond
Senior Member
 
Registered: Feb 2011
Location: Massachusetts, USA
Distribution: Fedora
Posts: 4,123

Rep: Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260
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?
 
Old 07-30-2015, 01:56 PM   #3
david_8274
Member
 
Registered: Jun 2013
Location: California
Distribution: Ubuntu, Fedora
Posts: 75

Original Poster
Rep: Reputation: Disabled
@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
 
Old 08-01-2015, 07:39 AM   #4
smallpond
Senior Member
 
Registered: Feb 2011
Location: Massachusetts, USA
Distribution: Fedora
Posts: 4,123

Rep: Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260Reputation: 1260
Then use fork or threads.
 
Old 08-01-2015, 07:55 AM   #5
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
Quote:
Originally Posted by david_8274 View Post
@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).
 
Old 08-03-2015, 10:29 AM   #6
david_8274
Member
 
Registered: Jun 2013
Location: California
Distribution: Ubuntu, Fedora
Posts: 75

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by jpollard View Post
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.

Thank you !
Wei
 
Old 08-03-2015, 10:54 AM   #7
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,599
Blog Entries: 4

Rep: Reputation: 3905Reputation: 3905Reputation: 3905Reputation: 3905Reputation: 3905Reputation: 3905Reputation: 3905Reputation: 3905Reputation: 3905Reputation: 3905Reputation: 3905
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.
 
Old 08-03-2015, 11:07 AM   #8
david_8274
Member
 
Registered: Jun 2013
Location: California
Distribution: Ubuntu, Fedora
Posts: 75

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by sundialsvcs View Post
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?

Thanks,
Wei
 
Old 08-03-2015, 11:52 AM   #9
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
Quote:
Originally Posted by david_8274 View Post
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.

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).
 
Old 08-03-2015, 01:14 PM   #10
david_8274
Member
 
Registered: Jun 2013
Location: California
Distribution: Ubuntu, Fedora
Posts: 75

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by jpollard View Post
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).

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.

Please provide with your feedback.

Thank you very much.

Wei
 
Old 08-03-2015, 04:52 PM   #11
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
Quote:
Originally Posted by david_8274 View Post
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.

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.
 
Old 08-03-2015, 05:14 PM   #12
david_8274
Member
 
Registered: Jun 2013
Location: California
Distribution: Ubuntu, Fedora
Posts: 75

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by jpollard View Post
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.

"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?

Thank you again,

Wei
 
Old 08-04-2015, 04:31 AM   #13
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
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.
 
Old 08-04-2015, 07:36 AM   #14
shekharrana
LQ Newbie
 
Registered: Sep 2006
Location: bangalore, IN
Posts: 6

Rep: Reputation: 1
Hi david_8274, can u share how u made it work?

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.

Regards
 
Old 08-04-2015, 09:39 AM   #15
david_8274
Member
 
Registered: Jun 2013
Location: California
Distribution: Ubuntu, Fedora
Posts: 75

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by jpollard View Post
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
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Getting hardware interrupt in user-space program david_8274 Linux - Newbie 1 07-29-2015 08:56 PM
[SOLVED] Catch LPT interrupt in user space. LEICIF Linux - Newbie 9 06-25-2011 11:15 AM
Mechanism for interrupt report to user space zvivered Linux - Embedded & Single-board computer 0 08-11-2009 03:59 PM
how to trensfer data from user space to interrupt handler? rose_hatami Programming 4 12-19-2007 05:17 AM
can interrupt handler call user space function? pot_po Programming 0 11-07-2002 09:32 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel

All times are GMT -5. The time now is 05:41 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration