Changeset 2654afb in mainline for uspace/lib/c/generic/fibril.c


Ignore:
Timestamp:
2015-06-16T22:17:31Z (9 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
47726b5e, cf3aee19, e96047c
Parents:
c721d26
Message:

Remove support for the abandoned concept of fibril serialization.
Streamline fibril_switch() a little bit.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/fibril.c

    rc721d26 r2654afb  
    5757/**
    5858 * This futex serializes access to ready_list,
    59  * serialized_list, manager_list and fibril_list.
     59 * manager_list and fibril_list.
    6060 */
    6161static futex_t fibril_futex = FUTEX_INITIALIZER;
    6262
    6363static LIST_INITIALIZE(ready_list);
    64 static LIST_INITIALIZE(serialized_list);
    6564static LIST_INITIALIZE(manager_list);
    6665static LIST_INITIALIZE(fibril_list);
    67 
    68 /** Number of threads that are executing a manager fibril. */
    69 static int threads_in_manager;
    70 
    71 /**
    72  * Number of threads that are executing a manager fibril
    73  * and are serialized. Protected by async_futex.
    74  */
    75 static int serialized_threads;
    76 
    77 /** Fibril-local count of serialization. If > 0, we must not preempt */
    78 static fibril_local int serialization_count;
    7966
    8067/** Function that spans the whole life-cycle of a fibril.
     
    161148int fibril_switch(fibril_switch_type_t stype)
    162149{
    163         int retval = 0;
    164        
    165         futex_lock(&fibril_futex);
    166 
    167         if (stype == FIBRIL_PREEMPT && list_empty(&ready_list))
    168                 goto ret_0;
    169        
    170         if (stype == FIBRIL_FROM_MANAGER) {
    171                 if ((list_empty(&ready_list)) && (list_empty(&serialized_list)))
    172                         goto ret_0;
    173                
    174                 /*
    175                  * Do not preempt if there is not enough threads to run the
    176                  * ready fibrils which are not serialized.
    177                  */
    178                 if ((list_empty(&serialized_list)) &&
    179                     (threads_in_manager <= serialized_threads)) {
    180                         goto ret_0;
     150        futex_lock(&fibril_futex);
     151
     152        switch (stype) {
     153        case FIBRIL_PREEMPT:
     154        case FIBRIL_FROM_MANAGER:
     155                if (list_empty(&ready_list)) {
     156                        futex_unlock(&fibril_futex);
     157                        return 0;
    181158                }
    182         }
    183        
    184         /* If we are going to manager and none exists, create it */
    185         if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) {
     159                break;
     160        case FIBRIL_TO_MANAGER:
     161        case FIBRIL_FROM_DEAD:
    186162                /* Make sure the async_futex is held. */
    187163                assert((atomic_signed_t) async_futex.val.count <= 0);
    188164
     165                /* If we are going to manager and none exists, create it */
    189166                while (list_empty(&manager_list)) {
    190167                        futex_unlock(&fibril_futex);
     
    192169                        futex_lock(&fibril_futex);
    193170                }
     171                break;
    194172        }
    195173       
     
    199177                /* Save current state */
    200178                if (!context_save(&srcf->ctx)) {
    201                         if (serialization_count)
    202                                 srcf->flags &= ~FIBRIL_SERIALIZED;
    203                        
    204179                        if (srcf->clean_after_me) {
    205180                                /*
     
    226201                }
    227202               
    228                 /* Save myself to the correct run list */
    229                 if (stype == FIBRIL_PREEMPT)
     203                /* Put the current fibril into the correct run list */
     204                switch (stype) {
     205                case FIBRIL_PREEMPT:
    230206                        list_append(&srcf->link, &ready_list);
    231                 else if (stype == FIBRIL_FROM_MANAGER) {
     207                        break;
     208                case FIBRIL_FROM_MANAGER:
    232209                        list_append(&srcf->link, &manager_list);
    233                         threads_in_manager--;
    234                 } else {
     210                        break;
     211                default:
     212                        assert(stype == FIBRIL_TO_MANAGER);
     213
    235214                        /*
    236                          * If stype == FIBRIL_TO_MANAGER, don't put ourselves to
    237                          * any list, we should already be somewhere, or we will
    238                          * be lost.
     215                         * Don't put the current fibril into any list, it should
     216                         * already be somewhere, or it will be lost.
    239217                         */
     218                        break;
    240219                }
    241220        }
    242221       
     222        fibril_t *dstf;
     223
    243224        /* Choose a new fibril to run */
    244         fibril_t *dstf;
    245         if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) {
     225        switch (stype) {
     226        case FIBRIL_TO_MANAGER:
     227        case FIBRIL_FROM_DEAD:
    246228                dstf = list_get_instance(list_first(&manager_list), fibril_t,
    247229                    link);
    248                 if (serialization_count && stype == FIBRIL_TO_MANAGER) {
    249                         serialized_threads++;
    250                         srcf->flags |= FIBRIL_SERIALIZED;
    251                 }
    252                 threads_in_manager++;
    253230               
    254231                if (stype == FIBRIL_FROM_DEAD)
    255232                        dstf->clean_after_me = srcf;
    256         } else {
    257                 if (!list_empty(&serialized_list)) {
    258                         dstf = list_get_instance(list_first(&serialized_list),
    259                             fibril_t, link);
    260                         serialized_threads--;
    261                 } else {
    262                         dstf = list_get_instance(list_first(&ready_list),
    263                             fibril_t, link);
    264                 }
    265         }
     233                break;
     234        default:
     235                dstf = list_get_instance(list_first(&ready_list), fibril_t,
     236                    link);
     237                break;
     238        }
     239
    266240        list_remove(&dstf->link);
    267241       
     
    276250        context_restore(&dstf->ctx);
    277251        /* not reached */
    278        
    279 ret_0:
    280         futex_unlock(&fibril_futex);
    281         return retval;
    282252}
    283253
     
    346316       
    347317        futex_lock(&fibril_futex);
    348        
    349         if ((fibril->flags & FIBRIL_SERIALIZED))
    350                 list_append(&fibril->link, &serialized_list);
    351         else
    352                 list_append(&fibril->link, &ready_list);
    353        
     318        list_append(&fibril->link, &ready_list);
    354319        futex_unlock(&fibril_futex);
    355320}
     
    374339{
    375340        futex_lock(&fibril_futex);
    376        
    377341        if (!list_empty(&manager_list))
    378342                list_remove(list_first(&manager_list));
    379        
    380343        futex_unlock(&fibril_futex);
    381344}
     
    391354}
    392355
    393 /** Disable preemption
    394  *
    395  * If the fibril wants to send several message in a row and does not want to be
    396  * preempted, it should start async_serialize_start() in the beginning of
    397  * communication and async_serialize_end() in the end. If it is a true
    398  * multithreaded application, it should protect the communication channel by a
    399  * futex as well.
    400  *
    401  */
    402 void fibril_inc_sercount(void)
    403 {
    404         serialization_count++;
    405 }
    406 
    407 /** Restore the preemption counter to the previous state. */
    408 void fibril_dec_sercount(void)
    409 {
    410         serialization_count--;
    411 }
    412 
    413 int fibril_get_sercount(void)
    414 {
    415         return serialization_count;
    416 }
    417 
    418356/** @}
    419357 */
Note: See TracChangeset for help on using the changeset viewer.