Which interrupt occurred when I using wait_event_interruptible_timeout? - linux-kernel

How can I know which interrupt break waiting on function wait_event_interruptible_timeout()?
I've got -ERESTARTSYS, but I need to know exectly which one cause return of function.

Related

How to get OUT of an ISR in freertos / esp-idf

I have an ISR that's fired from a button press. The handler looks like this...
void IRAM_ATTR buttonIsrHandler(void *arg) {
xTaskResumeFromISR(buttonTaskHandle);
}
// `buttonTaskHandle` is set up as the handle for this task function...
void buttonTask(void *pvParameter) {
while (1) {
vTaskSuspend(NULL);
// ... my task code goes here...
}
}
When I'm in an ISR, I can't do certain things. For instance, calling ESP_LOGI() results in an error relating to disallowed memory access.
I was expecting those limitations to exist only within the buttonIsrHandler() function, but they also exist within buttonTask() given that I woke it up from an ISR.
How do I get out of an ISR so that I can do all my normal stuff? I could use something like a queue to do this, but that seems heavy weight. Is there an easier way? Would sending a task-notification from the ISR handler be any different? Any other suggestions?
As you can see in the documentation of xTaskResumeFromISR, such a use case is not recommended. Task notifications are designed and optimized for this exact use case. In your case, you'd want to use vTaskNotifyGiveFromISR.
As for "leaving the ISR", FreeRTOS will not call your task function from the ISR context. xTaskResumeFromISR and other functions simply update the state of the task so that it can run when its turn comes.

Basic question about UART RXCn flag (AVR)

I got stuck in the interrupt part while learning AVR.
Datasheet says about RXCn flag:
"This flag bit is set when there are unread data in the receive buffer and cleared when the receive buffer is empty
(i.e., does not contain any unread data)."
and there is an example about getting a characters with uart
while ( !(UCSRnA & (1<<RXCn)) );
/* Get and return received data from buffer */
return UDRn;
Will it wait here forever until the data comes from the Uart? And will mcu not be able to do any other work because of "while(1);"?
I know this method is polling and I also know that there is an interrupt method but will the mcu be locked because of this?
As #AterLux already said the program will halt until data is recived there are some other possibilities to catch the data nonblocking e.g.:
char uart_get(char *data)
{
if (UCSRnA & (1<<RXCn) );
{
*data = UDRn;
return 1;
}
return 0;
}
If no data has been received you will get 0 and can continue with the program. If you should use interrupt handling or polling depends on your problem. With interrupt handling you can use for example a circular buffer to save received data and use it if you need it. if you are still waiting for one value polling is also an oppertunity.
Yes. It will wait forever while the condition (!(UCSRnA & (1<<RXCn))) is fulfiled. I.e. it will wait until UCSRnA has the bit RXCn set.
If the Global Interrupt Flag (I flag in SREG register) is not cleared (by calling cli(), or entering an interrupt handler) then interrupts still able to run, all the peripherals (counters, SPI, TWI, etc) continue to work, while in this cycle. Of course the program beneath the cycle will not execute.

program calling Sleep doesn't wakup on signals

In Linux when an executing thread calling 'sleep' suspends its execution. As soon as a signal is sent to the process the 'sleep' function returns immediately. I can install my signal handler and set the flag below properly to exit the while loop.
// a signal handler set 'flag' on CTRL-C
while(flag) {
sleep(10); // returns on signal caught
}
In Windows I cannot see that. I am using 'Sleep(DWORD milliseconds)' and I have installed my signal handler using 'signal' function. Essentially the sleeping threads resumes only at the end of 'Sleep'.
What do I have to do to allow 'Sleep' to return before hand in my code?
Am I using the right approach (using a flag to exit the while loop) or do I have to look at something else?
You should be using an event object.
Replace your loop with a call to WaitForSingleObject, and have the control-C handler call SetEvent.
(Of course, in practice it is unlikely that you really want your program to sit and wait, doing nothing, until the user presses control-C. But that's the scenario the question presents, and this answer gives you a starting point for more realistic scenarios.)

How do I check if a goroutine is created successfully?

In Go, go is the keyword to spawn a goroutine. However, it seems the keyword doesn't return any value, so how could I detect if the goroutine is spawned correctly?
It seems Go uses the following ways to check whether a func is successful or not.
value, err = myFunc(value)
Is there a similar usage for the go keyword to detect a creation error? It seems go will throw a runtime exception if it failed.
I want to make a test to find out the maximum number of goroutine I could create for a CPU.
As you already know:
value, err = myFunc(value)
is the idiomatic way to handle exceptions by returning the built-in error type. In a way you can compare it to a checked exception, I guess. In your case though, failing to spawn a new goroutine is more of a runtime exception. How golang handles those is by using panics. You can handle them in your code with the built-in recover() function, which will try to regain control of the execution flow. Without that the panic will go up the stack until it crashes the program.
Notice that recover() has to be called in a function which is being defered, those functions are pushed into a list and are always called at the end of the function in which they were defered - so even when the panic occurs they will be called, allowing you to call recover(). If you just try to call recover() at the end of your function (or well anywhere after you panicking subfunction) the execution will never reach it. If you can handle the panic (recover() doesn't return an err) so that your program can actually continue it will execute from the point where the function that threw the panic was.
Think the above blog post is enough but if you need more examples just comment here.
Also your system will most probably be bounded by RAM memory rather than CPU.
A goroutine creation is (more or less) just a memory allocation. You cannot in general catch memory allocation exceptions and it's the same with goroutines.
If your program runs out of memory, there's usually nothing you can do about it beyond quitting and restarting.
If the function you are using a go routine that returns an error, you can instead call go on an anonymous function and handle the error in the anonymous function.
go func() {
value, err := myFunc()
}()

NULL pointer dereference in swiotlb_unmap_sg_attrs() on disk IO

I'm getting an error I really don't understand when reading or writing files using a PCIe block device driver. I seem to be hitting an issue in swiotlb_unmap_sg_attrs(), which appears to be doing a NULL dereference of the sg pointer, but I don't know where this is coming from, as the only scatterlist I use myself is allocated as part of the device info structure and persists as long as the driver does.
There is a stacktrace to go with the problem. It tends to vary a bit in exact details, but it always crashes in swiotlb_unmap_sq_attrs().
I think it's likely I have a locking issue, as I am not sure how to handle the locks around the IO functions. The lock is already held when the request function is called, I release it before the IO functions themselves are called, as they need an (MSI) IRQ to complete. The IRQ handler updates a "status" value, which the IO function is waiting for. When the IO function returns, I then take the lock back up and return to request queue handling.
The crash happens in blk_fetch_request() during the following:
if (!__blk_end_request(req, res, bytes)){
printk(KERN_ERR "%s next request\n", DRIVER_NAME);
req = blk_fetch_request(q);
} else {
printk(KERN_ERR "%s same request\n", DRIVER_NAME);
}
where bytes is updated by the request handler to be the total length of IO (summed length of each scatter-gather segment).
It turned out this was due to re-entrancy of the request function. Because I was unlocking in the middle to allow IRQs to come in, the request function could be called again, would take the lock (while the original request handler was waiting on IO) and then the wrong handler would get the IRQ and everything went south with stacks of failed IO.
The way I solved this was to set a "busy" flag at the start of the request function, clear it at the end and return immediately at the start of the function if this is set:
static void mydev_submit_req(struct request_queue *q){
struct mydevice *dev = q->queuedata;
// We are already processing a request
// so reentrant calls can take a hike
// They'll be back
if (dev->has_request)
return;
// We own the IO now, new requests need to wait
// Queue lock is held when this function is called
// so no need for an atomic set
dev->has_request = 1;
// Access request queue here, while queue lock is held
spin_unlock_irq(q->queue_lock);
// Perform IO here, with IRQs enabled
// You can't access the queue or request here, make sure
// you got the info you need out before you release the lock
spin_lock_irq(q->queue_lock);
// you can end the requests as needed here, with the lock held
// allow new requests to be processed after we return
dev->has_request = 0;
// lock is held when the function returns
}
I am still not sure why I consistently got the stacktrace from swiotlb_unmap_sq_attrs(), however.

Resources