Changeset 3b3e776 in mainline for uspace/lib/libc/generic/async.c


Ignore:
Timestamp:
2010-02-05T10:57:50Z (14 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0358da0
Parents:
3f085132 (diff), b4cbef1 (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:

merged with head

File:
1 edited

Legend:

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

    r3f085132 r3b3e776  
    392392        /* If nothing in queue, wait until something arrives */
    393393        while (list_empty(&conn->msg_queue)) {
     394                if (conn->close_callid) {
     395                        /*
     396                         * Handle the case when the connection was already
     397                         * closed by the client but the server did not notice
     398                         * the first IPC_M_PHONE_HUNGUP call and continues to
     399                         * call async_get_call_timeout(). Repeat
     400                         * IPC_M_PHONE_HUNGUP until the caller notices.
     401                         */
     402                        memset(call, 0, sizeof(ipc_call_t));
     403                        IPC_SET_METHOD(*call, IPC_M_PHONE_HUNGUP);
     404                        futex_up(&async_futex);
     405                        return conn->close_callid;
     406                }
     407
    394408                if (usecs)
    395409                        async_insert_timeout(&conn->wdata);
     
    528542        list_initialize(&conn->msg_queue);
    529543        conn->callid = callid;
    530         conn->close_callid = false;
     544        conn->close_callid = 0;
    531545       
    532546        if (call)
     
    12731287}
    12741288
     1289/** Wrapper for forwarding any read request
     1290 *
     1291 *
     1292 */
     1293int async_data_read_forward_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
     1294    ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr)
     1295{
     1296        ipc_callid_t callid;
     1297        if (!async_data_read_receive(&callid, NULL)) {
     1298                ipc_answer_0(callid, EINVAL);
     1299                return EINVAL;
     1300        }
     1301       
     1302        aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
     1303            dataptr);
     1304        if (msg == 0) {
     1305                ipc_answer_0(callid, EINVAL);
     1306                return EINVAL;
     1307        }
     1308       
     1309        int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
     1310            IPC_FF_ROUTE_FROM_ME);
     1311        if (retval != EOK) {
     1312                ipc_answer_0(callid, retval);
     1313                return retval;
     1314        }
     1315       
     1316        ipcarg_t rc;
     1317        async_wait_for(msg, &rc);
     1318       
     1319        return (int) rc;
     1320}
     1321
    12751322/** Wrapper for making IPC_M_DATA_WRITE calls using the async framework.
    12761323 *
    1277  * @param phoneid       Phone that will be used to contact the receiving side.
    1278  * @param src           Address of the beginning of the source buffer.
    1279  * @param size          Size of the source buffer.
    1280  *
    1281  * @return              Zero on success or a negative error code from errno.h.
     1324 * @param phoneid Phone that will be used to contact the receiving side.
     1325 * @param src     Address of the beginning of the source buffer.
     1326 * @param size    Size of the source buffer.
     1327 *
     1328 * @return Zero on success or a negative error code from errno.h.
     1329 *
    12821330 */
    12831331int async_data_write_start(int phoneid, const void *src, size_t size)
     
    12941342 * So far, this wrapper is to be used from within a connection fibril.
    12951343 *
    1296  * @param callid        Storage where the hash of the IPC_M_DATA_WRITE call will
    1297  *                      be stored.
    1298  * @param size          Storage where the suggested size will be stored. May be
    1299  *                      NULL
    1300  *
    1301  * @return              Non-zero on success, zero on failure.
     1344 * @param callid Storage where the hash of the IPC_M_DATA_WRITE call will
     1345 *               be stored.
     1346 * @param size   Storage where the suggested size will be stored. May be
     1347 *               NULL
     1348 *
     1349 * @return Non-zero on success, zero on failure.
     1350 *
    13021351 */
    13031352int async_data_write_receive(ipc_callid_t *callid, size_t *size)
     
    13061355       
    13071356        assert(callid);
    1308 
     1357       
    13091358        *callid = async_get_call(&data);
    13101359        if (IPC_GET_METHOD(data) != IPC_M_DATA_WRITE)
    13111360                return 0;
     1361       
    13121362        if (size)
    13131363                *size = (size_t) IPC_GET_ARG2(data);
     1364       
    13141365        return 1;
    13151366}
     
    13201371 * so that the user doesn't have to remember the meaning of each IPC argument.
    13211372 *
    1322  * @param callid        Hash of the IPC_M_DATA_WRITE call to answer.
    1323  * @param dst           Final destination address for the IPC_M_DATA_WRITE call.
    1324  * @param size          Final size for the IPC_M_DATA_WRITE call.
    1325  *
    1326  * @return              Zero on success or a value from @ref errno.h on failure.
     1373 * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
     1374 * @param dst    Final destination address for the IPC_M_DATA_WRITE call.
     1375 * @param size   Final size for the IPC_M_DATA_WRITE call.
     1376 *
     1377 * @return Zero on success or a value from @ref errno.h on failure.
     1378 *
    13271379 */
    13281380int async_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
     
    13311383}
    13321384
     1385/** Wrapper for receiving binary data
     1386 *
     1387 * This wrapper only makes it more comfortable to use async_data_write_*
     1388 * functions to receive binary data.
     1389 *
     1390 * @param data       Pointer to data pointer (which should be later disposed
     1391 *                   by free()). If the operation fails, the pointer is not
     1392 *                   touched.
     1393 * @param min_size   Minimum size (in bytes) of the data to receive.
     1394 * @param max_size   Maximum size (in bytes) of the data to receive. 0 means
     1395 *                   no limit.
     1396 * @param granulariy If non-zero, then the size of the received data has to
     1397 *                   be divisible by this value.
     1398 * @param received   If not NULL, the size of the received data is stored here.
     1399 *
     1400 * @return Zero on success or a value from @ref errno.h on failure.
     1401 *
     1402 */
     1403int async_data_receive(void **data, const size_t min_size,
     1404    const size_t max_size, const size_t granularity, size_t *received)
     1405{
     1406        ipc_callid_t callid;
     1407        size_t size;
     1408        if (!async_data_write_receive(&callid, &size)) {
     1409                ipc_answer_0(callid, EINVAL);
     1410                return EINVAL;
     1411        }
     1412       
     1413        if (size < min_size) {
     1414                ipc_answer_0(callid, EINVAL);
     1415                return EINVAL;
     1416        }
     1417       
     1418        if ((max_size > 0) && (size > max_size)) {
     1419                ipc_answer_0(callid, EINVAL);
     1420                return EINVAL;
     1421        }
     1422       
     1423        if ((granularity > 0) && ((size % granularity) != 0)) {
     1424                ipc_answer_0(callid, EINVAL);
     1425                return EINVAL;
     1426        }
     1427       
     1428        void *_data = malloc(size);
     1429        if (_data == NULL) {
     1430                ipc_answer_0(callid, ENOMEM);
     1431                return ENOMEM;
     1432        }
     1433       
     1434        int rc = async_data_write_finalize(callid, _data, size);
     1435        if (rc != EOK) {
     1436                free(_data);
     1437                return rc;
     1438        }
     1439       
     1440        *data = _data;
     1441        if (received != NULL)
     1442                *received = size;
     1443       
     1444        return EOK;
     1445}
     1446
     1447/** Wrapper for receiving strings
     1448 *
     1449 * This wrapper only makes it more comfortable to use async_data_write_*
     1450 * functions to receive strings.
     1451 *
     1452 * @param str      Pointer to string pointer (which should be later disposed
     1453 *                 by free()). If the operation fails, the pointer is not
     1454 *                 touched.
     1455 * @param max_size Maximum size (in bytes) of the string to receive. 0 means
     1456 *                 no limit.
     1457 * @param received If not NULL, the size of the received data is stored here.
     1458 *
     1459 * @return Zero on success or a value from @ref errno.h on failure.
     1460 *
     1461 */
     1462int async_string_receive(char **str, const size_t max_size, size_t *received)
     1463{
     1464        ipc_callid_t callid;
     1465        size_t size;
     1466        if (!async_data_write_receive(&callid, &size)) {
     1467                ipc_answer_0(callid, EINVAL);
     1468                return EINVAL;
     1469        }
     1470       
     1471        if ((max_size > 0) && (size > max_size)) {
     1472                ipc_answer_0(callid, EINVAL);
     1473                return EINVAL;
     1474        }
     1475       
     1476        char *data = (char *) malloc(size + 1);
     1477        if (data == NULL) {
     1478                ipc_answer_0(callid, ENOMEM);
     1479                return ENOMEM;
     1480        }
     1481       
     1482        int rc = async_data_write_finalize(callid, data, size);
     1483        if (rc != EOK) {
     1484                free(data);
     1485                return rc;
     1486        }
     1487       
     1488        data[size] = 0;
     1489        *str = data;
     1490        if (received != NULL)
     1491                *received = size;
     1492       
     1493        return EOK;
     1494}
     1495
     1496/** Wrapper for voiding any data that is about to be received
     1497 *
     1498 * This wrapper can be used to void any pending data
     1499 *
     1500 * @param retval Error value from @ref errno.h to be returned to the caller.
     1501 *
     1502 */
     1503void async_data_void(const int retval)
     1504{
     1505        ipc_callid_t callid;
     1506        async_data_write_receive(&callid, NULL);
     1507        ipc_answer_0(callid, retval);
     1508}
     1509
     1510/** Wrapper for forwarding any data that is about to be received
     1511 *
     1512 *
     1513 */
     1514int async_data_forward_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
     1515    ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr)
     1516{
     1517        ipc_callid_t callid;
     1518        if (!async_data_write_receive(&callid, NULL)) {
     1519                ipc_answer_0(callid, EINVAL);
     1520                return EINVAL;
     1521        }
     1522       
     1523        aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
     1524            dataptr);
     1525        if (msg == 0) {
     1526                ipc_answer_0(callid, EINVAL);
     1527                return EINVAL;
     1528        }
     1529       
     1530        int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
     1531            IPC_FF_ROUTE_FROM_ME);
     1532        if (retval != EOK) {
     1533                ipc_answer_0(callid, retval);
     1534                return retval;
     1535        }
     1536       
     1537        ipcarg_t rc;
     1538        async_wait_for(msg, &rc);
     1539       
     1540        return (int) rc;
     1541}
     1542
    13331543/** @}
    13341544 */
Note: See TracChangeset for help on using the changeset viewer.