pthread_once() and rtems_gxx_once()

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Jul 4 14:18:17 UTC 2013


Hello,

both functions disable currently the preemption to ensure mutual exclusion. 
This doesn't work on SMP.  This makes also pthread_once() not POSIX conform. 
Here we have

http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_once.html

"On return from pthread_once(), it is guaranteed that init_routine() has 
completed."

This is not true if the init_routine() blocks on a resource access.  I assume 
that GCC needs also this guarantee.

To address this issue we have to protect the section with a mutex.  So it could 
look like this:

int pthread_once(
   pthread_once_t   *once_control,
   void           ( *init_routine )( void )
)
{
   int eno = 0;

   if ( once_control->is_initialized ) {
     if ( !once_control->init_executed ) {
       _RTEMS_Lock_allocator();
       if ( !once_control->init_executed ) {
         once_control->init_executed = true;
         ( *init_routine )();
       }
       _RTEMS_Unlock_allocator();
     }
   } else {
     eno = EINVAL;
   }

   return eno;
}

We can also introduce a new API mutex for this, but I don't think this is 
necessary.

This implementation has a severe defect.  Asynchronous cancellation, restart, 
suspend or deletion inside the critical section leads to a permanently locked 
mutex.  This leads to the next problem.  The cancellation support is also in 
the POSIX API (e.g. pthread_setcanceltype).  I think we have to move this also 
to the Classic API (there is a bug in this area 
https://www.rtems.org/bugzilla/show_bug.cgi?id=2035).  This leads to the next 
problem.  To use this we may need cleanup handlers (e.g. 
pthread_cleanup_push/pop).  The current pthread_cleanup_push() implementation 
is broken.  It uses workspace allocation with a silent failure.

As documented here

http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cleanup_push.html

the cleanup handling can be implemented with data structures on the stack 
(instead of the workspace).

I see the following steps to fix the pthread_once() and rtems_gxx_once() 
implementation.

1. Change the cleanup handler implementation to use data structures on the 
stack (Newlib owned header file, use <sys/queue.h> for lists instead of RTEMS 
chains) and move the cleanup support to the Score (available now in all APIs).

2. Implement the once functions with a mutex.

-- 
Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone   : +49 89 189 47 41-16
Fax     : +49 89 189 47 41-09
E-Mail  : sebastian.huber at embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.



More information about the devel mailing list