Jump to content


Photo

Priorities - Odd Behaviour


5 replies to this topic

#1 JorgeF

JorgeF

    Super Enthusiast

  • EstablishedMember
  • PipPipPip
  • 274 posts
  • Gender:Male
  • Location:ES @ Europe, third rock from the Sun

Posted 01 December 2012 - 11:57 PM

Hi


In a project with 4 tasks, where 2 are free running with the same priority and the other two run in function of semaphores, I noticed the following behaviour.


   	 // Create tasks
		// LEDs 1 and 2 blinking at 2Hz in oposition (phase = 180º)
		SysCreateTask(hTaskLED1,4,Task_LED1);		// Free run (LED1 follows LEDState)
		SysCreateTask(hTaskLED2,4,Task_LED2);		// Free run (LED1 follows not LEDState)
 
		// LED 3 and 4 blink at 1Hz in quadrature ( phase = 90º)
		SysCreateTask(hTaskLED3,4,Task_LED3);		// Wait Semaphore (LEDState 0->1)
		SysCreateTask(hTaskLED4,4,Task_LED4);		// Wait Semaphore (LEDState 1->0)
 
   	 // LEDState variable and the signaling of the semaphores is all handled in the ISR
 
***** Full project attached.*****

If the priority of tasks LED3 and LED4 are the same or higger than the priority of tasks LED1 and LED2 everything runs as expected and the all 4 LEDs flash acording to the program.
Even if one of Task LED1 and LED2 or both are not started things work as expected.

If the priority of tasks LED3 and LED4 is lower than the priority of tasks LED1 and LED2, tasks LED3 and LED4 still execute and LEDs 3 and 4 flash at 1Hz but in synch instead of in quadrature (not acording to the signaling of the semaphores).

I was expecting that tasks LED3 and LED4 will be stalled (never run) due to the higher priority of the free running tasks.

Is this some error of mine or there is a bug with the round robin algorithm that cycles the ready tasks with same priority. ?


Best regards
Jorge

Attached Files


Edited by JorgeF, 01 December 2012 - 11:59 PM.


#2 JorgeF

JorgeF

    Super Enthusiast

  • EstablishedMember
  • PipPipPip
  • 274 posts
  • Gender:Male
  • Location:ES @ Europe, third rock from the Sun

Posted 02 December 2012 - 11:27 PM

Hi

Quoting from another thread

Your Novo problem is a good one. I have it running on my EasyPIC5 board.
It says in the Novo source that the next task can be overridden by priority change or waiting task wakeup.
Maybe the last part has something to do with it (waiting task wakeup).

For sure it has something to do with the tasks being awaken from the semaphores.
Of course the "next task" can be overrriden by a priority change.
The "ready list" must be reorganized when priorities are changed so the head of the ready list can change.

Also if a task is woken up and inserted in the ready list it can be inserted at the head if its priority is >= than that of the previous head.
But waking up a task and inserting it ahead of another with higger priority seems a bit odd.

And there is still the side efect that both low priority tasks (LED3 and LED4) run in synch when this happens.
Each semaphore is signaled at about 1Hz rate and in an alternate fashion. There is about 1/2 second time gap betwen each semaphore signaling,
As we have the tasks for LED1 and 2 alternating at a high rate, there is plenty of yielding betwen each task wake up event, how do the LED 3 and 4 flash in synch after beeing signaled in quadrature oposition (see interrupt code).

It looks like the first of tasks LED3 or 4 wakes up and gets stalled at the end of the ready queue due to its low priority, but when the second wakes up the run task pointer gets messed.

I have to do some more testing and reviewing of the NOVO source code.
But so far I suspect that the run task pointer (ready queue head) skids from the second (ready queue order) high priority task (say LED2) to the just inserted low priority (say LED4), then the two low priority tasks get executed in a row and only then the run task pointer rolls back to the first high priority task.
If the just awaken task gets inserted in front of the other tasks of the same priority (a common practice in RTOSs) this would mean skiding from second to third task in ready queue.


EDIT: Corrected quadrature to oposition. The quadrature only applies to the output not to the semaphore signaling.

Best regards
Jorge

Edited by JorgeF, 03 December 2012 - 12:13 PM.


#3 Dave

Dave

    Super Maniac

  • Administrators
  • PipPipPipPipPip
  • 2,091 posts
  • Gender:Male
  • Location:UK
  • Interests:How things work, Electronics, Software, Cycling.

Posted 03 December 2012 - 11:41 PM

Hi

Quoting from another thread


Your Novo problem is a good one. I have it running on my EasyPIC5 board.
It says in the Novo source that the next task can be overridden by priority change or waiting task wakeup.
Maybe the last part has something to do with it (waiting task wakeup).

For sure it has something to do with the tasks being awaken from the semaphores.
Of course the "next task" can be overrriden by a priority change.
The "ready list" must be reorganized when priorities are changed so the head of the ready list can change.

Also if a task is woken up and inserted in the ready list it can be inserted at the head if its priority is >= than that of the previous head.
But waking up a task and inserting it ahead of another with higger priority seems a bit odd.
...

Something does seem to be wrong here, but I'm not sure what it is yet.

Regards
Dave

#4 Dave

Dave

    Super Maniac

  • Administrators
  • PipPipPipPipPip
  • 2,091 posts
  • Gender:Male
  • Location:UK
  • Interests:How things work, Electronics, Software, Cycling.

Posted 04 December 2012 - 09:04 PM

JorgeF,

Thanks for a fine example of code that failed.

Hi Quoting from another thread

Something does seem to be wrong here, but I'm not sure what it is yet. Regards Dave


The following function has the error corrected that caused this problem - incorrect capture of the max priority task when adding a task to the run queue.
void SysiAddToRunQueue( TASK_HANDLE hTask )
{
TASK_HANDLE pos = RUN_QUEUE_HEAD;
TASK_HANDLE nextPos;
 
BYTE priority = GetTaskPriority( hTask );
BYTE maxPriority = priority;
 
while( 1 )
{
  nextPos = GetNextTask( pos ); // move onto next
 
  if( nextPos == RUN_QUEUE_HEAD ) // end reached
   break; // exit with pos = node just before end
  // when priority is less than task to add we have found insertion point
  BYTE nextPriority = GetTaskPriority( nextPos );
  if( nextPriority < priority )
   break;
  else if( nextPriority > maxPriority ) // capture next priority
   maxPriority = nextPriority;
	
  pos = nextPos;
}	
  
// merge node into queue
SetPrevTask( hTask, pos );
SetNextTask( hTask, nextPos );
SetNextTask( pos, hTask );
SetPrevTask( nextPos, hTask );
 
// if task inserted at run queue head then it must be the one to run next
if( pos == RUN_QUEUE_HEAD )
  scheduler.os_hNextTaskActive = hTask;
 
// if task has max priority, then it will be the new last in the run line
if( priority == maxPriority )
  scheduler.os_hTaskLastHp = hTask;
 
SetTaskStatusBit( hTask, TS_IN_RUN_Q );
}
You will need to update this function in novo.c and rebuild the require Novo RTOS library.

Let me know if this fixes your issue.

Regards
Dave

#5 JorgeF

JorgeF

    Super Enthusiast

  • EstablishedMember
  • PipPipPip
  • 274 posts
  • Gender:Male
  • Location:ES @ Europe, third rock from the Sun

Posted 04 December 2012 - 10:02 PM

Hi Dave


You beated me to this one, by a couple of hours.
I already had my spotlights on this function, but hadn't pinpointed the exact spot yet.

Thanks for the support.
I'll report back as soon as I finish my tests, with this project and another variation of it that I alraedy had in place.

Best regards
Jorge

#6 JorgeF

JorgeF

    Super Enthusiast

  • EstablishedMember
  • PipPipPip
  • 274 posts
  • Gender:Male
  • Location:ES @ Europe, third rock from the Sun

Posted 05 December 2012 - 08:39 PM

Hi guys


After rebuilding the lib (novolib_pic16t6e4ts2.lib) used by the test projects and several rebuilds with different relative priorities for the various tasks everything works as expected.
So I'm glad to say ...

Thanks Dave its SOLVED

Next step is to rebuilding all the libs, before I mess something with a mix of corrected and uncorrected libs.



Attached are the two test projects.
One is the same project used to show the bug and the other is a variation with semaphores for Tasks LED3 and LED4 being signaled by Tasks LED1 and LED2, instead of being signaled by the ISR.
This makes task LED3 dependent of Task LED1 and Task LED4 dependent on Task LED2.



EDIT:
Tested with PIC18 also, as expected, no issues.




Best regards
Jorge

Attached Files


Edited by JorgeF, 07 December 2012 - 11:48 PM.




Reply to this topic



  


1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users