New event behaviour while busy

Discussions and support about ChibiOS/RT, the free embedded RTOS.
law
Posts: 12
Joined: Tue Jan 12, 2016 5:20 am
Been thanked: 1 time

New event behaviour while busy

Postby law » Wed Sep 25, 2024 6:02 am

Hi All,

Hopefully a quick question:
Say I have a thread waiting on an event with (eg) chEvtWaitAny().
An event occurs and the thread starts to do some work.
If another event occurs while the thread is still working, what is the expected outcome?
Will the event be dropped?

Thanks

User avatar
Giovanni
Site Admin
Posts: 14565
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1112 times
Been thanked: 937 times
Contact:

Re: New event behaviour while busy

Postby Giovanni » Wed Sep 25, 2024 6:36 am

Hi,

The event is buffered, as soon the thread re-enters chEvtWaitAny() it will be immediately served.

The only scenario where an event is "lost" is when an event is broadcasted twice while the thread is executing, only one is buffered. Note that this is by design, it is the same event so one notification is sufficient.

Giovanni

law
Posts: 12
Joined: Tue Jan 12, 2016 5:20 am
Been thanked: 1 time

Re: New event behaviour while busy

Postby law » Thu Sep 26, 2024 1:23 am

Hi Giovanni,
Excellent! Thank you for you help.

law
Posts: 12
Joined: Tue Jan 12, 2016 5:20 am
Been thanked: 1 time

Re: New event behaviour while busy

Postby law » Mon Sep 30, 2024 2:45 am

Hi again Giovanni,

If from my event worker thread I need to register a new event, is it acceptable to simply call chEvtBroadcastFlags from the worker thread?
My worker thread has a condition where say event_1 is registered from an external source.
The worker thread processes event_1, but determines that there is more event_1 related work to do.
I don't want to simply sit in a loop and check if that particular worker has more to do. I want to register an event, so that any other unrelated event might also be processed.

A code example of what I think I want:

Code: Select all

while(1) {
   chEvtWaitAny(EVENT_MASK(0));
   eventflags_t flags = chEvtGetAndClearFlags(&listener);
   
   if (flags & event_1) {
      if (do_event_1_work() == true) {
         // More event_1 work to do
         chEvtBroadcastFlags(&event_source, (eventflags_t)event_1);
      }
   }
   if (flags & event_2) {
      // process event_2, etc etc
   }
}


A code example of what I don't want:

Code: Select all

while(1) {
   chEvtWaitAny(EVENT_MASK(0));
   eventflags_t flags = chEvtGetAndClearFlags(&listener);
   
   if (flags & event_1) {
      bool more_work = false;
      do {
         more_work = do_event_1_work();
      } while (more_work == true);
   }
   if (flags & event_2) {
      // process event_2, etc etc
   }
}


Do you have any thoughts on this?

Thank

User avatar
FXCoder
Posts: 393
Joined: Sun Jun 12, 2016 4:10 am
Location: Sydney, Australia
Has thanked: 184 times
Been thanked: 131 times

Re: New event behaviour while busy

Postby FXCoder » Tue Oct 01, 2024 1:00 am

Hi,
Unless you need to notify other subscriber threads (if any) listening to the event source, then simply use a direct thread add to post your "more to do" event.
Then your code can process other events flags (if any) and then pickup the newly posted event flag at the top of the loop.
See...

Code: Select all

chEvtAddEvents(events)


--
Bob

law
Posts: 12
Joined: Tue Jan 12, 2016 5:20 am
Been thanked: 1 time

Re: New event behaviour while busy

Postby law » Tue Oct 01, 2024 2:11 am

Hey, That is great - thanks very much

law
Posts: 12
Joined: Tue Jan 12, 2016 5:20 am
Been thanked: 1 time

Re: New event behaviour while busy

Postby law » Tue Oct 01, 2024 2:34 am

Hi again,
On further investigation, chEvtAddEvents(events) would add an event.
I also need to broadcast a flag for the event.
Can you offer any advice on how to do that too?

I could reach into the event_listener struct and OR the flags myself. Would this be considered an acceptable Chibios way of doing things?!
It seems a bit hacky to me!

Code: Select all

while(1) {
   chEvtWaitAny(EVENT_MASK(0));
   eventflags_t flags = chEvtGetAndClearFlags(&listener);
   
   if (flags & event_1) {
      if (do_event_1_work() == true) {
         // More event_1 work to do
         listener.flags |= (eventflags_t)event_1;
         chEvtAddEvents(EVENT_MASK(0));
      }
   }
   if (flags & event_2) {
      // process event_2, etc etc
   }
}


Thanks again

User avatar
FXCoder
Posts: 393
Joined: Sun Jun 12, 2016 4:10 am
Location: Sydney, Australia
Has thanked: 184 times
Been thanked: 131 times

Re: New event behaviour while busy

Postby FXCoder » Tue Oct 01, 2024 4:13 am

OK. The terminology may be a little confusing.
What the worker thread gets is a flag set in its own thread bitmask.
There is no need to do more than that.

However, if you need other subscribers to get the event then just use the broadcast API (as you originally described).
You'll need the event source object address available to your worker thread to do that of course (a global or an API to get the address as part of your system).
Then when you broadcast to that event source all subscribers (including the worker_1 which initiated the broadcast) will get the event added to their thread event flags.

--
Bob

law
Posts: 12
Joined: Tue Jan 12, 2016 5:20 am
Been thanked: 1 time

Re: New event behaviour while busy

Postby law » Tue Oct 01, 2024 5:07 am

Hey,
Yeah, I'm a bit confused.
I see how calling chEvtAddEvents would add a new event and allow chEvtWaitAny to continue.
What I don't understand is how would I get back into the "event_1" flag condition?
chEvtGetAndClearFlags would have got and cleared the flags, so on the next entry to chEvtGetAndClearFlags after calling chEvtAddEvents, the "event_1" flag bit would not be set?

If I dig into chEvtAddEvents I can see that it just ORs the current thread epending with the event passed into it. No flags are set in there.
Also, hello from Australia!

User avatar
FXCoder
Posts: 393
Joined: Sun Jun 12, 2016 4:10 am
Location: Sydney, Australia
Has thanked: 184 times
Been thanked: 131 times

Re: New event behaviour while busy

Postby FXCoder » Tue Oct 01, 2024 6:47 am

Hi,
In this case (where you want to re-post events) put chEvtGetAndClearEvents(...) at the top to get the events in your thread and then chEvtGetAndClearFlags(...) at the bottom of the loop to clear the listener object flags.
This would leave any added thread flags set by the worker_1 (etc.), as part of the loop work intact, but will clear the event listener flags at the bottom.
Of course you will still be in a somewhat hard loop doing it this way but at least servicing the worker list in a round robin fashion as they post "more to do".

--
Bob


Return to “ChibiOS/RT”

Who is online

Users browsing this forum: No registered users and 14 guests