224 | | #include <ipc/ipc.h> |
225 | | #include <async.h> |
226 | | ... |
227 | | int vfs_phone; |
228 | | int rc; |
229 | | char *pa; |
230 | | size_t pa_len; |
231 | | ... |
232 | | rc = async_data_write_start(vfs_phone, pa, pa_len); |
233 | | if (rc != EOK) { |
234 | | /* an error or the recipient denied the bid */ |
235 | | } |
236 | | }}} |
237 | | |
238 | | The ''pa'' and ''pa_len'' arguments, respectively, specify the source address and the suggested number of bytes to transfer, respectively. |
| 224 | #include <async.h> |
| 225 | ... |
| 226 | char *pa; |
| 227 | size_t pa_len; |
| 228 | ... |
| 229 | async_exch_t *exch = async_exchange_begin(session); |
| 230 | if (exch == NULL) { |
| 231 | /* Handle error creating an exchange */ |
| 232 | } |
| 233 | |
| 234 | int rc = async_data_write_start(exch, pa, pa_len); |
| 235 | async_exchange_end(exch); |
| 236 | |
| 237 | if (rc != EOK) { |
| 238 | /* Error or the recipient denied the bid */ |
| 239 | } |
| 240 | }}} |
| 241 | |
| 242 | The ''pa'' and ''pa_len'' arguments specify the source address and the suggested number of bytes to transfer, respectively. |
257 | | Now the recipient is on the cross-roads. It can do one of three things. It can answer the call with a non-zero return code, or it can accept and restrict the size of the |
258 | | transfer, or it can accept the transfer including the suggested size. The latter two options are achieved like this: |
259 | | |
260 | | {{{ |
261 | | char *path; |
262 | | ... |
263 | | (void) async_data_write_finalize(callid, path, len); |
| 260 | Now the recipient is on the cross-roads. It can do one of three things. It can answer the call with a non-zero return code, or it |
| 261 | can accept and restrict the size of the transfer, or it can accept the transfer including the suggested size. The latter two options are achieved like this: |
| 262 | |
| 263 | {{{ |
| 264 | char *path; |
| 265 | |
| 266 | /* Allocate the receive buffer */ |
| 267 | |
| 268 | (void) async_data_write_finalize(callid, path, len); |
272 | | specifies the destination address and the largest possible size for the transfer. The server can send less data than requested. In the following example, the ''read()'' |
273 | | function in the standard library is requesting ''nbyte'' worth of data to be read from a file system into the ''buf'' buffer: |
274 | | |
275 | | {{{ |
276 | | #include <ipc/ipc.h> |
277 | | #include <async.h> |
278 | | ... |
279 | | int vfs_phone; |
280 | | void *buf; |
281 | | size_t nbyte; |
282 | | ipcarg_t rc; |
283 | | ... |
284 | | rc = async_data_read_start(vfs_phone, buf, nbyte); |
285 | | if (rc != EOK) { |
286 | | /* handle error */ |
287 | | } |
| 277 | specifies the destination address and the largest possible size for the transfer. The server can send less data than requested. In the following example, |
| 278 | the ''read()'' function in the standard library is requesting ''nbyte'' worth of data to be read from a file system into the ''buf'' buffer: |
| 279 | |
| 280 | {{{ |
| 281 | #include <async.h> |
| 282 | ... |
| 283 | async_exch_t *exch = async_exchange_begin(session); |
| 284 | if (exch == NULL) { |
| 285 | /* Handle error creating an exchange */ |
| 286 | } |
| 287 | |
| 288 | int rc = async_data_read_start(exch, buf, nbyte) |
| 289 | async_exchange_end(exch); |
| 290 | |
| 291 | if (rc != EOK) { |
| 292 | /* Error or the recipient denied the bid */ |
| 293 | } |
327 | | When sharing an address space area to other tasks, the client is the sender and the server is the recipient. The client offers one of its address space areas to the server for sharing. |
328 | | The following code snippet illustrates libblock's ''block_init()'' function offering a part of its address space starting at ''com_area'' to a block device associated with the ''dev_phone'' phone handle: |
329 | | |
330 | | {{{ |
331 | | #include <ipc/ipc.h> |
332 | | #include <async.h> |
333 | | ... |
334 | | int rc; |
335 | | int dev_phone; |
336 | | void *com_area; |
337 | | ... |
338 | | rc = async_share_out_start(dev_phone, com_area, |
339 | | AS_AREA_READ | AS_AREA_WRITE); |
340 | | if (rc != EOK) { |
341 | | /* handle error */ |
342 | | } |
343 | | }}} |
344 | | |
345 | | This is how the RD server receives the address space area offer made above: |
346 | | |
347 | | {{{ |
348 | | #include <ipc/ipc.h> |
349 | | #include <async.h> |
350 | | ... |
351 | | ipc_callid_t callid; |
352 | | size_t maxblock_size; |
353 | | int flags; |
354 | | ... |
355 | | if (!async_share_out_receive(&callid, &maxblock_size, &flags)) { |
356 | | /* handle error */ |
357 | | } |
358 | | }}} |
359 | | |
360 | | After the offer is received, the server has a chance to reject it by answering ''callid'' with an error code distinct from EOK. The reason for denial can be an inappropriate ''maxblock_size'' or non-suitable address space area flags in the ''flags'' variable. If the offer looks good to the server, it will accept it like this: |
361 | | |
362 | | {{{ |
363 | | void *fs_va; |
364 | | ... |
365 | | (void) async_share_out_finalize(callid, fs_va); |
366 | | }}} |
367 | | |
368 | | Note that the return value of ''ipc_share_out_finalize()'' is maybe unjustly ignored here. |
369 | | |
370 | | The kernel will attempt to create the mapping only after the server calls ''ipc_share_out_finalize()''. |
| 333 | When sharing an address space area to other tasks, the client is the sender and the server is the recipient. The client offers one of its address space areas |
| 334 | to the server for sharing. The following code snippet illustrates libblock's ''block_init()'' function offering a part of its address space starting at |
| 335 | ''com_area'' to a block device associated with the ''dev_session'' session: |
| 336 | |
| 337 | {{{ |
| 338 | #include <async.h> |
| 339 | ... |
| 340 | async_exch_t *exch = async_exchange_begin(session); |
| 341 | if (exch == NULL) { |
| 342 | /* Handle error creating an exchange */ |
| 343 | } |
| 344 | |
| 345 | int rc = async_share_out_start(exch, com_area, |
| 346 | AS_AREA_READ | AS_AREA_WRITE); |
| 347 | async_exchange_end(exch); |
| 348 | |
| 349 | if (rc != EOK) { |
| 350 | /* Error or the recipient denied the bid */ |
| 351 | } |
| 352 | }}} |
| 353 | |
| 354 | This is how the RAM disk server receives the address space area offer made above: |
| 355 | |
| 356 | {{{ |
| 357 | #include <async.h> |
| 358 | ... |
| 359 | ipc_callid_t callid; |
| 360 | size_t len; |
| 361 | int flags; |
| 362 | if (!async_share_out_receive(&callid, &len, &flags)) { |
| 363 | /* Protocol error - the sender is sharing out an area */ |
| 364 | } |
| 365 | |
| 366 | /* Success, the receive phase is complete */ |
| 367 | }}} |
| 368 | |
| 369 | After the offer is received, the server has a chance to reject it by answering ''callid'' with an error code distinct from EOK. The reason for denial can be an inappropriate ''len'' or non-suitable address space area flags in the ''flags'' variable. If the offer looks good to the server, it will accept it like this: |
| 370 | |
| 371 | {{{ |
| 372 | void *fs_va; |
| 373 | (void) async_share_out_finalize(callid, fs_va); |
| 374 | }}} |
| 375 | |
| 376 | Note that the return value of ''async_share_out_finalize()'' is maybe unjustly ignored here. The kernel will attempt to create the mapping only after the server calls ''async_share_out_finalize()''. |
394 | | #include <ipc/ipc.h> |
395 | | #include <async.h> |
396 | | ... |
397 | | ipc_callid_t callid; |
398 | | size_t size; |
399 | | ... |
400 | | if (!async_share_in_receive(&callid, &size)) { |
401 | | /* handle error */ |
402 | | } |
403 | | }}} |
404 | | |
405 | | The server now has a chance to react to the request. If ''size'' does not meet the server's requirement, the server will reject the offer. Otherwise the server will accept it. Note that so far, the address space area flags were not specified. That will happen in the final phase: |
406 | | |
407 | | {{{ |
408 | | ... |
409 | | uint8_t *plb; |
410 | | (void) async_share_in_finalize(callid, plb, AS_AREA_READ | AS_AREA_CACHEABLE); |
411 | | }}} |
412 | | |
413 | | Again, the kernel will not create the mapping before the server completes the final phase of the negotiation via ''ipc_share_in_finalize()''. |
| 402 | #include <async.h> |
| 403 | ... |
| 404 | ipc_callid_t callid; |
| 405 | size_t size; |
| 406 | if (!async_share_in_receive(&callid, &size)) { |
| 407 | /* Protocol error - the sender is not requesting a share */ |
| 408 | } |
| 409 | |
| 410 | /* Success, the receive phase is complete */ |
| 411 | }}} |
| 412 | |
| 413 | The server now has a chance to react to the request. If ''size'' does not meet the server's requirements, the server will reject the offer. Otherwise the server will accept it. Note that so far, the address space area flags were not specified. That will happen in the final phase: |
| 414 | |
| 415 | {{{ |
| 416 | uint8_t *plb; |
| 417 | (void) async_share_in_finalize(callid, plb, AS_AREA_READ | AS_AREA_CACHEABLE); |
| 418 | }}} |
| 419 | |
| 420 | Again, the kernel will not create the mapping before the server completes the final phase of the negotiation via ''async_share_in_finalize()''. |