Changeset a55d5f9f in mainline


Ignore:
Timestamp:
2007-12-23T21:21:41Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a92da0a
Parents:
654b7db
Message:

Add support for IPC_M_DATA_READ calls.

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/ipc/ipc.h

    r654b7db ra55d5f9f  
    280280        ipc_data_t data;
    281281
    282         /** Buffer for IPC_M_DATA_SEND. */
     282        /** Buffer for IPC_M_DATA_WRITE and IPC_M_DATA_READ. */
    283283        uint8_t *buffer;
    284284} call_t;
  • kernel/generic/src/ipc/ipc.c

    r654b7db ra55d5f9f  
    415415        while (!list_empty(lst)) {
    416416                call = list_get_instance(lst->next, call_t, link);
     417                if (call->buffer)
     418                        free(call->buffer);
    417419                list_remove(&call->link);
    418420
  • kernel/generic/src/ipc/sysipc.c

    r654b7db ra55d5f9f  
    236236                        IPC_SET_RETVAL(answer->data, rc);
    237237                }
     238        } else if (IPC_GET_METHOD(*olddata) == IPC_M_DATA_READ) {
     239                ASSERT(!answer->buffer);
     240                if (!IPC_GET_RETVAL(answer->data)) {
     241                        /* The recipient agreed to send data. */
     242                        uintptr_t src = IPC_GET_ARG1(answer->data);
     243                        uintptr_t dst = IPC_GET_ARG1(*olddata);
     244                        size_t max_size = IPC_GET_ARG2(*olddata);
     245                        size_t size = IPC_GET_ARG2(answer->data);
     246                        if (size <= max_size) {
     247                                /*
     248                                 * Copy the destination VA so that this piece of
     249                                 * information is not lost.
     250                                 */
     251                                IPC_SET_ARG1(answer->data, dst);
     252
     253                                answer->buffer = malloc(size, 0);
     254                                int rc = copy_from_uspace(answer->buffer,
     255                                    (void *) src, size);
     256                                if (rc) {
     257                                        IPC_SET_RETVAL(answer->data, rc);
     258                                        free(answer->buffer);
     259                                        answer->buffer = NULL;
     260                                }
     261                        } else {
     262                                IPC_SET_RETVAL(answer->data, ELIMIT);
     263                        }
     264                }
    238265        } else if (IPC_GET_METHOD(*olddata) == IPC_M_DATA_WRITE) {
    239266                ASSERT(answer->buffer);
    240267                if (!IPC_GET_RETVAL(answer->data)) {
     268                        /* The recipient agreed to receive data. */
    241269                        int rc;
    242270                        uintptr_t dst;
    243271                        uintptr_t size;
     272                        uintptr_t max_size;
    244273
    245274                        dst = IPC_GET_ARG1(answer->data);
    246275                        size = IPC_GET_ARG3(answer->data);
    247 
    248                         rc = copy_to_uspace((void *) dst, answer->buffer, size);
    249                         if (rc != 0)
    250                                 IPC_SET_RETVAL(answer->data, rc);
     276                        max_size = IPC_GET_ARG3(*olddata);
     277
     278                        if (size <= max_size) {
     279                                rc = copy_to_uspace((void *) dst,
     280                                    answer->buffer, size);
     281                                if (rc)
     282                                        IPC_SET_RETVAL(answer->data, rc);
     283                        } else {
     284                                IPC_SET_RETVAL(answer->data, ELIMIT);
     285                        }
    251286                }
    252287                free(answer->buffer);
     
    285320                IPC_SET_ARG2(call->data, size);
    286321                break;
     322        case IPC_M_DATA_READ:
     323                size = IPC_GET_ARG2(call->data);
     324                if ((size <= 0 || (size > DATA_XFER_LIMIT)))
     325                        return ELIMIT;
     326                break;
    287327        case IPC_M_DATA_WRITE:
    288328                src = IPC_GET_ARG2(call->data);
     
    325365                        IPC_SET_ARG5(call->data, call->priv);
    326366        }
     367
     368        if (call->buffer) {
     369                /* This must be an affirmative answer to IPC_M_DATA_READ. */
     370                uintptr_t dst = IPC_GET_ARG1(call->data);
     371                size_t size = IPC_GET_ARG2(call->data);
     372                int rc = copy_to_uspace((void *) dst, call->buffer, size);
     373                if (rc)
     374                        IPC_SET_RETVAL(call->data, rc);
     375                free(call->buffer);
     376                call->buffer = NULL;
     377        }
    327378}
    328379
  • uspace/lib/libc/generic/ipc.c

    r654b7db ra55d5f9f  
    667667}
    668668
     669/** Wrapper for making IPC_M_DATA_READ calls.
     670 *
     671 * @param phoneid       Phone that will be used to contact the receiving side.
     672 * @param dst           Address of the beginning of the destination buffer.
     673 * @param size          Size of the destination buffer.
     674 *
     675 * @return              Zero on success or a negative error code from errno.h.
     676 */
     677int ipc_data_read_send(int phoneid, void *dst, size_t size)
     678{
     679        return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst,
     680            (ipcarg_t) size);
     681}
     682
     683/** Wrapper for receiving the IPC_M_DATA_READ calls.
     684 *
     685 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ calls
     686 * so that the user doesn't have to remember the meaning of each IPC argument.
     687 *
     688 * So far, this wrapper is to be used from within a connection fibril.
     689 *
     690 * @param callid        Storage where the hash of the IPC_M_DATA_READ call will
     691 *                      be stored.
     692 * @param size          Storage where the maximum size will be stored.
     693 *
     694 * @return              Non-zero on success, zero on failure.
     695 */
     696int ipc_data_read_receive(ipc_callid_t *callid, size_t *size)
     697{
     698        ipc_call_t data;
     699       
     700        assert(callid);
     701
     702        *callid = async_get_call(&data);
     703        if (IPC_GET_METHOD(data) != IPC_M_DATA_READ)
     704                return 0;
     705        assert(size);
     706        *size = (size_t) IPC_GET_ARG2(data);
     707        return 1;
     708}
     709
     710/** Wrapper for answering the IPC_M_DATA_READ calls.
     711 *
     712 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
     713 * so that the user doesn't have to remember the meaning of each IPC argument.
     714 *
     715 * @param callid        Hash of the IPC_M_DATA_READ call to answer.
     716 * @param src           Source address for the IPC_M_DATA_READ call.
     717 * @param size          Size for the IPC_M_DATA_READ call. Can be smaller than
     718 *                      the maximum size announced by the sender.
     719 *
     720 * @return              Zero on success or a value from @ref errno.h on failure.
     721 */
     722int ipc_data_read_deliver(ipc_callid_t callid, void *src, size_t size)
     723{
     724        return ipc_answer_2(callid, EOK, (ipcarg_t) src, (ipcarg_t) size);
     725}
     726
    669727/** Wrapper for making IPC_M_DATA_WRITE calls.
    670728 *
     
    724782 * @return              Zero on success or a value from @ref errno.h on failure.
    725783 */
    726 ipcarg_t ipc_data_write_deliver(ipc_callid_t callid, void *dst, size_t size)
     784int ipc_data_write_deliver(ipc_callid_t callid, void *dst, size_t size)
    727785{
    728786        return ipc_answer_3(callid, EOK, (ipcarg_t) dst, 0, (ipcarg_t) size);
  • uspace/lib/libc/include/ipc/ipc.h

    r654b7db ra55d5f9f  
    261261extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method,
    262262    ipcarg_t arg1, ipcarg_t arg2, int mode);
     263
     264
     265extern int ipc_data_read_send(int phoneid, void *dst, size_t size);
     266extern int ipc_data_read_receive(ipc_callid_t *callid, size_t *size);
     267extern int ipc_data_read_deliver(ipc_callid_t callid, void *src, size_t size);
    263268extern int ipc_data_write_send(int phoneid, void *src, size_t size);
    264269extern int ipc_data_write_receive(ipc_callid_t *callid, void **dst,
    265270    size_t *size);
    266 extern ipcarg_t ipc_data_write_deliver(ipc_callid_t callid, void *dst,
    267     size_t size);
     271extern int ipc_data_write_deliver(ipc_callid_t callid, void *dst, size_t size);
    268272
    269273#endif
Note: See TracChangeset for help on using the changeset viewer.