Changeset 3b3e776 in mainline for uspace/lib/libc/generic/async.c
- Timestamp:
- 2010-02-05T10:57:50Z (15 years ago)
- 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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libc/generic/async.c
r3f085132 r3b3e776 392 392 /* If nothing in queue, wait until something arrives */ 393 393 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 394 408 if (usecs) 395 409 async_insert_timeout(&conn->wdata); … … 528 542 list_initialize(&conn->msg_queue); 529 543 conn->callid = callid; 530 conn->close_callid = false;544 conn->close_callid = 0; 531 545 532 546 if (call) … … 1273 1287 } 1274 1288 1289 /** Wrapper for forwarding any read request 1290 * 1291 * 1292 */ 1293 int 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 1275 1322 /** Wrapper for making IPC_M_DATA_WRITE calls using the async framework. 1276 1323 * 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 * 1282 1330 */ 1283 1331 int async_data_write_start(int phoneid, const void *src, size_t size) … … 1294 1342 * So far, this wrapper is to be used from within a connection fibril. 1295 1343 * 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 * 1302 1351 */ 1303 1352 int async_data_write_receive(ipc_callid_t *callid, size_t *size) … … 1306 1355 1307 1356 assert(callid); 1308 1357 1309 1358 *callid = async_get_call(&data); 1310 1359 if (IPC_GET_METHOD(data) != IPC_M_DATA_WRITE) 1311 1360 return 0; 1361 1312 1362 if (size) 1313 1363 *size = (size_t) IPC_GET_ARG2(data); 1364 1314 1365 return 1; 1315 1366 } … … 1320 1371 * so that the user doesn't have to remember the meaning of each IPC argument. 1321 1372 * 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 * 1327 1379 */ 1328 1380 int async_data_write_finalize(ipc_callid_t callid, void *dst, size_t size) … … 1331 1383 } 1332 1384 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 */ 1403 int 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 */ 1462 int 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 */ 1503 void 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 */ 1514 int 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 1333 1543 /** @} 1334 1544 */
Note:
See TracChangeset
for help on using the changeset viewer.