[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