Ignore:
Timestamp:
Oct 20, 2022, 4:09:13 PM (20 months ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, master
Children:
a5e2682
Parents:
1a45263
Message:

Some clean-up in pthread emulation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/pthread.cfa

    r1a45263 r8bd886e  
    3333enum { PTHREAD_KEYS_MAX = 1024 };
    3434
    35 struct Pthread_values{
     35struct pthread_values{
    3636        inline Seqable;
    3737        void* value;
     
    3939};
    4040
    41 
    42 static Pthread_values *& Back( Pthread_values * n ) {
    43         return (Pthread_values *)Back( (Seqable *)n );
    44 }
    45 static Pthread_values *& Next( Pthread_values * n ) {
    46         return (Pthread_values *)Next( (Colable *)n );
    47 }
    48 
    49 struct Pthread_keys{
     41static inline {
     42        pthread_values *& Back( pthread_values * n ) {
     43                return (pthread_values *)Back( (Seqable *)n );
     44        }
     45
     46        pthread_values *& Next( pthread_values * n ) {
     47                return (pthread_values *)Next( (Colable *)n );
     48        }
     49}
     50
     51struct pthread_keys {
    5052        bool in_use;
    5153        void (*destructor)( void * );
    52         Sequence(Pthread_values) threads;
    53 };  // Pthread keys
    54 
    55 static void ?{}(Pthread_keys& k){
     54        Sequence(pthread_values) threads;
     55};
     56
     57static void ?{}(pthread_keys& k){
    5658        k.threads{};
    5759}
    5860
    5961// Create storage separately to ensure no constructors are called.
    60 static Pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16)));
     62static pthread_keys cfa_pthread_keys_storage[PTHREAD_KEYS_MAX] __attribute__((aligned (16)));
    6163
    6264static void init_pthread_storage(){
     
    6668}
    6769
    68 #define cfa_pthread_keys ((Pthread_keys *)cfa_pthread_keys_storage)
     70#define cfa_pthread_keys ((pthread_keys *)cfa_pthread_keys_storage)
    6971
    7072/* Controlling the iterations of destructors for thread-specific data.  */
     
    115117/* mutex helper routines */
    116118static void mutex_check(pthread_mutex_t* t){
    117         // Use double check to improve performance. Check is safe on x86; volatile prevents compiler reordering
     119        // Use double check to improve performance.
     120        // Check is safe on x86; volatile prevents compiler reordering
    118121        volatile pthread_mutex_t *const mutex_ = t;
     122
    119123        // SKULLDUGGERY: not a portable way to access the kind field, /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h
    120124        int _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock;
     125
    121126        // if pthread_mutex_t is initialized by PTHREAD_MUTEX_INITIALIZER, _lock_val should be 0
    122         if ( _lock_val == 0 ) {                 // static initialized ?
    123                 lock(magic_mutex_check);        // race
     127        if ( _lock_val == 0 ) {
     128                lock(magic_mutex_check);
    124129                _lock_val = ((pthread_mutex_t *)mutex_)->__data.__lock;
    125                 if ( _lock_val == 0 ) {         // static initialized ?
    126                 pthread_mutex_init( t, NULL );
    127                 } // if
    128                 unlock(magic_mutex_check);      // race
    129         } // if
     130                if ( _lock_val == 0 ) {
     131                        pthread_mutex_init( t, NULL );
     132                }
     133                unlock(magic_mutex_check);
     134        }
    130135} // mutex_check
    131136
     
    168173};
    169174
    170 
    171 /*
    172 static const cfaPthread_attr_t default_attrs = {
    173         PTHREAD_SCOPE_SYSTEM,
    174         PTHREAD_CREATE_JOINABLE,
    175         (size_t)DEFAULT_STACK_SIZE,
    176         (void *)NULL,
    177         0,
    178         PTHREAD_EXPLICIT_SCHED,
    179         {0}
    180 };
    181 */
    182 
    183 
    184 
    185175static cfaPthread_attr_t* get(const pthread_attr_t* attr){
    186176        static_assert(sizeof(pthread_attr_t) >= sizeof(cfaPthread_attr_t),"sizeof(pthread_attr_t) < sizeof(cfaPthread_attr_t)");
     
    198188        cfaPthread_attr_t attr;
    199189        pthread_t pthreadId;
    200         void *joinval;                                                                          // pthreads return value
    201         pthread_attr_t pthread_attr;                                            // pthread attributes
    202         void *(*start_routine)(void *);                     // routine start
    203         void *arg;                                                              // thread parameter
    204         Pthread_values* pthreadData;
    205         bool isTerminated;                                  // flag used for tryjoin
     190
     191        // pthreads return value
     192        void *joinval;
     193
     194        // pthread attributes
     195        pthread_attr_t pthread_attr;
     196
     197        void *(*start_routine)(void *);
     198        void *start_arg;
     199
     200        // thread local data
     201        pthread_values* pthreadData;
     202
     203        // flag used for tryjoin
     204        bool isTerminated;
    206205};
    207206
     
    209208//  cfaPthread entry point
    210209void main(cfaPthread& _thread) with(_thread){
    211         joinval =  start_routine(arg);
     210        joinval =  start_routine(start_arg);
    212211        isTerminated = true;
    213 }
    214 
    215 // generate pthread_t by cfaPthread ptr
    216 static pthread_t create( cfaPthread *p ) {
    217         static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*),"sizeof(pthread_t) < sizeof(cfaPthread*)");
    218         return (pthread_t)p;
    219212}
    220213
     
    224217}
    225218
    226 static void pthread_deletespecific_( Pthread_values* values )  { // see uMachContext::invokeTask
    227         Pthread_values* value;
    228         Pthread_keys* key;
     219static void pthread_deletespecific_( pthread_values* values )  { // see uMachContext::invokeTask
     220        pthread_values* value;
     221        pthread_keys* key;
    229222        bool destcalled = true;
    230223        if (values != NULL){
     
    258251static void ^?{}(cfaPthread & mutex t){
    259252        // delete pthread local storage
    260         Pthread_values* values = t.pthreadData;
     253        pthread_values * values = t.pthreadData;
    261254        pthread_deletespecific_(values);
    262255}
    263256
    264257static void ?{}(cfaPthread &t, pthread_t* _thread, const pthread_attr_t * _attr,void *(*start_routine)(void *), void * arg) {
     258        static_assert(sizeof(pthread_t) >= sizeof(cfaPthread*), "pthread_t too small to hold a pointer: sizeof(pthread_t) < sizeof(cfaPthread*)");
    265259
    266260        // set up user thread stackSize
     
    269263
    270264        // initialize _thread & cfaPthread id
    271         t.pthreadId = create(&t);
    272         *_thread = t.pthreadId;
     265        *_thread = t.pthreadId = (pthread_t)(&t);
    273266
    274267        // if attr null, self attr will be set as default_attrs; else set to attr
     
    277270        // init start routine and arguments
    278271        t.start_routine = start_routine;
    279         t.arg = arg;
     272        t.start_arg = arg;
    280273        t.pthreadData = NULL;
    281 }   // not used
     274}
    282275
    283276
     
    287280        int pthread_attr_init(pthread_attr_t *attr) libcfa_public __THROW {
    288281                cfaPthread_attr_t* _attr = get(attr);
    289                 ?{}(*_attr);
    290                 *_attr = default_attrs;
     282                ?{}(*_attr, default_attrs);
    291283                return 0;
    292284        }
     
    360352        // and destroyed with pthread_attr_destroy when no longer needed.
    361353        int pthread_getattr_np( pthread_t threadID, pthread_attr_t *attr ) libcfa_public __THROW { // GNU extension
    362                 // race condition during copy
    363                 cfaPthread_attr_t* _attr = get(attr);
    364                 ?{}(*_attr);
    365                 if (_attr == NULL){
    366                         return ENOMEM;
    367                 }   // if
    368                 *_attr = lookup( threadID )->attr; // copy all fields
     354                check_nonnull(attr);
     355
     356                // copy all fields
     357                *get(attr) = lookup( threadID )->attr;
     358
    369359                return 0;
    370360        } // pthread_getattr_np
     
    376366                cfaPthread *t = alloc();
    377367                (*t){_thread, attr, start_routine, arg};
    378                 //init_user_pthread(*t, _thread, attr, start_routine, arg);
    379                 if (t == NULL) return EAGAIN; //no resource
    380                 return 0;
    381         }   //pthread_create_
     368                return 0;
     369        }
    382370
    383371
    384372        int pthread_join(pthread_t _thread, void **value_ptr) libcfa_public __THROW {
    385                 if (_thread == NULL) return EINVAL;   // if thread is invalid
     373                // if thread is invalid
     374                if (_thread == NULL) return EINVAL;
    386375                if (_thread == pthread_self()) return EDEADLK;
    387                 cfaPthread* p = lookup(_thread);    // get user thr pointer
     376
     377                // get user thr pointer
     378                cfaPthread* p = lookup(_thread);
    388379                try {
    389380                        join(*p);
    390                 } catchResume (ThreadCancelled(cfaPthread) * cancel) {} // if thread called pthread_exit
    391                 if (value_ptr != NULL ) *value_ptr = p->joinval;   // fetch result
    392                 delete(p);
    393                 return 0;
    394         }   //pthread_join_
    395 
    396         int pthread_tryjoin_np(pthread_t _thread, void **value_ptr) libcfa_public __THROW {
    397                 if (_thread == NULL) return EINVAL;  // if thread is invalid
    398                 if (_thread == pthread_self()) return EDEADLK;
    399                 cfaPthread* p = lookup(_thread);
    400                 if (!p->isTerminated) return EBUSY; // thread not finished ?
    401                 join( *p );
     381                }
     382                // if thread called pthread_exit
     383                catchResume (ThreadCancelled(cfaPthread) * cancel) {}
     384
     385                // fetch result
    402386                if (value_ptr != NULL ) *value_ptr = p->joinval;
    403387                delete(p);
    404388                return 0;
    405         }   //pthread_join_
     389        }
     390
     391        int pthread_tryjoin_np(pthread_t _thread, void **value_ptr) libcfa_public __THROW {
     392                // if thread is invalid
     393                if (_thread == NULL) return EINVAL;
     394                if (_thread == pthread_self()) return EDEADLK;
     395
     396                cfaPthread* p = lookup(_thread);
     397
     398                // thread not finished ?
     399                if (!p->isTerminated) return EBUSY;
     400
     401                join( *p );
     402
     403                if (value_ptr != NULL ) *value_ptr = p->joinval;
     404                delete(p);
     405                return 0;
     406        }
    406407
    407408        pthread_t pthread_self(void) libcfa_public __THROW {
    408                 return (pthread_t)((char*)active_thread()-(sizeof(cfaPthread)-sizeof(thread$)));
    409         }   //pthread_self_
     409                return (pthread_t)((uintptr_t)active_thread() - (sizeof(cfaPthread) - sizeof(thread$)));
     410        }
    410411
    411412        void pthread_exit(void * status) libcfa_public __THROW {
     
    551552
    552553                // Remove key from all threads with a value.
    553                 Pthread_values& p;
    554                 Sequence(Pthread_values)& head = cfa_pthread_keys[key].threads;
    555                 for ( SeqIter(Pthread_values) iter = { head }; iter | p; ) {
     554                pthread_values& p;
     555                Sequence(pthread_values)& head = cfa_pthread_keys[key].threads;
     556                for ( SeqIter(pthread_values) iter = { head }; iter | p; ) {
    556557                        remove(head, p);
    557558                        p.in_use = false;
     
    565566                cfaPthread* t = lookup(pthread_self());
    566567                // if current thread's pthreadData is NULL; initialize it
    567                 Pthread_values* values;
     568                pthread_values* values;
    568569                if (t->pthreadData == NULL){
    569570                        values = anew( PTHREAD_KEYS_MAX);
     
    582583                        return EINVAL;
    583584                } // if
    584                 Pthread_values &entry = values[key];
     585                pthread_values &entry = values[key];
    585586                if ( ! entry.in_use ) {
    586587                        entry.in_use = true;
     
    599600                if (t->pthreadData == NULL) return NULL;
    600601                lock(key_lock);
    601                 Pthread_values &entry = ((Pthread_values *)t->pthreadData)[key];
     602                pthread_values &entry = ((pthread_values *)t->pthreadData)[key];
    602603                if ( ! entry.in_use ) {
    603604                        unlock( key_lock );
     
    611612
    612613        //######################### Parallelism #########################
    613         void pthread_delete_kernel_threads_() libcfa_public __THROW {   // see uMain::~uMain
     614        void pthread_delete_kernel_threads_() __THROW { // see uMain::~uMain
    614615                Pthread_kernel_threads& p;
    615616                for ( StackIter(Pthread_kernel_threads) iter = {cfa_pthreads_kernel_threads}; iter | p; ) {
     
    618619        } // pthread_delete_kernel_threads_
    619620
    620         int pthread_getconcurrency( void ) libcfa_public __THROW {      // XOPEN extension
     621        int pthread_getconcurrency( void ) __THROW {    // XOPEN extension
    621622                return cfa_pthreads_kernel_threads_zero ? 0 : cfa_pthreads_no_kernel_threads;
    622623        } // pthread_getconcurrency
    623624
    624625        int pthread_setconcurrency( int new_level ) libcfa_public __THROW { // XOPEN extension
    625           if ( new_level < 0 ) return EINVAL;
    626           if ( new_level == 0 ) {
    627                 cfa_pthreads_kernel_threads_zero = true;        // remember set to zero, but ignore
    628                 return 0;                                       // do not do kernel thread management
    629           } // exit
    630           cfa_pthreads_kernel_threads_zero = false;
    631           lock( concurrency_lock );
    632           for ( ; new_level > cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads += 1 ) { // add processors ?
    633                 push(cfa_pthreads_kernel_threads, *new() );
    634           } // for
    635           for ( ; new_level < cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads -= 1 ) { // remove processors ?
    636                 delete(&pop(cfa_pthreads_kernel_threads));
    637           } // for
    638           unlock( concurrency_lock );
    639           return 0;
     626                if ( new_level < 0 ) return EINVAL;
     627                if ( new_level == 0 ) {
     628                        cfa_pthreads_kernel_threads_zero = true;        // remember set to zero, but ignore
     629                        return 0;                                       // do not do kernel thread management
     630                } // exit
     631                cfa_pthreads_kernel_threads_zero = false;
     632                lock( concurrency_lock );
     633                for ( ; new_level > cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads += 1 ) { // add processors ?
     634                        push(cfa_pthreads_kernel_threads, *new() );
     635                } // for
     636                for ( ; new_level < cfa_pthreads_no_kernel_threads; cfa_pthreads_no_kernel_threads -= 1 ) { // remove processors ?
     637                        delete(&pop(cfa_pthreads_kernel_threads));
     638                } // for
     639                unlock( concurrency_lock );
     640                return 0;
    640641        } // pthread_setconcurrency
    641642
     
    644645
    645646         int pthread_sigmask( int /* how */, const sigset_t * /* set */, sigset_t * /* oset */ ) libcfa_public __THROW {
    646                  return 0;
     647                abort( "pthread_sigmask : not implemented" );
     648                return 0;
    647649         } // pthread_sigmask
    648650
     
    657659
    658660        int pthread_sigqueue(pthread_t , int sig, const union sigval) libcfa_public __THROW {
     661                abort( "pthread_sigqueue : not implemented" );
    659662                return 0;
    660663        } // pthread_sigqueue
     
    662665        //######################### Scheduling #########################
    663666        int pthread_detach( pthread_t threadID ) __THROW {
    664                 abort( "pthread_detach" );
     667                abort( "pthread_detach : not implemented" );
    665668                return 0;
    666669        } // pthread_detach
     
    683686
    684687        int pthread_mutexattr_destroy( pthread_mutexattr_t * /* attr */ ) libcfa_public __THROW {
    685         return 0;
     688                return 0;
    686689        } // pthread_mutexattr_destroy
    687690
    688691        int pthread_mutexattr_setpshared( pthread_mutexattr_t * /* attr */, int /* pshared */ ) libcfa_public __THROW {
    689         return 0;
     692                return 0;
    690693        } // pthread_mutexattr_setpshared
    691694
    692695        int pthread_mutexattr_getpshared( const pthread_mutexattr_t * /* attr */, int * /* pshared */ ) libcfa_public __THROW {
    693         return 0;
     696                return 0;
    694697        } // pthread_mutexattr_getpshared
    695698
    696699        int pthread_mutexattr_setprotocol( pthread_mutexattr_t * /* attr */, int /* protocol */ ) libcfa_public __THROW {
    697         return 0;
     700                return 0;
    698701        } // pthread_mutexattr_setprotocol
    699702
    700703        int pthread_mutexattr_getprotocol( const pthread_mutexattr_t * /* attr */, int * /* protocol */ ) libcfa_public __THROW {
    701         return 0;
     704                return 0;
    702705        } // pthread_mutexattr_getprotocol
    703706
    704707        int pthread_mutexattr_setprioceiling( pthread_mutexattr_t * /* attr */, int /* prioceiling */ ) libcfa_public __THROW {
    705         return 0;
     708                return 0;
    706709        } // pthread_mutexattr_setprioceiling
    707710
    708711        int pthread_mutexattr_getprioceiling( const pthread_mutexattr_t * /* attr */, int * /* ceiling */ ) libcfa_public __THROW {
    709         return 0;
     712                return 0;
    710713        } // pthread_mutexattr_getprioceiling
    711714
    712715        int pthread_mutex_setprioceiling( pthread_mutex_t * /* mutex */, int /* prioceiling */, int * /* old_ceiling */ ) libcfa_public __THROW {
    713         return 0;
     716                return 0;
    714717        } // pthread_mutex_setprioceiling
    715718
    716719        int pthread_mutex_getprioceiling( const pthread_mutex_t * /* mutex */, int * /* ceiling */ ) libcfa_public __THROW {
    717         return 0;
     720                return 0;
    718721        } // pthread_mutex_getprioceiling
    719722
    720723        int pthread_mutexattr_gettype( __const pthread_mutexattr_t * __restrict /* __attr */, int * __restrict /* __kind */ ) libcfa_public __THROW {
    721         return 0;
     724                return 0;
    722725        } // pthread_mutexattr_gettype
    723726
    724727        int pthread_mutexattr_settype( pthread_mutexattr_t * /* __attr */, int /* __kind */ ) libcfa_public __THROW {
    725         return 0;
     728                return 0;
    726729        } // pthread_mutexattr_settype
    727730
Note: See TracChangeset for help on using the changeset viewer.