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

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.

Related

Synchronization primitives in DriverKit

In a DriverKit extension, I would like to block a call from a user client until a specific hardware interrupt fires. Since there are no semaphores available (Does the DriverKit SDK support semaphores?), I've reached for a very basic spinlock using an _Atomic(bool) member and busy waiting:
struct IVars
{
volatile _Atomic(bool) InterruptOccurred = false;
}
// In the user client method handler
{
// Clear the flag
atomic_store(&ivars->InterruptOccurred, false);
// Set up the interrupt on the device
...
// Wait for the interrupt
while (!atomic_load(&ivars->InterruptOccurred))
{
IOSleep(10);
}
}
// In the interrupt handler
{
bool expected = false;
if (atomic_compare_exchange_strong(&ivars->InterruptOccurred, &expected, true))
{
return;
}
// Proceed with normal handling if the user client method is not waiting
}
The user client method is called infrequently and the interrupt is guaranteed to fire within 100ms, so in principle busy waiting should be acceptable, but I am not very happy with the solution. I haven't worked with spinlocks before and they make me feel rather uneasy.
I would like to avoid taking an IOLock in the interrupt handler. Is there any other synchronization primitive in DriverKit I could reach for? I guess a cleaner way to handle this would be for the user client method to accept a callback that fires on the interrupt, but that would still require synchronization with the interrupt handler and would complicate the client application code.
Preliminaries
I would like to avoid taking an IOLock in the interrupt handler.
I assume you're aware that, this being DriverKit, this isn't running in the context of a primary interrupt controller, but you're already behind a layer of Mach messaging, kernel/user context switch, and IODispatchQueue serialisation?
Possible solutions:
Since there are no semaphores available[…]
OSAction
The OSAction class contains a set of methods for sleeping in a thread until the action is invoked. (WillWait/Wait/EndWait) This might be a feasible way of implementing what you're trying to do. As usual, the documentation is in the header/iig file but hasn't made it into the web-based API docs.
IODispatchQueue
As of DriverKit 21 (macOS 12), you also get Apple's simpler Sleep/Wakeup event system baked into IODispatchQueue, which you might be familiar with from the kernel. (It is also similar to pthreads condition variables.) Note you need to create the queue with the kIODispatchQueueReentrant option in this case.
From DriverKit 22 (macOS 13/iPadOS) on, there's also a version with a deadline for the sleep SleepWithDeadline.
Async callbacks
I guess a cleaner way to handle this would be for the user client method to accept a callback that fires on the interrupt, but that would still require synchronization with the interrupt handler and would complicate the client application code.
If you're happy calling the async callback in the app on every interrupt, there's not really any synchronisation needed, you can just invoke the same OSAction repeatedly. Even if you want to only invoke the async call on the "next" interrupt, atomic compare-and-swap should be sufficient for the interrupt handler to claim the OSAction* pointer.
Important note:
With all of these potential solutions except IODispatchQueue::Sleep and the async callback: bear in mind that sleeping in the context of a user client external method will block the dispatch queue and thus any other calls to external methods in that user client will fail to make progress. (As well as any other methods scheduled to that queue.)

Allow-listing IP addresses using `call.cancel()` from within `EventListener.dnsEnd()` in OkHttp

i am overriding the dnsEnd() function in EventListener:
#Override
public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
inetAddressList.forEach(address -> {
logger.debug("checking if url ({}) is in allowlist", address.toString());
if (!allowlist.contains(address)) {
call.cancel();
}
});
}
i know, in the documentation it says not to alter call parameters etc:
"All event methods must execute fast, without external locking, cannot throw exceptions, attempt to mutate the event parameters, or be re-entrant back into the client. Any IO - writing to files or network should be done asynchronously."
but, as i don't care about the call if it is trying to get to an address outside the allowlist, i fail to see the issue with this implementation.
I want to know if anyone has experience with this, and why it may be an issue?
I tested this and it seems to work fine.
This is fine and safe. Probably the strangest consequence of this is the canceled event will be triggered by the thread already processing the DNS event.
But cancelling is not the best way to constrain permitted IP addresses to a list. You can instead implement the Dns interface. Your implementation should delegate to Dns.SYSTEM and them filter its results to your allowlist. That way you don't have to worry about races on cancelation.

How does another program/process interrupt the execution of my program?

Lets say I have written a very simple program in an operating system which supports UI. My program looks like below:-
#include <os_specific_ui.h>
int main()
{
// Create a button using os specific API
object my_button = add_button("I am a button");
// Register for a mouse down call back on that button
mouse_down_handler = register_mouse_down_cb(my_button, func_to_be_called_on_mouse_down);
// do something...
// have a lot of functions which keep calling each other for a long period of time
}
void func_to_be_called_on_mouse_down(void)
{
print("my_button got clicked");
}
The program is clearly a single threaded program. When I run it, it keeps on doing something. In the mean time if there is a mouse down event, then callback registered for it will get hit and start executing.
I want to know how can another process (which handles mouse movements) can call a function in my process? And what happens to the state of my process when such a callback is hit. I mean my program was doing something when callback was hit. So it just stops doing that and starts executing callback or what? And what after the callback function finishes executing? Does my program go back to do whatever it was doing before callback was hit?
Pretty much all GUI programs run some form of event/main loop. That is, as the last part in main() it enters a loop, which reads events from the OS, and dispatches those events to your callback handlers and performs other tasks to realize the GUI.
i.e. the code you have in // have a lot of functions which keep calling each other just isn't possible unless you do that in a separate thread. Your own execution flow isn't stopped and taken over by some other process.
A GUI program is more or less done like this:
#include <os_specific_ui.h>
void func_to_be_called_on_mouse_down(void)
{
print("my_button got clicked");
}
int main()
{
// Create a button using os specific API
object my_button = add_button("I am a button");
// Register for a mouse down call back on that button
mouse_down_handler = register_mouse_down_cb(my_button, func_to_be_called_on_mouse_down);
for (;;) {
Event e
read_event_from_OS(&e);
handle_event(&e);
}
}
Where read_event_from_OS() fetches mouse/keyboard/redraw/etc. events from the operating system, and handle_event() figures out what to do with that event, such as redraw a window, or call one of the callback functions that your program has registered.
If the OS you're working on does things differently, you'll have to tell us more about it

Windows Phone Mutex issue

I made some researches about mutexes, but could not find anything to worth to clarify what I want as much as I can understand. I can use mutexes on linux easily. But I don't know why my mutexes won't work on my application. I also looked for some examples, and implemented it. But no way;
Here is my mutex initilaziation;
public static Mutex mutex = new Mutex(true,"mut");
Here I used my mutex to lock;
private void button4_Click(object sender, RoutedEventArgs e) //Challenge Start/Stop
{
StartLocationService(GeoPositionAccuracy.High);
mutex.WaitOne();
mutex.WaitOne();
MessageBox.Show("I'm in mutex");
///...
}
I did this just to see if mutex is cared by my application. But no ways, my application shows "IM in mutex" message without getting any release signal from somewhere. Normally, there must be a deadlock, but no.
What I'm trying to do is, before StartLocationService fully completed, I don't want the message to appear. I also tried mutex.ReleaseMutex(); within end of StartLocationService function. But it did not work too.
I wish semaphores had existed in WP.
Please help me; Thanks
You have no deadlock because you passed 'true' for the first parameter of the Mutex, which means that the mutex is initially owned by the thread who created it. That is, your main thread.
For your example, what you must do is set the constructor's parameter to False, then call mutex.WaitOne(). This should effectively block your main thread. Then, call mutex.ReleaseMutex() at the end of the StartLocationService method.
Now that's for the theory. I wouldn't recommend you to do that, because the main thread is the UI thread. It means that the UI will become unresponsive until the location service has finished initializing, which is awful UX. You should rather display some kind of loading screen, and hide it at the end of the StartLocationService method.
Note that you can use a ManualResetEvent instead of a mutex. The end result will be the same, but it might be a tad more intuitive to use.

Can someone explain callback/event firing

In a previous SO question it was recommended to me to use callback/event firing instead of polling. Can someone explain this in a little more detail, perhaps with references to online tutorials that show how this can be done for Java based web apps.
Thanks.
The definition of a callback from Wikipedia is:
In computer programming, a callback is
executable code that is passed as an
argument to other code. It allows a
lower-level software layer to call a
subroutine (or function) defined in a
higher-level layer.
In it's very basic form a callback could be used like this (pseudocode):
void function Foo()
{
MessageBox.Show("Operation Complete");
}
void function Bar(Method myCallback)
{
//Perform some operation
//When completed execute the callback method
myCallBack().Invoke();
}
static int Main()
{
Bar(Foo); //Pops a message box when Bar is completed
}
Modern languages like Java and c# have a standardized way of doing this and they call it events. An event is simply a special type of property added to a class that contains a list of Delegates / Method Pointers / Callbacks (all three of these things are the same thing. When the event gets "fired" it simply iterates through it's list of callbacks and executes them. These are also referred to as listeners.
Here's an example
public class Button
{
public event Clicked;
void override OnMouseUp()
{
//User has clicked on the button. Let's notify anyone listening to this event.
Clicked(); //Iterates through all the callbacks in it's list and calls Invoke();
}
}
public class MyForm
{
private _Button;
public Constructor()
{
_Button = new Button();
//Different languages provide different ways of registering listeners to events.
// _Button.Clicked += Button_Clicked_Handler;
// _Button.Clicked.AddListener(Button_Clicked_Handler);
}
public void Button_Clicked_Handler()
{
MessageBox.Show("Button Was Clicked");
}
}
In this example the Button class has an event called Clicked. It allows anyone who wants to be notified when is clicked to register a callback method. In this case the "Button_Clicked_Handler" method would be executed by Clicked event.
Eventing/Callback architecture is very handy whenever you need to be notified that something has occurred elsewhere in the program and you have no direct knowledge of when or how this happens.
This greatly simplifies notification. Polling makes it much more difficult because you are responsible for checking every so often whether or not an operation has completed. A simple polling mechanism would be like this:
static void CheckIfDone()
{
while(!Button.IsClicked)
{
//Sleep
}
//Button has been clicked.
}
The problem is that this particular situation would block your existing thread and have to continue checking until Button.IsClicked is true. The nice thing about eventing architecture is that it is asynchronous and let's the Acting Item (button) notify the listener when it is completed instead of the listener having to keep checking,
The difference between polling and callback/event is simple:
Polling: You are asking, continuously or every fixed amount of time, if some condition is meet, for example, if some keyboard key have been pressed.
Callback: You say to some driver, other code or whatever: When something happens (the keyboard have been pressed in our example), call this function, and you pass it what function you want to be called when the event happens. This way, you can "forget" about that event, knowing that it will be handled correctly when it happens.
Callback is when you pass a function/object to be called/notified when something it cares about happens. This is used a lot in UI - A function is passed to a button that is called whenever the button is pressed, for example.
There are two players involved in this scenario. First you have the "observed" which from time to time does things in which other players are interested. These other players are called "observers". The "observed" could be a timer, the "observers" could be tasks, interested in alarm events.
This "pattern" is described in the book "Design Patterns, Elements of Reusable Object-Oriented Software" by Gamma, Helm, Johnson and Vlissides.
Two examples:
The SAX parser to parse XML walks
trough an XML file and raises events
each time an element is encountered.
A listener can listen to these
elements and do something with it.
Swing and AWT are based on this
pattern. When the user moves the
mouse, clicks or types something on
the keyboard, these actions are
converted into events. The UI
components listen to these
events and react to them.
Being notified via an event is almost always preferable to polling, especially if hardware is involved and that event originates from a driver issuing a CPU interrupt. In that case, you're not using ANY cpu at all while you wait for some piece of hardware to complete a task.

Resources