Changeset 085bd54 in mainline for libc/generic/psthread.c


Ignore:
Timestamp:
2006-06-06T15:16:08Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
63bb83e
Parents:
d7eafd8
Message:

Revised ipc. Now it is preferrable to use only functions from async.h, they
take care of correct buffering, waiting for answers etc.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libc/generic/psthread.c

    rd7eafd8 r085bd54  
    4343
    4444static LIST_INITIALIZE(ready_list);
     45static LIST_INITIALIZE(serialized_list);
    4546static LIST_INITIALIZE(manager_list);
    4647
     
    4950
    5051static atomic_t psthread_futex = FUTEX_INITIALIZER;
     52/** Count of real threads that are in async_serialized mode */
     53static int serialized_threads; /* Protected by async_futex */
     54/** Thread-local count of serialization. If >0, we must not preempt */
     55static __thread serialization_count;
     56/** Counter of threads residing in async_manager */
     57static int threads_in_manager;
    5158
    5259/** Setup PSthread information into TCB structure */
     
    7885}
    7986
    80 /** Function to preempt to other pseudo thread without adding
    81  * currently running pseudo thread to ready_list.
    82  */
    83 void psthread_exit(void)
    84 {
    85         psthread_data_t *pt;
    86 
    87         futex_down(&psthread_futex);
    88 
    89         if (!list_empty(&ready_list))
    90                 pt = list_get_instance(ready_list.next, psthread_data_t, link);
    91         else if (!list_empty(&manager_list))
    92                 pt = list_get_instance(manager_list.next, psthread_data_t, link);
    93         else {
    94                 printf("Cannot find suitable psthread to run.\n");
    95                 _exit(0);
    96         }
    97         list_remove(&pt->link);
    98         futex_up(&psthread_futex);
    99 
    100         context_restore(&pt->ctx);
    101         /* Never reached */
    102 }
    103 
    10487/** Function that is called on entry to new uspace thread */
    10588void psthread_main(void)
     
    10790        psthread_data_t *pt = __tcb_get()->pst_data;
    10891
     92        serialization_count = 0; // TODO: WHY HERE?
    10993        pt->retval = pt->func(pt->arg);
    11094
     
    11397                list_append(&pt->waiter->link, &ready_list);
    11498
    115         psthread_exit();
     99        psthread_schedule_next_adv(PS_FROM_DEAD);
    116100}
    117101
     
    128112int psthread_schedule_next_adv(pschange_type ctype)
    129113{
    130         psthread_data_t *pt;
     114        psthread_data_t *srcpt, *dstpt;
    131115        int retval = 0;
    132116       
     
    136120                goto ret_0;
    137121
    138         if (ctype == PS_FROM_MANAGER && list_empty(&ready_list)) {
    139                 goto ret_0;
     122        if (ctype == PS_FROM_MANAGER) {
     123                if (list_empty(&ready_list) && list_empty(&serialized_list))
     124                        goto ret_0;
     125                /* Do not preempt if there is not sufficient count of thread managers */
     126                if (list_empty(&serialized_list) && threads_in_manager <= serialized_threads) {
     127                        goto ret_0;
     128                }
    140129        }
    141130        /* If we are going to manager and none exists, create it */
    142         while (ctype == PS_TO_MANAGER && list_empty(&manager_list)) {
    143                 futex_up(&psthread_futex);
    144                 async_create_manager();
    145                 futex_down(&psthread_futex);
    146         }
    147 
    148         pt = __tcb_get()->pst_data;
    149         if (!context_save(&pt->ctx))
    150                 return 1; // futex_up already done here
    151 
    152         if (ctype == PS_PREEMPT)
    153                 list_append(&pt->link, &ready_list);
    154         else if (ctype == PS_FROM_MANAGER)
    155                 list_append(&pt->link, &manager_list);
     131        if (ctype == PS_TO_MANAGER || ctype == PS_FROM_DEAD) {
     132                while (list_empty(&manager_list)) {
     133                        futex_up(&psthread_futex);
     134                        async_create_manager();
     135                        futex_down(&psthread_futex);
     136                }
     137        }
    156138       
    157         if (ctype == PS_TO_MANAGER)
    158                 pt = list_get_instance(manager_list.next,psthread_data_t, link);
    159         else
    160                 pt = list_get_instance(ready_list.next, psthread_data_t, link);
    161         list_remove(&pt->link);
    162 
    163         futex_up(&psthread_futex);
    164         context_restore(&pt->ctx);
     139        if (ctype != PS_FROM_DEAD) {
     140                /* Save current state */
     141                srcpt = __tcb_get()->pst_data;
     142                if (!context_save(&srcpt->ctx)) {
     143                        if (serialization_count)
     144                                srcpt->flags &= ~PSTHREAD_SERIALIZED;
     145                        return 1; // futex_up already done here
     146                }
     147
     148                /* Save myself to correct run list */
     149                if (ctype == PS_PREEMPT)
     150                        list_append(&srcpt->link, &ready_list);
     151                else if (ctype == PS_FROM_MANAGER) {
     152                        list_append(&srcpt->link, &manager_list);
     153                        threads_in_manager--;
     154                } /* If ctype == PS_TO_MANAGER, don't save ourselves to any list, we should
     155                   * already be somewhere, or we will be lost */
     156        }
     157
     158        /* Choose new thread to run */
     159        if (ctype == PS_TO_MANAGER || ctype == PS_FROM_DEAD) {
     160                dstpt = list_get_instance(manager_list.next,psthread_data_t, link);
     161                if (serialization_count && ctype == PS_TO_MANAGER) {
     162                        serialized_threads++;
     163                        srcpt->flags |= PSTHREAD_SERIALIZED;
     164                }
     165                threads_in_manager++;
     166        } else {
     167                if (!list_empty(&serialized_list)) {
     168                        dstpt = list_get_instance(serialized_list.next, psthread_data_t, link);
     169                        serialized_threads--;
     170                } else
     171                        dstpt = list_get_instance(ready_list.next, psthread_data_t, link);
     172        }
     173        list_remove(&dstpt->link);
     174
     175        futex_up(&psthread_futex);
     176        context_restore(&dstpt->ctx);
    165177
    166178ret_0:
     
    183195        pt = (psthread_data_t *) psthrid;
    184196
    185         if (!pt->finished) {
    186                 mypt = __tcb_get()->pst_data;
    187                 if (context_save(&((psthread_data_t *) mypt)->ctx)) {
    188                         pt->waiter = (psthread_data_t *) mypt;
    189                         psthread_exit();
    190                 }
    191         }
     197        /* TODO */
     198        printf("join unsupported\n");
     199        _exit(1);
     200
    192201        retval = pt->retval;
    193202
     
    224233        pt->finished = 0;
    225234        pt->waiter = NULL;
     235        pt->flags = 0;
    226236
    227237        context_save(&pt->ctx);
     
    239249        pt = (psthread_data_t *) psthrid;
    240250        futex_down(&psthread_futex);
    241         list_append(&pt->link, &ready_list);
     251        if ((pt->flags & PSTHREAD_SERIALIZED))
     252                list_append(&pt->link, &serialized_list);
     253        else
     254                list_append(&pt->link, &ready_list);
    242255        futex_up(&psthread_futex);
    243256}
     
    272285        return (pstid_t)__tcb_get()->pst_data;
    273286}
     287
     288/** Disable preemption
     289 *
     290 * If the thread wants to send several message in row and does not want
     291 * to be preempted, it should start async_serialize_start() in the beginning
     292 * of communication and async_serialize_end() in the end. If it is a
     293 * true multithreaded application, it should protect the communication channel
     294 * by a futex as well. Interrupt messages will can still be preempted.
     295 */
     296void psthread_inc_sercount(void)
     297{
     298        serialization_count++;
     299}
     300
     301void psthread_dec_sercount(void)
     302{
     303        serialization_count--;
     304}
Note: See TracChangeset for help on using the changeset viewer.