Changeset 7719958 in mainline for uspace/lib/c/generic


Ignore:
Timestamp:
2012-04-23T22:51:36Z (13 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6a3808e
Parents:
3293a94 (diff), 32fef47 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge mainline changes

Location:
uspace/lib/c/generic
Files:
5 added
3 deleted
10 edited

Legend:

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

    r3293a94 r7719958  
    189189        /** If reply was received. */
    190190        bool done;
     191
     192        /** If the message / reply should be discarded on arrival. */
     193        bool forget;
     194
     195        /** If already destroyed. */
     196        bool destroyed;
    191197       
    192198        /** Pointer to where the answer data is stored. */
     
    240246/** Identifier of the incoming connection handled by the current fibril. */
    241247static fibril_local connection_t *fibril_connection;
     248
     249static void to_event_initialize(to_event_t *to)
     250{
     251        struct timeval tv = { 0, 0 };
     252
     253        to->inlist = false;
     254        to->occurred = false;
     255        link_initialize(&to->link);
     256        to->expires = tv;
     257}
     258
     259static void wu_event_initialize(wu_event_t *wu)
     260{
     261        wu->inlist = false;
     262        link_initialize(&wu->link);
     263}
     264
     265void awaiter_initialize(awaiter_t *aw)
     266{
     267        aw->fid = 0;
     268        aw->active = false;
     269        to_event_initialize(&aw->to_event);
     270        wu_event_initialize(&aw->wu_event);
     271}
     272
     273static amsg_t *amsg_create(void)
     274{
     275        amsg_t *msg;
     276
     277        msg = malloc(sizeof(amsg_t));
     278        if (msg) {
     279                msg->done = false;
     280                msg->forget = false;
     281                msg->destroyed = false;
     282                msg->dataptr = NULL;
     283                msg->retval = (sysarg_t) EINVAL;
     284                awaiter_initialize(&msg->wdata);
     285        }
     286
     287        return msg;
     288}
     289
     290static void amsg_destroy(amsg_t *msg)
     291{
     292        assert(!msg->destroyed);
     293        msg->destroyed = true;
     294        free(msg);
     295}
    242296
    243297static void *default_client_data_constructor(void)
     
    892946       
    893947        switch (IPC_GET_IMETHOD(*call)) {
    894         case IPC_M_CONNECT_ME:
     948        case IPC_M_CLONE_ESTABLISH:
    895949        case IPC_M_CONNECT_ME_TO:
    896950                /* Open new connection with fibril, etc. */
     
    9631017               
    9641018                suseconds_t timeout;
     1019                unsigned int flags = SYNCH_FLAGS_NONE;
    9651020                if (!list_empty(&timeout_list)) {
    9661021                        awaiter_t *waiter = list_get_instance(
     
    9731028                                futex_up(&async_futex);
    9741029                                handle_expired_timeouts();
    975                                 continue;
    976                         } else
     1030                                /*
     1031                                 * Notice that even if the event(s) already
     1032                                 * expired (and thus the other fibril was
     1033                                 * supposed to be running already),
     1034                                 * we check for incoming IPC.
     1035                                 *
     1036                                 * Otherwise, a fibril that continuously
     1037                                 * creates (almost) expired events could
     1038                                 * prevent IPC retrieval from the kernel.
     1039                                 */
     1040                                timeout = 0;
     1041                                flags = SYNCH_FLAGS_NON_BLOCKING;
     1042
     1043                        } else {
    9771044                                timeout = tv_sub(&waiter->to_event.expires, &tv);
    978                 } else
     1045                                futex_up(&async_futex);
     1046                        }
     1047                } else {
     1048                        futex_up(&async_futex);
    9791049                        timeout = SYNCH_NO_TIMEOUT;
    980                
    981                 futex_up(&async_futex);
     1050                }
    9821051               
    9831052                atomic_inc(&threads_in_ipc_wait);
    9841053               
    9851054                ipc_call_t call;
    986                 ipc_callid_t callid = ipc_wait_cycle(&call, timeout,
    987                     SYNCH_FLAGS_NONE);
     1055                ipc_callid_t callid = ipc_wait_cycle(&call, timeout, flags);
    9881056               
    9891057                atomic_dec(&threads_in_ipc_wait);
     
    11001168       
    11011169        msg->done = true;
    1102         if (!msg->wdata.active) {
     1170
     1171        if (msg->forget) {
     1172                assert(msg->wdata.active);
     1173                amsg_destroy(msg);
     1174        } else if (!msg->wdata.active) {
    11031175                msg->wdata.active = true;
    11041176                fibril_add_ready(msg->wdata.fid);
    11051177        }
    1106        
     1178
    11071179        futex_up(&async_futex);
    11081180}
     
    11311203                return 0;
    11321204       
    1133         amsg_t *msg = malloc(sizeof(amsg_t));
     1205        amsg_t *msg = amsg_create();
    11341206        if (msg == NULL)
    11351207                return 0;
    11361208       
    1137         msg->done = false;
    11381209        msg->dataptr = dataptr;
    1139        
    1140         msg->wdata.to_event.inlist = false;
    1141        
    1142         /*
    1143          * We may sleep in the next method,
    1144          * but it will use its own means
    1145          */
    11461210        msg->wdata.active = true;
    11471211       
     
    11771241                return 0;
    11781242       
    1179         amsg_t *msg = malloc(sizeof(amsg_t));
    1180        
     1243        amsg_t *msg = amsg_create();
    11811244        if (msg == NULL)
    11821245                return 0;
    11831246       
    1184         msg->done = false;
    11851247        msg->dataptr = dataptr;
    1186        
    1187         msg->wdata.to_event.inlist = false;
    1188        
    1189         /*
    1190          * We may sleep in the next method,
    1191          * but it will use its own means
    1192          */
    11931248        msg->wdata.active = true;
    11941249       
     
    12131268       
    12141269        futex_down(&async_futex);
     1270
     1271        assert(!msg->forget);
     1272        assert(!msg->destroyed);
     1273
    12151274        if (msg->done) {
    12161275                futex_up(&async_futex);
     
    12311290                *retval = msg->retval;
    12321291       
    1233         free(msg);
     1292        amsg_destroy(msg);
    12341293}
    12351294
    12361295/** Wait for a message sent by the async framework, timeout variant.
     1296 *
     1297 * If the wait times out, the caller may choose to either wait again by calling
     1298 * async_wait_for() or async_wait_timeout(), or forget the message via
     1299 * async_forget().
    12371300 *
    12381301 * @param amsgid  Hash of the message to wait for.
     
    12491312       
    12501313        amsg_t *msg = (amsg_t *) amsgid;
    1251        
    1252         /* TODO: Let it go through the event read at least once */
    1253         if (timeout < 0)
    1254                 return ETIMEOUT;
    1255        
     1314
    12561315        futex_down(&async_futex);
     1316
     1317        assert(!msg->forget);
     1318        assert(!msg->destroyed);
     1319
    12571320        if (msg->done) {
    12581321                futex_up(&async_futex);
     
    12601323        }
    12611324       
     1325        /*
     1326         * Negative timeout is converted to zero timeout to avoid
     1327         * using tv_add with negative augmenter.
     1328         */
     1329        if (timeout < 0)
     1330                timeout = 0;
     1331
    12621332        gettimeofday(&msg->wdata.to_event.expires, NULL);
    12631333        tv_add(&msg->wdata.to_event.expires, timeout);
    12641334       
     1335        /*
     1336         * Current fibril is inserted as waiting regardless of the
     1337         * "size" of the timeout.
     1338         *
     1339         * Checking for msg->done and immediately bailing out when
     1340         * timeout == 0 would mean that the manager fibril would never
     1341         * run (consider single threaded program).
     1342         * Thus the IPC answer would be never retrieved from the kernel.
     1343         *
     1344         * Notice that the actual delay would be very small because we
     1345         * - switch to manager fibril
     1346         * - the manager sees expired timeout
     1347         * - and thus adds us back to ready queue
     1348         * - manager switches back to some ready fibril
     1349         *   (prior it, it checks for incoming IPC).
     1350         *
     1351         */
    12651352        msg->wdata.fid = fibril_get_id();
    12661353        msg->wdata.active = false;
     
    12791366                *retval = msg->retval;
    12801367       
    1281         free(msg);
     1368        amsg_destroy(msg);
    12821369       
    12831370        return 0;
    12841371}
     1372 
     1373/** Discard the message / reply on arrival.
     1374 *
     1375 * The message will be marked to be discarded once the reply arrives in
     1376 * reply_received(). It is not allowed to call async_wait_for() or
     1377 * async_wait_timeout() on this message after a call to this function.
     1378 *
     1379 * @param amsgid  Hash of the message to forget.
     1380 */
     1381void async_forget(aid_t amsgid)
     1382{
     1383        amsg_t *msg = (amsg_t *) amsgid;
     1384
     1385        assert(msg);
     1386        assert(!msg->forget);
     1387        assert(!msg->destroyed);
     1388
     1389        futex_down(&async_futex);
     1390        if (msg->done)
     1391                amsg_destroy(msg);
     1392        else
     1393                msg->forget = true;
     1394        futex_up(&async_futex);
     1395}
    12851396
    12861397/** Wait for specified time.
     
    12931404void async_usleep(suseconds_t timeout)
    12941405{
    1295         amsg_t *msg = malloc(sizeof(amsg_t));
    1296        
     1406        amsg_t *msg = amsg_create();
    12971407        if (!msg)
    12981408                return;
    12991409       
    13001410        msg->wdata.fid = fibril_get_id();
    1301         msg->wdata.active = false;
    13021411       
    13031412        gettimeofday(&msg->wdata.to_event.expires, NULL);
     
    13131422        /* Futex is up automatically after fibril_switch() */
    13141423       
    1315         free(msg);
     1424        amsg_destroy(msg);
    13161425}
    13171426
     
    15591668}
    15601669
    1561 /** Wrapper for making IPC_M_CONNECT_ME calls using the async framework.
    1562  *
    1563  * Ask through for a cloned connection to some service.
     1670/** Wrapper for making IPC_M_CLONE_ESTABLISH calls using the async framework.
     1671 *
     1672 * Ask for a cloned connection to some service.
    15641673 *
    15651674 * @param mgmt Exchange management style.
     
    15691678 *
    15701679 */
    1571 async_sess_t *async_connect_me(exch_mgmt_t mgmt, async_exch_t *exch)
     1680async_sess_t *async_clone_establish(exch_mgmt_t mgmt, async_exch_t *exch)
    15721681{
    15731682        if (exch == NULL) {
     
    15841693        ipc_call_t result;
    15851694       
    1586         amsg_t *msg = malloc(sizeof(amsg_t));
    1587         if (msg == NULL) {
     1695        amsg_t *msg = amsg_create();
     1696        if (!msg) {
    15881697                free(sess);
    15891698                errno = ENOMEM;
     
    15911700        }
    15921701       
    1593         msg->done = false;
    15941702        msg->dataptr = &result;
    1595        
    1596         msg->wdata.to_event.inlist = false;
    1597        
    1598         /*
    1599          * We may sleep in the next method,
    1600          * but it will use its own means
    1601          */
    16021703        msg->wdata.active = true;
    16031704       
    1604         ipc_call_async_0(exch->phone, IPC_M_CONNECT_ME, msg,
     1705        ipc_call_async_0(exch->phone, IPC_M_CLONE_ESTABLISH, msg,
    16051706            reply_received, true);
    16061707       
     
    16431744        ipc_call_t result;
    16441745       
    1645         amsg_t *msg = malloc(sizeof(amsg_t));
    1646         if (msg == NULL)
     1746        amsg_t *msg = amsg_create();
     1747        if (!msg)
    16471748                return ENOENT;
    16481749       
    1649         msg->done = false;
    16501750        msg->dataptr = &result;
    1651        
    1652         msg->wdata.to_event.inlist = false;
    1653        
    1654         /*
    1655          * We may sleep in the next method,
    1656          * but it will use its own means
    1657          */
    16581751        msg->wdata.active = true;
    16591752       
     
    22512344            IPC_FF_ROUTE_FROM_ME);
    22522345        if (retval != EOK) {
    2253                 async_wait_for(msg, NULL);
     2346                async_forget(msg);
    22542347                ipc_answer_0(callid, retval);
    22552348                return retval;
     
    24452538            IPC_FF_ROUTE_FROM_ME);
    24462539        if (retval != EOK) {
    2447                 async_wait_for(msg, NULL);
     2540                async_forget(msg);
    24482541                ipc_answer_0(callid, retval);
    24492542                return retval;
  • uspace/lib/c/generic/device/nic.c

    r3293a94 r7719958  
    6565       
    6666        if (retval != EOK) {
    67                 async_wait_for(req, NULL);
     67                async_forget(req);
    6868                return retval;
    6969        }
     
    9494        rc = async_connect_to_me(exch, 0, 0, 0, cfun, carg);
    9595        if (rc != EOK) {
    96                 async_wait_for(req, NULL);
     96                async_forget(req);
    9797                return rc;
    9898        }
  • uspace/lib/c/generic/devman.c

    r3293a94 r7719958  
    188188       
    189189        if (retval != EOK) {
    190                 async_wait_for(req, NULL);
     190                async_forget(req);
    191191                return retval;
    192192        }
     
    226226        if (retval != EOK) {
    227227                devman_exchange_end(exch);
    228                 async_wait_for(req, NULL);
     228                async_forget(req);
    229229                return retval;
    230230        }
     
    242242                if (retval != EOK) {
    243243                        devman_exchange_end(exch);
    244                         async_wait_for(req2, NULL);
    245                         async_wait_for(req, NULL);
     244                        async_forget(req2);
     245                        async_forget(req);
    246246                        return retval;
    247247                }
     
    250250                if (retval != EOK) {
    251251                        devman_exchange_end(exch);
    252                         async_wait_for(req, NULL);
     252                        async_forget(req);
    253253                        return retval;
    254254                }
     
    283283       
    284284        if (retval != EOK) {
    285                 async_wait_for(req, NULL);
     285                async_forget(req);
    286286                return retval;
    287287        }
     
    386386       
    387387        if (retval != EOK) {
    388                 async_wait_for(req, NULL);
     388                async_forget(req);
    389389                return retval;
    390390        }
     
    423423       
    424424        if (dretval != EOK) {
    425                 async_wait_for(req, NULL);
     425                async_forget(req);
    426426                return dretval;
    427427        }
     
    488488       
    489489        if (rc != EOK) {
    490                 async_wait_for(req, NULL);
     490                async_forget(req);
    491491                return rc;
    492492        }
  • uspace/lib/c/generic/fibril_synch.c

    r3293a94 r7719958  
    112112                awaiter_t wdata;
    113113
     114                awaiter_initialize(&wdata);
    114115                wdata.fid = fibril_get_id();
    115                 wdata.active = false;
    116116                wdata.wu_event.inlist = true;
    117                 link_initialize(&wdata.wu_event.link);
    118117                list_append(&wdata.wu_event.link, &fm->waiters);
    119118                check_for_deadlock(&fm->oi);
     
    205204                awaiter_t wdata;
    206205
     206                awaiter_initialize(&wdata);
    207207                wdata.fid = (fid_t) f;
    208                 wdata.active = false;
    209208                wdata.wu_event.inlist = true;
    210                 link_initialize(&wdata.wu_event.link);
    211209                f->flags &= ~FIBRIL_WRITER;
    212210                list_append(&wdata.wu_event.link, &frw->waiters);
     
    233231                awaiter_t wdata;
    234232
     233                awaiter_initialize(&wdata);
    235234                wdata.fid = (fid_t) f;
    236                 wdata.active = false;
    237235                wdata.wu_event.inlist = true;
    238                 link_initialize(&wdata.wu_event.link);
    239236                f->flags |= FIBRIL_WRITER;
    240237                list_append(&wdata.wu_event.link, &frw->waiters);
     
    375372                return ETIMEOUT;
    376373
     374        awaiter_initialize(&wdata);
    377375        wdata.fid = fibril_get_id();
    378         wdata.active = false;
    379        
    380376        wdata.to_event.inlist = timeout > 0;
    381         wdata.to_event.occurred = false;
    382         link_initialize(&wdata.to_event.link);
    383 
    384377        wdata.wu_event.inlist = true;
    385         link_initialize(&wdata.wu_event.link);
    386378
    387379        futex_down(&async_futex);
  • uspace/lib/c/generic/io/printf_core.c

    r3293a94 r7719958  
    283283        /* Print leading spaces. */
    284284        size_t strw = str_length(str);
    285         if (precision == 0)
     285        if ((precision == 0) || (precision > strw))
    286286                precision = strw;
    287287       
     
    331331        /* Print leading spaces. */
    332332        size_t strw = wstr_length(str);
    333         if (precision == 0)
     333        if ((precision == 0) || (precision > strw))
    334334                precision = strw;
    335335       
  • uspace/lib/c/generic/ipc.c

    r3293a94 r7719958  
    647647 *
    648648 */
    649 int ipc_connect_me(int phoneid)
     649int ipc_clone_establish(int phoneid)
    650650{
    651651        sysarg_t newphid;
    652         int res = ipc_call_sync_0_5(phoneid, IPC_M_CONNECT_ME, NULL, NULL,
    653             NULL, NULL, &newphid);
     652        int res = ipc_call_sync_0_5(phoneid, IPC_M_CLONE_ESTABLISH, NULL,
     653            NULL, NULL, NULL, &newphid);
    654654        if (res)
    655655                return res;
  • uspace/lib/c/generic/loader.c

    r3293a94 r7719958  
    101101       
    102102        if (rc != EOK) {
    103                 async_wait_for(req, NULL);
     103                async_forget(req);
    104104                return (int) rc;
    105105        }
     
    139139       
    140140        if (rc != EOK) {
    141                 async_wait_for(req, NULL);
     141                async_forget(req);
    142142                return (int) rc;
    143143        }
     
    177177       
    178178        if (rc != EOK) {
    179                 async_wait_for(req, NULL);
     179                async_forget(req);
    180180                return (int) rc;
    181181        }
     
    236236       
    237237        if (rc != EOK) {
    238                 async_wait_for(req, NULL);
     238                async_forget(req);
    239239                return (int) rc;
    240240        }
     
    281281
    282282        if (rc != EOK) {
    283                 async_wait_for(req, NULL);
     283                async_forget(req);
    284284                return (int) rc;
    285285        }
  • uspace/lib/c/generic/loc.c

    r3293a94 r7719958  
    246246       
    247247        if (retval != EOK) {
    248                 async_wait_for(req, NULL);
     248                async_forget(req);
    249249                return retval;
    250250        }
     
    285285       
    286286        if (retval != EOK) {
    287                 async_wait_for(req, NULL);
     287                async_forget(req);
    288288                return retval;
    289289        }
     
    352352       
    353353        if (retval != EOK) {
    354                 async_wait_for(req, NULL);
     354                async_forget(req);
    355355                return retval;
    356356        }
     
    401401       
    402402        if (dretval != EOK) {
    403                 async_wait_for(req, NULL);
     403                async_forget(req);
    404404                return dretval;
    405405        }
     
    471471       
    472472        if (retval != EOK) {
    473                 async_wait_for(req, NULL);
     473                async_forget(req);
    474474                return retval;
    475475        }
     
    520520       
    521521        if (retval != EOK) {
    522                 async_wait_for(req, NULL);
     522                async_forget(req);
    523523                return retval;
    524524        }
     
    683683               
    684684                if (rc != EOK) {
    685                         async_wait_for(req, NULL);
     685                        async_forget(req);
    686686                        free(devs);
    687687                        return 0;
     
    732732               
    733733                if (rc != EOK) {
    734                         async_wait_for(req, NULL);
     734                        async_forget(req);
    735735                        free(devs);
    736736                        return 0;
     
    760760       
    761761        if (rc != EOK) {
    762                 async_wait_for(req, NULL);
     762                async_forget(req);
    763763                return rc;
    764764        }
  • uspace/lib/c/generic/net/modules.c

    r3293a94 r7719958  
    9393}
    9494
     95/** Connect to the needed module.
     96 *
     97 * @param[in] need Needed module service.
     98 *
     99 * @return Session to the needed service.
     100 * @return NULL if the connection timeouted.
     101 *
     102 */
     103static async_sess_t *connect_to_service(services_t need)
     104{
     105        return service_connect_blocking(EXCHANGE_SERIALIZE, need, 0, 0);
     106}
     107
    95108/** Create bidirectional connection with the needed module service and register
    96109 * the message receiver.
     
    129142}
    130143
    131 /** Connect to the needed module.
    132  *
    133  * @param[in] need Needed module service.
    134  *
    135  * @return Session to the needed service.
    136  * @return NULL if the connection timeouted.
    137  *
    138  */
    139 async_sess_t *connect_to_service(services_t need)
    140 {
    141         return service_connect_blocking(EXCHANGE_SERIALIZE, need, 0, 0);
    142 }
    143 
    144 /** Reply the data to the other party.
    145  *
    146  * @param[in] data        The data buffer to be sent.
    147  * @param[in] data_length The buffer length.
    148  *
    149  * @return EOK on success.
    150  * @return EINVAL if the client does not expect the data.
    151  * @return EOVERFLOW if the client does not expect all the data.
    152  *         Only partial data are transfered.
    153  * @return Other error codes as defined for the
    154  *         async_data_read_finalize() function.
    155  *
    156  */
    157 int data_reply(void *data, size_t data_length)
    158 {
    159         size_t length;
    160         ipc_callid_t callid;
    161        
    162         /* Fetch the request */
    163         if (!async_data_read_receive(&callid, &length))
    164                 return EINVAL;
    165        
    166         /* Check the requested data size */
    167         if (length < data_length) {
    168                 async_data_read_finalize(callid, data, length);
    169                 return EOVERFLOW;
    170         }
    171        
    172         /* Send the data */
    173         return async_data_read_finalize(callid, data, data_length);
    174 }
    175 
    176144/** Refresh answer structure and argument count.
    177145 *
  • uspace/lib/c/generic/private/async.h

    r3293a94 r7719958  
    8181} awaiter_t;
    8282
     83extern void awaiter_initialize(awaiter_t *);
     84
    8385extern void __async_init(void);
    8486extern void async_insert_timeout(awaiter_t *);
Note: See TracChangeset for help on using the changeset viewer.