Opened on 08/20/07 at 16:44:20
Closed on 05/07/08 at 20:24:43
#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: | cpukit → doc |
---|---|
Severity: | major → minor |
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: | new → closed |
Discussion completed bug report -- should already have been closed. User misunderstanding of behavior.