Linux kernel driver: IRQ triggered or timeout - linux

In a linux kernel driver, I would like to repeat indefinitely the following sequence:
at time T, a hardware IRQ is enabled
between time T and T + "around" 15ms, the IRQ callback can be reached if the IRQ is triggered. I say around because I'm not using an RT kernel and if it's 14 or 16ms, it's fine. In the IRQ callback, I need to write down get cpu_clock(0) and call wake_up_interruptible. The timeout needs to be killed. The whole process needs to be started again within 5ms.
if by T + "around" 15ms, the IRQ has not been triggered, I need to execute some other code. The IRQ should be disabled then. The whole process needs to be started again within 5ms.
Therefore, by T + "around" 20ms, in worst case, the whole process needs to be started again.
Note that if the IRQ is physically triggered at 18ms, too bad, "I missed the train". I will catch another hardware trigger at the next sequence.
While testing, I was doing something along the following pseudo-code:
INIT_DELAYED_WORK(&priv->work, driver_work);
INIT_DELAYED_WORK(&priv->timeout, driver_timeout);
request_irq(priv->irq, driver_interrupt, IRQF_TRIGGER_RISING, "my_irq", priv);
then:
queue_delayed_work(priv->workq, &priv->work, 0ms);
static void driver_work(struct work_struct *work) {
queue_delayed_work(priv->workq, &priv->timeout, 15ms);
priv->interruptCalled = 0;
enable_irq(priv->irq);
}
Then:
static irqreturn_t driver_interrupt(int irq, void *_priv) {
disable_irq_nosync(priv->irq);
priv->interruptCalled = 1;
cancel_delayed_work(&priv->timeout);
priv->stamp = cpu_clock(0);
wake_up_interruptible(&driver_wait);
queue_delayed_work(priv->workq, &priv->work, 5ms);
return IRQ_HANDLED;
}
And:
static void driver_timeout(struct work_struct *work) {
if (priv->interruptCalled == 0) {
disable_irq_nosync(priv->irq);
//Do other small cleanup
queue_delayed_work(priv->workq, &priv->work, 5ms);
}
}
I'm trying to write a robust but simple driver. Is this a proper implementation? How can I improve this implementation?

Answering my own question: the problem is that queue_delayed_work is based on jiffies. Or 5ms is not possible as HZ=100 (1 jiffy = 10ms). HR timer brought a good solution.

Related

change while(1) loop to busy wait in linux kernel

void cpu_idle (void)
{
/* endless idle loop with no priority at all */
while (1) {
void (*idle)(void) = pm_idle;
if (!idle)
idle = default_idle;
if (!current->need_resched)
idle();
schedule();
check_pgt_cache();
}
}
this code existed in : "arch/i386/kernel/process.c" related to linux 2.4.18-14
this code is responsable of the ( cpu idle loop ).
the question is : can I change the while(1) loop with bust wait ?
The loop here properly schedules processes so the system continues to run properly. Switching to a pure busy wait would lock up the system when the cpu goes idle, meaning other processes would cease to be scheduled. You definitely do not want that.

Linux External Event Handling - IRQ vs. Polling kthread

I am porting a device driver from QNX to Linux. In QNX, the old driver used a pthread with an infinite loop to monitor for the occurrence of an interrupt, rather than registering a true interrupt handler. To try to demonstrate the efficacy of using register_irq() instead of a dedicated polling thread, I wrote two drivers in Linux. The relevant code for each is shown below and the question is at the bottom.
IRQ
Write the handler
irqreturn_t timing_interrupt_handler(int irq, void *dev_id) {
u32 test;
/* read device interrupt command/status register */
test = ioread32(timing_card[3].base);
/* sanity check that the device reported the interrupt */
if ( test & (1 << 2) ) {
/* clear interrupt status */
iowrite32( 0x0d, timing_card[3].base);
/* toggle digital output line */
test = ioread32(timing_card[2].base);
if ( test & 0x01 )
iowrite32(test & ~0x1, timing_card[2].base);
else
iowrite32(test | 0x1, timing_card[2].base);
}
return IRQ_HANDLED;
}
Register the handler
rc = request_irq(irq_line, timing_interrupt_handler,
IRQF_SHARED, "timing", timing_card);
if ( rc ) {
printk(KERN_ALERT "Failed to register irq %d\n", irq_line);
return rc;
}
POLLING THREAD
Write the thread function
int poll_irq(void *data) {
u32 test;
/* until module unload */
while ( !kthread_should_stop() ) {
/* read device interrupt command/status register */
test = ioread32(timing_card[3].base);
/* sanity check that the device reported the interrupt */
if ( test & (1 << 2) ) {
/* clear interrupt status */
iowrite32( 0x0d, timing_card[3].base);
/* toggle digital output line */
test = ioread32(timing_card[2].base);
if ( test & 0x01 )
iowrite32(test & ~0x1, timing_card[2].base);
else
iowrite32(test | 0x1, timing_card[2].base);
}
else
usleep_range(9, 11);
}
return 0;
}
Begin the thread
kthread = kthread_create(poll_irq, 0x0, "poll_IRQ_test");
wake_up_process(kthread);
THE QUESTION
When I put two traces on an oscilloscope - one monitoring the card's digital input (which would trigger the interrupt) and one monitoring the card's digital output (which would react to the interrupt) I can measure the reaction time to an event.
The first "proper" method, registering an IRQ, takes approximately 80 microseconds.
The second method, running an infinite thread, takes approximately 15-30 microseconds.
What gives? The benefit of the first is that it doesn't waste as much processing power, but why does response time suffer so dramatically? How bad is it, really, to have this polling thread? How could one go about investigating and eventually demonstrating the extra toll the polling thread puts on the CPU?
Thanks for your time!
Best
Scott
The interrupt response time is affected by the time your system (whatever it is) needs to deliver the interrupt, and by the time your CPU (whatever it is) needs to wake up from some power-saving sleeping mode.
The polling thread eats both CPU time and power.
To measure them, use something like top or powertop, or measure the power consumption directly on the hardware.

How to kill a thread from another thread in vala

I have a main thread which creates another thread to perform some job.
main thread has a reference to that thread. How do I kill that thread forcefully some time later, even if thread is still operating. I cant find a proper function call that does that.
any help would be appreciable.
The original problem that I want to solve is I created a thread a thread to perform a CPU bound operation that may take 1 second to complete or may be 10 hours. I cant predict how much time it is going to take. If it is taking too much time, I want it to gracefully abandon the job when/ if I want. can I somehow communicate this message to that thread??
Assuming you're talking about a GLib.Thread, you can't. Even if you could, you probably wouldn't want to, since you would likely end up leaking a significant amount of memory.
What you're supposed to do is request that the thread kill itself. Generally this is done by using a variable to indicate whether or not it has been requested that the operation stop at the earliest opportunity. GLib.Cancellable is designed for this purpose, and it integrates with the I/O operations in GIO.
Example:
private static int main (string[] args) {
GLib.Cancellable cancellable = new GLib.Cancellable ();
new GLib.Thread<int> (null, () => {
try {
for ( int i = 0 ; i < 16 ; i++ ) {
cancellable.set_error_if_cancelled ();
GLib.debug ("%d", i);
GLib.Thread.usleep ((ulong) GLib.TimeSpan.MILLISECOND * 100);
}
return 0;
} catch ( GLib.Error e ) {
GLib.warning (e.message);
return -1;
}
});
GLib.Thread.usleep ((ulong) GLib.TimeSpan.SECOND);
cancellable.cancel ();
/* Make sure the thread has some time to cancel. In an application
* with a UI you probably wouldn't need to do this artificially,
* since the entire application probably wouldn't exit immediately
* after cancelling the thread (otherwise why bother cancelling the
* thread? Just exit the program) */
GLib.Thread.usleep ((ulong) GLib.TimeSpan.MILLISECOND * 150);
return 0;
}

lio_listio: How to wait until all requests complete?

In my C++ program, i use the lio_listio call to send many (up to a few hundred) write requests at once. After that, I do some calculations, and when I'm done I need to wait for all outstanding requests to finish before I can submit the next batch of requests. How can I do this?
Right now, I am just calling aio_suspend in a loop, with one request per call, but this seems ugly. It looks like I should use the struct sigevent *sevp argument to lio_listio. My current guess is that I should do something like this:
In the main thread, create a mutex and lock it just before the call to lio_listio.
In the call to lio_listio, specify a notification function / signal handler that unlocks this mutex.
This should give me the desired behavior, but will it work reliably? Is it allowed to manipulate mutexes from the signal handler context? I read that pthread mutexes can provide error detection and fail with if you try to lock them again from the same thread or unlock them from a different thread, yet this solution relies on deadlocking.
Example code, using a signal handler:
void notify(int, siginfo_t *info, void *) {
pthread_mutex_unlock((pthread_mutex_t *) info->si_value);
}
void output() {
pthread_mutex_t iomutex = PTHREAD_MUTEX_INITIALIZER;
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_sigaction = &notify;
act.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1, &act, NULL);
for (...) {
pthread_mutex_lock(&iomutex);
// do some calculations here...
struct aiocb *cblist[];
int cbno;
// set up the aio request list - omitted
struct sigevent sev;
memset(&sev, 0, sizeof(struct sigevent));
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGUSR1;
sev.sigev_value.sival_ptr = &iomutex;
lio_listio(LIO_NOWAIT, cblist, cbno, &sev);
}
// ensure that the last queued operation completes
// before this function returns
pthread_mutex_lock(&iomutex);
pthread_mutex_unlock(&iomutex);
}
Example code, using a notification function - possibly less efficient, since an extra thread is created:
void output() {
pthread_mutex_t iomutex = PTHREAD_MUTEX_INITIALIZER;
for (...) {
pthread_mutex_lock(&iomutex);
// do some calculations here...
struct aiocb *cblist[];
int cbno;
// set up the aio request list - omitted
struct sigevent sev;
memset(&sev, 0, sizeof(struct sigevent));
sev.sigev_notify = SIGEV_THREAD;
sev_sigev_notify_function = &pthread_mutex_unlock;
sev.sigev_value.sival_ptr = &iomutex;
lio_listio(LIO_NOWAIT, cblist, cbno, &sev);
}
// ensure that the last queued operation completes
// before this function returns
pthread_mutex_lock(&iomutex);
pthread_mutex_unlock(&iomutex);
}
If you set the sigevent argument in the lio_listio() call, you will be notified with a signal (or function call) when all the jobs in that one particular call completes. You would still need to:
wait until you receive as many notifications as you have made lio_listio() calls, to know when they're all done.
use some safe mechanism to communicate from your signal handler to your main thread, probably via a global variable (to be portable).
If you're on linux, I would recommend tying an eventfd to your sigevent instead and wait on that. That's a lot more flexible since you don't need to involve signal handlers. On BSD (but not Mac OS), you can wait on aiocbs using kqueue and on solaris/illumos you can use a port to get notified of aiocb completions.
Here's an example of how to use eventfds on linux:
As a side note, I would use caution when issuing jobs with lio_listio. You're not guaranteed that it supports taking more than 2 jobs, and some systems have very low limits of how many you can issue at a time. Default on Mac OS for instance is 16. This limit may be defined as the AIO_LISTIO_MAX macro, but it isn't necessarily. In which case you need to call sysconf(_SC_AIO_LISTIO_MAX) (see docs). For details, see the lio_listio documentation.
You should at least check error conditions from your lio_listio() call.
Also, your solution of using a mutex is sub-optimal, since you will synchronize each loop in the for loop, and just run one at a time (unless it's a recursive mutex, but in that case its state could be corrupt if your signal handler happens to land on a different thread).
A more appropriate primitive may be a semaphore, which is released in the handler, and then (after your for loop) acquired the same number of times as you looped, calling lio_listio(). But, I would still recommend an eventfd if it's OK to be linux specific.

Does Arduino support threading?

I have a couple of tasks to do with arduino but one of them takes very long time, so I was thinking to use threads to run them simultaneously.
I have an Arduino Mega
[Update]
Finally after four years I can install FreeRTOS in my arduino mega. Here is a link
In short: NO.
But you may give it a shot at:
http://www.kwartzlab.ca/2010/09/arduino-multi-threading-librar/
(Archived version: https://web.archive.org/web/20160505034337/http://www.kwartzlab.ca/2010/09/arduino-multi-threading-librar
Github: https://github.com/jlamothe/mthread
Not yet, but I always use this Library with big projects:
https://github.com/ivanseidel/ArduinoThread
I place the callback within a Timer interrupt, and voilá! You have pseudo-threads running on the Arduino...
Just to make this thread more complete: there are also protothreads which have very small memory footprint (couple bytes if I remember right) and preserve variables local to thread; very handy and time saving (far less finite state machines -> more readable code).
Examples and code:
arduino-class / ProtoThreads wiki
Just to let you know what results you may expect: serial communication # 153K6 baudrate with threads for: status diodes blinking, time keeping, requested functions evaluation, IO handling and logic and all on atmega328.
Not real threading but TimedActions are a good alternative for many uses
http://playground.arduino.cc/Code/TimedAction#Example
Of course, if one task blocks, the others will too, while threading can let one task freeze and the others will continue...
No you can't but you can use Timer interrupt.
Ref : https://www.teachmemicro.com/arduino-timer-interrupt-tutorial/
The previous answer is correct, however, the arduino generally runs pretty quick, so if you properly time your code, it can accomplish tasks more or less simultaneously.
The best practice is to make your own functions and avoid putting too much real code in the default void loop
You can use arduinos
It is designed for Arduino environment. Features:
Only static allocation (no malloc/new)
Support context switching when delaying execution
Implements semaphores
Lightweight, both cpu and memory
I use it when I need to receive new commands from bluetooth/network/serial while executing the old ones and the old ones have delay in them.
One thread is the sever thread that does the following loop:
while (1) {
while ((n = Serial.read()) != -1) {
// do something with n, like filling a buffer
if (command_was_received) {
arduinos_create(command_func, arg);
}
}
arduinos_yield(); // context switch to other threads
}
The other is the command thread that executes the command:
int command_func(void* arg) {
// move some servos
arduinos_delay(1000); // wait for them to move
// move some more servos
}
Arduino does not support multithread programming.
However there have been some workarounds, for example the one in this project (you can install it also from the Arduino IDE).
It seems you have to define the schedule time yourself while in a real multithread environment it is the OS that decides when to execute tasks.
Alternatively you can use protothreads
The straight answer is No No No!. There are some alternatives but you can't expect a perfect multi threading functionality from an arduino mega. You can use arduino due or lenado for multithreading like below-
void loop1(){
}
void loop2(){
}
void loop3(){
}
Normally, I handle those types of cases in backend. You can run the main code in a server while using Arduino to just collect inputs and show outputs. In such cases I would prefer nodemcu which has built in wifi.
Thread NO!
Concurrent YES!
You can run different tasks concurrently with FreeRTOS library.
https://www.arduino.cc/reference/en/libraries/freertos/
void TaskBlink( void *pvParameters );
void TaskAnalogRead( void *pvParameters );
// Now set up two tasks to run independently.
xTaskCreate(
TaskBlink
, (const portCHAR *)"Blink" // A name just for humans
, 128 // Stack size
, NULL
, 2 // priority
, NULL );
xTaskCreate(
TaskAnalogRead
, (const portCHAR *) "AnalogRead"
, 128 // This stack size can be checked & adjusted by reading Highwater
, NULL
, 1 // priority
, NULL );
void TaskBlink(void *pvParameters) // This is a task.
{
(void) pvParameters;
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
for (;;) // A Task shall never return or exit.
{
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
}
}
void TaskAnalogRead(void *pvParameters) // This is a task.
{
(void) pvParameters;
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
for (;;)
{
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
Serial.println(sensorValue);
vTaskDelay(1); // one tick delay (15ms) in between reads for stability
}
}
Just take care!
When different tasks tried to reach variables at the same time, like i2c communication line or sd card module. Use Semaphores and mutexes
https://www.geeksforgeeks.org/mutex-vs-semaphore/.
Arduino does not supports threading. However, you can do the next best thing and structure your code around state machines running in interleaving.
While there are lots of ways to implement your tasks as state machines, I recommend this library (https://github.com/Elidio/StateMachine). This library abstracts most of the process.
You can create a state machine as a class like this:
#include "StateMachine.h"
class STATEMACHINE(Blink) {
private:
int port;
int waitTime;
CREATE_STATE(low);
CREATE_STATE(high);
void low() {
digitalWrite(port, LOW);
*this << &STATE(high)<< waitTime;
}
void high() {
digitalWrite(port, HIGH);
*this << &STATE(low)<< waitTime;
}
public:
Blink(int port = 0, int waitTime = 0) :
port(port),
waitTime(waitTime),
INIT_STATE(low),
INIT_STATE(high)
{
pinMode(port, OUTPUT);
*this << &STATE(low);
}
};
The macro STATEMACHINE() abstracts the class inheritances, the macro CREATE_STATE() abstracts the state wrapper creation, the macro INIT_STATE() abstracts method wrapping and the macro STATE() abstracts state wrapper reference within the state machine class.
State transition is abstracted by << operator between the state machine class and the state, and if you want a delayed state transition, all you have to do is to use that operator with an integer, where the integer is the delay in millisseconds.
To use the state machine, first you have to instantiate it. Declaring an reference to the class in global space while instantiating it with new on setup function might do the trick
Blink *led1, *led2, *led3;
void setup() {
led1 = new Blink(12, 300);
led2 = new Blink(11, 500);
led3 = new Blink(10, 700);
}
Then you run the states on loop.
void loop() {
(*led2)();
(*led1)();
(*led3)();
}

Resources