Skip to content

Use EventFlags instead of Semaphores #4580

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 4, 2017

Conversation

deepikabhavnani
Copy link

@deepikabhavnani deepikabhavnani commented Jun 16, 2017

Description

Synchronization in sockets required binary semaphores which is not available
in RTX5, hence switching to event flags.
Issue #4575

Migrations

PR should be merged after PR #4517. EventFlags Class implementation is picked up from this PR.

Related PRs

PR #4517
PR #4560

Todos

Copy link
Contributor

@geky geky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, yay for reducing a semaphore object : )


if (count < 1) {
// Semaphore wait timed out so break out and return
if (0 == (flag & WRITE_FLAG)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the surprising annoyances of the new osEventFlags API, is that wait actually returns error codes on timeout:
https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__flags__error__codes.html

These conditions should probably be something like:

if ((flag & WRITE_FLAG) != WRITE_FLAG) {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@geky: Both conditions are logically same. I prefer comparison with zero over fix values. Any specific reason for other condition?

Copy link
Contributor

@geky geky Jun 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_event_flag.wait returns 0xFFFFFFFEU on timeout, not zero (I don't really get why but it is what it is):
https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__flags__error__codes.html

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They set the most significant bit to 1 (osFlagsError) to mark error. To check for any error it's enough to check ret | osFlagsError

Copy link
Contributor

@geky geky Jun 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good to know, that works too 👍

@theotherjimmy theotherjimmy changed the title Using EventFlags instead of Semaphores Use EventFlags instead of Semaphores Jun 16, 2017
@@ -18,8 +18,11 @@
#include "Timer.h"
#include "mbed_assert.h"

#define READ_FLAG 0x1u
#define WRITE_FLAG (0x1u << 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a final value here? It makes debugging way easier when you can actually grep the code to find what the value is. Also `<< 1`` doesn't help with readability here.


/** Set the specified Event Flags.
@param flags specifies the flags that shall be set.
@return event flags after setting or error code if highest bit set.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth mentioning a osFlagsErrorfor all the return values, that's a macro with highest bit set, so people know they can use it rather than defining their own.

@param timeout timeout value or 0 in case of no time-out.
@return event flags before clearing or error code if highest bit set.
*/
uint32_t wait (uint32_t flags, uint32_t options=osFlagsWaitAny, uint32_t timeout=0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about that, it's a very thin wrapper on RTX, it caused us some grief with RTX update (as we are not supposed to break the APIs). I would say we could abstract it out a bit, wait could be for any flags if flag is 0 and for specified flag in other cases. If we do that we can ignore the options parameter (and the remaining 'don't clear' option or add clear parameter defaulting to true.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bulislaw : User can have multiple flags say 5, and can select any two bits in flag option to wait for any "one" of them to be set in case of "osFlagsWaitAny" If we set flag to "0", we cannot know wait for which specific set of bits.
This option will change the behavior of RTX API's.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think following is reasonable:

#define flag1 0x1 
#define flag2 0x2

/*[...]*/
flag.wait(flag1) /* Waits only for the flag1 */
flag.wait(flag2) /* Waits only for the flag2 to be set */
res = flag.wait(0) /* Waits for anything to be set */
if (res | flag1 || res | flag2) { \*...*/ }

but we could also introduce wait_any or something similar to only interrupt the wait if any one of the flags finish. I think this form of API is easier and more user friendly.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. But what should be the option for "osFlagsWaitAll" flag? Wait for flag1 and flag2 both

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait(flag1 | flag2) should translate to wait with osFlagsWaitAll and wait(0) to wait for 0x8FFFFFF flag (msb set to one is an error so it's not allowed) with osFlagsWaitAny.

Copy link
Author

@deepikabhavnani deepikabhavnani Jun 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only case I don't see getting covered here is: I need to wait for any 1 or 3

#define flag3 0x4
flag.wait(flag1 | flag3) - Will wait for 1 and 3
flag.wait(0) - Will wait for all three (2 is not required in my case)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, forgot timeout: It should be wait(flag, timeout). Correct ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I skipped the timeout for brevity as it has default 0. I think case s you mentioned can be handled by either:

res = flag.wait(0) /* Waits for anything to be set */
if (res | flag1 || res | flag3) { \*...*/ }

or the wait in a loop for that mater. Second option would be to add wait_any member. I think adding second member function is cleaner. Also worth mentioning in docs that flags are 1bit long.

@theotherjimmy
Copy link
Contributor

@bulislaw does this most recent commit address your comments?

@deepikabhavnani
Copy link
Author

@theotherjimmy : Most recent comment by @bulislaw is related to event flag Class.
He is suggesting to change wait API in eventflag Class

@bulislaw
Copy link
Member

EventFlag Class wasn't updated, I would say that because of 'no API breakage policy' new public classes shouldn't be introduced lightly, there should be wider discussion about them. I don't think the new class is ready.

@bulislaw
Copy link
Member

@0xc0170 @c1728p9 @geky @pan- can you review the new EvenFlag class please

@0xc0170
Copy link
Contributor

0xc0170 commented Jun 30, 2017

OK now I am confused, so #4517 is adding it , still under review, this is on top of it but doing also changes to the class itself :-) It would be easier to have only that class addition as it is in 4517 and doing edits there (having write access or take over that PR and send a new one ?) ?

@bulislaw
Copy link
Member

Ah i missed that! I'll have a look at #4517

@deepikabhavnani
Copy link
Author

@bulislaw - I have rebased the code and using updated API's. Please review

Copy link
Member

@bulislaw bulislaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@geky can you review as well.

_write_sem.release();
_read_sem.release();

_event_flag.set(WRITE_FLAG);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not to set it in one go? WRITE_FLAG | READ_FLAG?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

EventFlags class is a wrapper for Event Flag functionality introduced in
RTOS2/RTX5.
Copy link
Member

@bulislaw bulislaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@geky geky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me 👍

@studavekar
Copy link
Contributor

/morph test-nightly

@mbed-bot
Copy link

mbed-bot commented Sep 3, 2017

Result: SUCCESS

Your command has finished executing! Here's what you wrote!

/morph test-nightly

Output

mbed Build Number: 1187

All builds and test passed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants