Notice: We have migrated to GitLab launching 2024-05-01 see here: https://gitlab.rtems.org/

#1252 closed defect (invalid)

_Thread_queue_Dequeue_priority incomplete

Reported by: Manuel Coutinho Owned by: Joel Sherrill
Priority: normal Milestone: 4.8
Component: doc Version: 4.7
Severity: minor Keywords:
Cc: manuel.coutinho@… Blocked By:
Blocking:

Description

Hi

This is my first bug report so go easy on me :)

I believe there is an internal bug when a semaphore_release is called.
In short, this bug happens when a high priority task blocks in a semaphore (with no priority inheritance/ceiling) and another task suspends that high priority task. When the _Thread_queue_Dequeue_priority function is called (assuming the semaphores are created with a priority protocol) the thread on top (the highest priority thread) is always unblocked which is incorrect if that thread is suspended.
Well, at least it is what I think...

The following code shows an example where T1 is the highest priority task which, after blocking in a semaphore, is still the thread on top of the thread_queue and is unblocked.

#include <stdlib.h>
#include <stdio.h>
#include <rtems.h>
rtems_id id1,id2,id3,id4,id5,sem_id;

rtems_task Task1()
{

printf("T1: obtaining semaphore\n");
rtems_semaphore_obtain(sem_id,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
printf("T1: releasing semaphore\n");
rtems_semaphore_release(sem_id);

while(1)

{

rtems_task_wake_after(10);

}

}

rtems_task Task2()
{

printf("T2: obtaining semaphore\n");

rtems_semaphore_obtain(sem_id,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
printf("T2: releasing semaphore\n");
rtems_semaphore_release(sem_id);

while(1)

{

rtems_task_wake_after(10);

}

}

rtems_task Task3()
{

printf("T3: obtaining semaphore\n");
rtems_semaphore_obtain(sem_id,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
printf("T3: releasing semaphore\n");
rtems_semaphore_release(sem_id);

while(1)

{

rtems_task_wake_after(10);

}

}

rtems_task Task4()
{

printf("T4: obtaining semaphore\n");
rtems_semaphore_obtain(sem_id,RTEMS_WAIT,RTEMS_NO_TIMEOUT);
printf("T4: releasing semaphore\n");
rtems_semaphore_release(sem_id);


while(1)

{

rtems_task_wake_after(10);

}

}

rtems_task Task5()
{

printf("T5: obtaining semaphore\n");
rtems_semaphore_obtain(sem_id,RTEMS_WAIT,RTEMS_NO_TIMEOUT);

printf("T5: starting the higher priority tasks\n");


rtems_task_start(id4,Task4,0);
rtems_task_start(id3,Task3,0);
rtems_task_start(id2,Task2,0);
rtems_task_start(id1,Task1,0);

rtems_task_suspend(id1); /* UNCOMMENT THIS LINE AND ALL IS WELL */

printf("T5: releasing semaphore\n");
rtems_semaphore_release(sem_id);

while(1)

{

rtems_task_wake_after(10);

}


}

rtems_task Init(

rtems_task_argument ignored

)
{

rtems_status_code status;

printf("Creating tasks...\n");


status = rtems_task_create(rtems_build_name('t','e','k','1'),

10 ,
RTEMS_MINIMUM_STACK_SIZE ,
RTEMS_DEFAULT_MODES ,
RTEMS_DEFAULT_ATTRIBUTES ,
&id1 );

status = rtems_task_create(rtems_build_name('t','e','k','2'),

70 ,
RTEMS_MINIMUM_STACK_SIZE ,
RTEMS_DEFAULT_MODES ,
RTEMS_DEFAULT_ATTRIBUTES ,
&id2 );

status = rtems_task_create(rtems_build_name('t','e','k','3'),

140 ,
RTEMS_MINIMUM_STACK_SIZE ,
RTEMS_DEFAULT_MODES ,
RTEMS_DEFAULT_ATTRIBUTES ,
&id3 );

status = rtems_task_create(rtems_build_name('t','e','k','4'),

219 ,
RTEMS_MINIMUM_STACK_SIZE ,
RTEMS_DEFAULT_MODES ,
RTEMS_DEFAULT_ATTRIBUTES ,
&id4 );

status = rtems_task_create(rtems_build_name('t','e','k','5'),

220 ,
RTEMS_MINIMUM_STACK_SIZE ,
RTEMS_DEFAULT_MODES ,
RTEMS_DEFAULT_ATTRIBUTES ,
&id5 );

printf("creating semaphore\n");
status = rtems_semaphore_create(rtems_build_name('s','e','l','0') ,

1 ,
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY ,
0 ,
&sem_id );

printf("starting the lowest priority task\n");
rtems_task_start(id5,Task5,0);

while(1)

{

rtems_task_wake_after(40000); /* remain idle...*/

}

exit( 0 );

}

/* configuration information */

#define CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_TEST_NEEDS_CLOCK_DRIVER

#define CONFIGURE_RTEMS_INIT_TASKS_TABLE

#define CONFIGURE_MAXIMUM_TASKS 100 /*just to put a high value*/
#define CONFIGURE_MAXIMUM_SEMPAHORES 10 /*just to put a high value*/

#define CONFIGURE_INIT

#include <rtems/confdefs.h>

/* end of file */

The output of this code is (tested with SIS for ERC32 in RTEMS 4.7.1):
Creating tasks...
creating semaphore
starting the lowest priority task
T5: obtaining semaphore
T5: starting the higher priority tasks
T4: obtaining semaphore
T3: obtaining semaphore
T2: obtaining semaphore
T1: obtaining semaphore
T5: releasing semaphore

and it should be:
Creating tasks...
creating sempahore
starting the lowest priority task
T5: obtaining semaphore
T5: starting the higher priority tasks
T4: obtaining semaphore
T3: obtaining semaphore
T2: obtaining semaphore
T1: obtaining semaphore
T5: releasing semaphore
T2: releasing semaphore
T3: releasing semaphore
T4: releasing semaphore

That is, the task 2 (and the remaining tasks) should be able run.
Of course, I believe this error may happen with other managers apart from the semaphore (e.g. message queue).

I suspect the correction to this error is in the _Thread_queue_Dequeue_priority function:

Thread_Control *_Thread_queue_Dequeue_priority(Thread_queue_Control *the_thread_queue)
{

uint32_t index;
ISR_Level level;
Thread_Control *the_thread = NULL; /* just to remove warnings */
Thread_Control *new_first_thread;
Chain_Node *new_first_node;
Chain_Node *new_second_node;
Chain_Node *last_node;
Chain_Node *next_node;
Chain_Node *previous_node;

_ISR_Disable( level );

for( index=0 ; index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ; index++ )

{

if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) )

{

aux = (Thread_Control *)

the_thread_queue->Queues.Priority[index].first;


while(!(aux->current_state & STATES_SUSPENDED))

{

/* search the threads which are not suspended */
aux = aux->?????????????;

}


the_thread = aux;
_state_flag = index;
goto dequeue;

}

}

.
.
.
.
.

}

I don't know how to "navigate" through the Chain_Node structure to search the (64) nodes in each index...otherwise I would have detailed the "solution" better :)

Hope this is an actual bug and I'm not wasting anybody's time :)

Regards
Manuel Coutinho

Change History (3)

comment:1 Changed on 08/20/07 at 17:03:44 by Joel Sherrill

Component: cpukitdoc
Severity: majorminor

comment:2 Changed on 08/21/07 at 08:36:05 by Manuel Coutinho

Cc: Manuel Coutinho added

comment:3 Changed on 05/07/08 at 20:24:43 by Joel Sherrill

Resolution: invalid
Status: newclosed

Discussion completed bug report -- should already have been closed. User misunderstanding of behavior.

Note: See TracTickets for help on using tickets.