[Bug 1252] New: _Thread_queue_Dequeue_priority incomplete
rtems-bugs at rtems.org
rtems-bugs at rtems.org
Mon Aug 20 17:44:21 UTC 2007
http://www.rtems.org/bugzilla/show_bug.cgi?id=1252
Summary: _Thread_queue_Dequeue_priority incomplete
Product: RTEMS
Version: 4.7
Platform: All
OS/Version: RTEMS
Status: NEW
Severity: major
Priority: P3
Component: cpukit
AssignedTo: joel.sherrill at oarcorp.com
ReportedBy: manuel.coutinho at edisoft.pt
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
--
Configure bugmail: http://www.rtems.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
More information about the bugs
mailing list