Changeset 085bd54 in mainline for libc


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.

Location:
libc
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • libc/generic/async.c

    rd7eafd8 r085bd54  
    135135} connection_t;
    136136
    137 
     137/** Identifier of incoming connection handled by current thread */
    138138__thread connection_t *PS_connection;
     139/** If true, it is forbidden to use async_req functions and
     140 *  all preemption is disabled */
     141__thread int in_interrupt_handler;
    139142
    140143static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
     
    226229
    227230        wd->timedout = 0;
     231        wd->inlist = 1;
    228232
    229233        tmp = timeout_list.next;
     
    295299        conn = PS_connection;
    296300
    297         if (usecs < 0) /* TODO: let it get through the ipc_call once */
    298                 return 0;
    299 
    300301        futex_down(&async_futex);
    301302
     
    308309        /* If nothing in queue, wait until something appears */
    309310        while (list_empty(&conn->msg_queue)) {
    310                 if (usecs) {
    311                         conn->wdata.inlist = 1;
     311                if (usecs)
    312312                        insert_timeout(&conn->wdata);
    313                 }
     313
    314314                conn->wdata.active = 0;
    315315                psthread_schedule_next_adv(PS_TO_MANAGER);
     
    363363        PS_connection = (connection_t *)arg;
    364364        PS_connection->cthread(PS_connection->callid, &PS_connection->call);
    365 
    366365        /* Remove myself from connection hash table */
    367366        futex_down(&async_futex);
     
    436435        switch (IPC_GET_METHOD(*call)) {
    437436        case IPC_M_INTERRUPT:
     437                in_interrupt_handler = 1;
    438438                (*interrupt_received)(callid,call);
     439                in_interrupt_handler = 0;
    439440                return;
    440441        case IPC_M_CONNECT_ME_TO:
     
    486487
    487488/** Endless loop dispatching incoming calls and answers */
    488 int async_manager(void)
     489static int async_manager_worker(void)
    489490{
    490491        ipc_call_t call;
     
    522523                }
    523524
    524                 if (callid & IPC_CALLID_ANSWERED)
     525                if (callid & IPC_CALLID_ANSWERED) {
    525526                        continue;
     527                }
    526528
    527529                handle_call(callid, &call);
     
    538540static int async_manager_thread(void *arg)
    539541{
     542        in_interrupt_handler = 0; // TODO: Handle TLS better
    540543        futex_up(&async_futex); /* async_futex is always locked when entering
    541544                                * manager */
    542         async_manager();
     545        async_manager_worker();
    543546}
    544547
     
    608611        amsg_t *msg;
    609612
     613        if (in_interrupt_handler) {
     614                printf("Cannot send asynchronou request in interrupt handler.\n");
     615                _exit(1);
     616        }
     617
    610618        msg = malloc(sizeof(*msg));
    611619        msg->done = 0;
     
    628636{
    629637        amsg_t *msg;
     638
     639        if (in_interrupt_handler) {
     640                printf("Cannot send asynchronou request in interrupt handler.\n");
     641                _exit(1);
     642        }
    630643
    631644        msg = malloc(sizeof(*msg));
     
    699712        msg->wdata.ptid = psthread_get_id();
    700713        msg->wdata.active = 0;
    701         msg->wdata.inlist = 1;
    702 
    703714        insert_timeout(&msg->wdata);
    704715
     
    726737        amsg_t *msg;
    727738       
     739        if (in_interrupt_handler) {
     740                printf("Cannot call async_usleep in interrupt handler.\n");
     741                _exit(1);
     742        }
     743
    728744        msg = malloc(sizeof(*msg));
    729745        if (!msg)
     
    731747
    732748        msg->wdata.ptid = psthread_get_id();
    733         msg->wdata.inlist = 1;
    734749        msg->wdata.active = 0;
    735750
     
    757772        interrupt_received = conn;
    758773}
     774
     775/* Primitive functions for simple communication */
     776void async_msg_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
     777                 ipcarg_t arg2, ipcarg_t arg3)
     778{
     779        ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, !in_interrupt_handler);
     780}
     781
     782void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2)
     783{
     784        ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, !in_interrupt_handler);
     785}
  • libc/generic/io/stream.c

    rd7eafd8 r085bd54  
    6565
    6666        while (i < count) {
    67                 if (sync_send_2(streams[0].phone, CONSOLE_GETCHAR, 0, 0, &r0, &r1) < 0) {
     67                if (async_req_2(streams[0].phone, CONSOLE_GETCHAR, 0, 0, &r0, &r1) < 0) {
    6868                        return -1;
    6969                }
     
    7979
    8080        for (i = 0; i < count; i++)
    81                 send_call(streams[1].phone, CONSOLE_PUTCHAR, ((const char *)buf)[i]);
     81                async_msg(streams[1].phone, CONSOLE_PUTCHAR, ((const char *)buf)[i]);
    8282       
    8383        return count;
     
    131131{
    132132        int c = 0;
    133        
     133
    134134        while (((streams[c].w) || (streams[c].r)) && (c < FDS))
    135135                c++;
     
    160160ssize_t write(int fd, const void *buf, size_t count)
    161161{
     162//      __SYSCALL3(SYS_IO, 1, (sysarg_t)buf, (sysarg_t) count);
     163//      return count;
    162164        if (fd < FDS)
    163165                return streams[fd].w(streams[fd].param, buf, count);
  • libc/generic/ipc.c

    rd7eafd8 r085bd54  
    438438}
    439439
    440 /* Primitive functions for simple communication */
    441 void send_call_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
    442                  ipcarg_t arg2, ipcarg_t arg3)
    443 {
    444         ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, 1);
    445 }
    446 
    447 void send_call_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2)
    448 {
    449         ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, 1);
    450 }
    451 
    452 void nsend_call_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
    453                   ipcarg_t arg2, ipcarg_t arg3)
    454 {
    455         ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, 0);
    456 }
    457 
    458 void nsend_call_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2)
    459 {
    460         ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, 0);
    461 }
    462 
  • 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}
  • libc/include/async.h

    rd7eafd8 r085bd54  
    3838typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call);
    3939
    40 int async_manager(void);
     40static inline void async_manager(void)
     41{
     42        psthread_schedule_next_adv(PS_TO_MANAGER);
     43}
     44
    4145ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
    4246static inline ipc_callid_t async_get_call(ipc_call_t *data)
     
    5862 * @return Return code of message
    5963 */
    60 static inline ipcarg_t sync_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, ipcarg_t *r1, ipcarg_t *r2)
     64static inline ipcarg_t async_req_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, ipcarg_t *r1, ipcarg_t *r2)
    6165{
    6266        ipc_call_t result;
     
    7175        return rc;
    7276}
    73 #define sync_send(phoneid, method, arg1, r1) sync_send_2(phoneid, method, arg1, 0, r1, 0)
     77#define async_req(phoneid, method, arg1, r1) async_req_2(phoneid, method, arg1, 0, r1, 0)
    7478
    75 static inline ipcarg_t sync_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
     79static inline ipcarg_t async_req_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
    7680                                   ipcarg_t arg2, ipcarg_t arg3, ipcarg_t *r1,
    7781                                   ipcarg_t *r2, ipcarg_t *r3)
     
    103107
    104108
     109/* Primitve functions for IPC communication */
     110void async_msg_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
     111                 ipcarg_t arg3);
     112void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2);
     113#define async_msg(ph,m,a1) async_msg_2(ph,m,a1,0)
     114
     115static inline void async_serialize_start(void)
     116{
     117        psthread_inc_sercount();
     118}
     119static inline void async_serialize_end(void)
     120{
     121        psthread_dec_sercount();
     122}
     123
    105124extern atomic_t async_futex;
    106 
    107125#endif
  • libc/include/ipc/ipc.h

    rd7eafd8 r085bd54  
    8282extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, ipcarg_t arg1);
    8383
    84 
    85 /* Primitve functions for IPC communication */
    86 void send_call_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
    87                  ipcarg_t arg3);
    88 void send_call_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2);
    89 #define send_call(ph,m,a1) send_call_2(ph,m,a1,0)
    90 /* These functions never preempt */
    91 void nsend_call_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
    92                   ipcarg_t arg2, ipcarg_t arg3);
    93 void nsend_call_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2);
    94 #define nsend_call(ph,m,a1) nsend_call_2(ph,m,a1,0)
    95 
    9684#endif
  • libc/include/psthread.h

    rd7eafd8 r085bd54  
    4141#endif /* context_set */
    4242
     43#define PSTHREAD_SERIALIZED   1
     44
    4345typedef enum {
    4446        PS_TO_MANAGER,
    4547        PS_FROM_MANAGER,
    46         PS_PREEMPT
     48        PS_PREEMPT,
     49        PS_FROM_DEAD
    4750} pschange_type;
    4851
     
    7679void psthread_remove_manager(void);
    7780pstid_t psthread_get_id(void);
     81void psthread_inc_sercount(void);
     82void psthread_dec_sercount(void);
    7883
    7984static inline int psthread_schedule_next() {
Note: See TracChangeset for help on using the changeset viewer.