FreeRTOS Support Archive
The FreeRTOS support forum is used to obtain active support directly from Real
Time Engineers Ltd. In return for using our top quality software and services for
free, we request you play fair and do your bit to help others too! Sign up
to receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.
[FreeRTOS Home] [Live FreeRTOS Forum] [FAQ] [Archive Top] [March 2009 Threads] taskYIELD() in critical sectionPosted by Grigore-Mihai Dobra on March 19, 2009 In freeRTOS 5.1.12, there is a taskYIELD() inside a critical section(portENTER_CRITICAL) in function xTaskResumeAll. Is that ok? If disabling the interrupts before switching the context, who will preempt the new running task?
RE: taskYIELD() in critical sectionPosted by Richard on March 19, 2009 I really need to add this to the FAQ!
Yes this is perfectly OK everywhere the scheduler does it, although i don't recommend doing this in the application code unless you fully understand the consequences.
Each task maintains its own flags value so a task can yield from a critical section to a task that is not in a critical section - the original idea being that when the original task started to run again it would start from within a critical section and therefore have guaranteed access to the data structures. This reason has actually since disappeared but it is still safe.
Regards.
RE: taskYIELD() in critical sectionPosted by Grigore-Mihai Dobra on March 19, 2009 Maybe I'm missing the point here, but when you enter a critical section, uxCriticalNesting is incremented and the interrupts are disabled. The interrupts being disabled, no timer interrupt will give the kernel the tick. This means the current task(the one becoming active after yield) will run for an indefinite amount of time without being preempted.
RE: taskYIELD() in critical sectionPosted by Richard Damon on March 20, 2009 What you are missing is that as part of the context switch caused by the yield will re-enable the interrupts (unless the new task was also in a critical section) as uxCriticalNesting is stored on a per TASK basis.
RE: taskYIELD() in critical sectionPosted by Grigore-Mihai Dobra on March 20, 2009 Well, first, I should say that my architecture won't store the General Interrupt Flag in the Program Status Word, thus this flag will not be saved/restored at a context switch.
More, nowhere in the example ports did I see that uxCriticalNesting is stored on a per task basis. Could this feature be introduced later from the V5.1.2 or so?
So I am still puzzled by this yield inside critical section.
RE: taskYIELD() in critical sectionPosted by Grigore-Mihai Dobra on March 20, 2009 Ok, it is clear to me now, as I have inspected 'tasks.c' and found this: #if ( portCRITICAL_NESTING_IN_TCB == 1 ) unsigned portBASE_TYPE uxCriticalNesting; #endif
So I'll just have to redesign a little my context switch functions(timer interrupt and yield 'function') to use this feature.
RE: taskYIELD() in critical sectionPosted by Richard on March 20, 2009 In most cases the critical nesting count is stored on the stack of the task, but in newer ports it is stored as part of the TCB.
Also, not wanting to add confusion to the discussion, but some ports now don't actually yield until they leave the critical section. This part is very port specific.
Regards.
RE: taskYIELD() in critical sectionPosted by Grigore-Mihai Dobra on March 20, 2009 As I have already said in a missposted post: https://sourceforge.net/forum/message.php?msg_id=6885683
RE: taskYIELD() in critical sectionPosted by Richard on March 20, 2009 If you have the nesting count then you don't need the status word as well, just look at the nesting count value to know if you are in a critical section or not.
Which architecture are you using?
Regards.
RE: taskYIELD() in critical sectionPosted by Grigore-Mihai Dobra on March 22, 2009 Well, I am trying to port freeRTOS to NXP 51XA(8051 eXtended Architecture). Upon interrupt, the stack contains the PSW(program status word), PC(program counter), and eventually, the CS(Code segment), if using the non-page zero mode. Non-page zero mode means the controller will use more than 64KB of RAM and more that 64KB of code. I won't go into much detail here, just for reference.
Anyway, if using the uxCriticalNesting inside the TCB, another problem arises: Who will set the member variable uxCriticalNesting to 0? Because, if it is not set to zero, the start count will not be consistent with the interrupts enable/disable state.
RE: taskYIELD() in critical sectionPosted by Prithwee on March 23, 2009 >>Who will set the member variable uxCriticalNesting to 0?
if you have set "portCRITICAL_NESTING_IN_TCB==1" then in tasks.c file, "prvInitialiseTCBVariables" function will take care of it.
RE: taskYIELD() in critical sectionPosted by Grigore-Mihai Dobra on March 23, 2009 Yeah, that's right. Looked for something like this in the source code before asking the question, but found nothing. Looked again now, it's there. I should concentrate my attention better.
RE: taskYIELD() in critical sectionPosted by Grigore-Mihai Dobra on March 28, 2009 Another problem found in xTaskCreate:
portENTER_CRITICAL(); { uxCurrentNumberOfTasks++; if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) { /* As this is the first task it must also be the current task. */ pxCurrentTCB = pxNewTCB;
well, my implementation of portENTER_CRITICAL() is on a per-task basis(portCRITICAL_NESTING_IN_TCB == 1), so uxCriticalNesting is contained within the TCB. Well, pxCurrentTCB is not initialized at the point portENTER_CRITICAL() is called here. So my implementation of portENTER_CRITICAL() will alter some RAM zone which is not a TCB.
I saw in the source code that there are two forms of entering critical: portENTER_CRITICAL and taskENTER_CRITICAL. Unfortunately, both refer to the same function/code snippet. Why not split them to have one of them(taskENTER_CRITICAL) for tasks(TCB based) and the other(portENTER_CRITICAL) for the whole system(global uxCriticalNesting)?
Of course, my implementation of portENTER_CRITICAL could use both a global variable or the field from TCB, based on the scheduler state, but that would increase code size and timing.
RE: taskYIELD() in critical sectionPosted by Richard on March 28, 2009 The idea is (was) that user code does not call anything in the port layer directly, only the task and queue API. Therefore user code should call taskENTER_CRITICAL() not portENTER_CRITICAL(), although the two are mapped to the same code so in reality it makes no difference unless you switch code from one port to another.
When portCRITICAL_NESTING_IN_TCB is set to 1 then the enter/exit critical section macros should map to vTaskEnterCritical() and vTaskExitCritical() [defined in task.c]. These functions will only attempt to access pxCurrentTCB if the scheduler is running to remove the risk of them accessing it before it have been set to point to a valid TCB structure.
Regards.
RE: taskYIELD() in critical sectionPosted by Grigore-Mihai Dobra on March 28, 2009 Ok, I can see a valid critical section schema now. The truth is I haven't went on a exhaustive reading of the documentation or source code, so my questions could seem stupid sometimes.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|