-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
refactor: remove uneccesary task{ENTER | EXIT}_CRITICAL() #1140
refactor: remove uneccesary task{ENTER | EXIT}_CRITICAL() #1140
Conversation
uxQueueSpacesAvailableThis function reads 2 variables xTimerGetReloadMode, xTimerGetReloadModeThese functions read |
uxlLength is a constant for a given queue, initialized on construction and never changed, thus its access doesn't need to be protected. uxMesssagesWaiting can probably be read atomically, and not need to be protected, I believe we have a conditional critical section that could be used for that sort of action. Yes, there is a fundamental race in the function that even its critical section can't handle, in that between the call to get the number of items and an operation to use them, the number of items could change, but there is nothing this function can do about that. |
You are exactly right. Thank you for pointing that! Ignore my comment about this function. |
You say that we have a conditional critial section. This Condifitional critical section have a check for atomic context? If uxMessagesWaiting can be access for a atomic context or a access for a unprivileged context, then this conditional critical section is neccessary. |
@GuilhermeGiacomoSimoes Thank you for raising this PR. This PR relies on the fact that Read and Write of Instead of doing this change in a way which impacts all the ports, we can introduce this gradually on a port-by-port basis. We can introduce a new set of macros, namely #ifndef portBASE_TYPE_ENTER_CRITICAL
#define portBASE_TYPE_ENTER_CRITICAL() taskENTER_CRITICAL()
#endif
#ifndef portBASE_TYPE_EXIT_CRITICAL
#define portBASE_TYPE_EXIT_CRITICAL() taskEXIT_CRITICAL()
#endif The above can be inserted here - https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/include/portable.h#L87. We can then change the functions in this PR to use these new macros instead. Once that is done, these new macros can be defined to nothing in #define portBASE_TYPE_ENTER_CRITICAL()
#define portBASE_TYPE_EXIT_CRITICAL() What do you think about this? |
Okay, I understand your concern, and really make sense. Your suggestions make sense too .. Then, instead call taskENTER_CRITICAL(), we would should call the new portBASE_TYPE_ENTER_CRITICAL(). I will make this change and test this. |
I am good with whatever you prefer. Thank you for all the work! |
The read and write from BaseType_t, can be do in a atomic context, and dont need a mutex contol. Change this methods for access the critical regiao only if is neccessary. For make this, create a macro in portable.h that apoint to tasENTER|EXIT_CRITIAL() function. Now, if port is guarantee that access BaseType_t in atomic context, a empty macro can be define in portmacro.h, like this: Signed-off-by: guilherme giacomo simoes <trintaeoitogc@gmail.com>
1da3e1a
to
a118f6a
Compare
@aggarg I make the changes that is suggested by you here. I test this rigorously. For test this, you can make this simple change in portmacro.h: diff --git a/portable/GCC/ATMega323/portmacro.h b/portable/GCC/ATMega323/portmacro.h
index 6ed5e4295..131819004 100644
--- a/portable/GCC/ATMega323/portmacro.h
+++ b/portable/GCC/ATMega323/portmacro.h
@@ -61,6 +61,8 @@
#define portSTACK_TYPE uint8_t
#define portBASE_TYPE char
+#include "help.h" /// this is the help.h that I mentionated in the PR description
+
#define portPOINTER_SIZE_TYPE uint16_t
typedef portSTACK_TYPE StackType_t;
@@ -78,13 +80,18 @@ typedef unsigned char UBaseType_t;
#endif
/*-----------------------------------------------------------*/
+#define portBASE_TYPE_ENTER_CRITICAL()
+#define portBASE_TYPE_EXIT_CRITICAL()
+
/* Critical section management. */
#define portENTER_CRITICAL() \
+ serial_print("\nenter critical\n"); \
asm volatile ( "in __tmp_reg__, __SREG__" ::); \
asm volatile ( "cli" ::); \
asm volatile ( "push __tmp_reg__" ::)
#define portEXIT_CRITICAL() \
+ serial_print("\nexit critical\n"); \
asm volatile ( "pop __tmp_reg__" ::); \
asm volatile ( "out __SREG__, __tmp_reg__" ::) You can see that I already create the empty macro portBASE_TYPE_ENTER_CRITIAL() .... Now, when I run the tests that I mentioned in PR description , you can see where the string "enter critical" should or don't should showed. For ex, If you want run the test about uxQueueMessagesWaiting(), the string showing in console gonna be: BUT, If you comment the empty macros: /// #define portBASE_TYPE_ENTER_CRITICAL()
/// #define portBASE_TYPE_EXIT_CRITICAL() Then, the portENTER_CRITIAL() should execute .. Then in your console, you can see this:
Because the prints that I set in portmacro should be executed. If you need any explanation or help, you can found me on this email trintaeoitogc@gmail.com |
Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Quality Gate passedIssues Measures |
refactor: remove uneccesary task{ENTER | EXIT}_CRITICAL()
Description
The call to the task{ENTER|EXIT}_CRITICAL() function is being made unnecessarily. It was probably placed to control access to the UBaseType_t variable, which the kernel is only accessed in atomic contexts. Therefore, the MUTEX to access this variable is not necessary since tasks in the atomic context do not have concurrency problems in accessing certain data
I would like to thanks @n9wxu, @svenbieg, @richard-damon to help me with this task.
Test Steps
For test in ATMega328p:
First I create this FreeRTOSConfig.h
Then, I create this simple Makefile
For help me with some things like print in serial port I create this help.c
and this help.h
for make a simple test about create a simple task, I create this main.c:
I compile:
make
and upload this for my Arduino:I use the picocom for monitoring of serial port:
main.c for test uxQueueMessagesWaiting() and uxQueueSpacesAvailable():
for test uxTaskPriorityGet() ans uxTaskBasePriorityGet();
for test xTimerGetReloadMode() and xTimerIsTimerActive()
Checklist:
Related Issue
1059
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.