/* store the message descriptors in the queue, *andthebufferseparately.Thebuffercould *eventuallymovetoaseparateareathatcan *bemappedintotheprocessdirectly.
*/ struct msg_item items[0];
};
if (msg->num_handles) { if (msg->num_handles > MAX_MSG_HANDLES) {
LTRACEF("sending too many (%u) handles\n", msg->num_handles); return ERR_TOO_BIG;
}
if (!msg->handles) return ERR_INVALID_ARGS;
}
/* copy any message body */ if (likely(msg->num_iov)) {
ret = kern_iovec_to_membuf(buf, mq->item_sz,
(conststruct iovec_kern*)msg->iov,
msg->num_iov); if (ret < 0) return ret;
}
/* copy attached handles */ for (uint i = 0; i < msg->num_handles; i++) { if (!msg->handles[i]) {
ret = ERR_BAD_HANDLE; goto err_bad_handle;
}
if (!handle_is_sendable(msg->handles[i])) {
ret = ERR_NOT_ALLOWED; goto err_bad_handle;
}
/* Need to send all or none */ for (uint i = 0; i < msg->num_handles; i++) {
rc = uctx_handle_get(uctx, ids[i], &item->handles[i]); if (unlikely(rc != NO_ERROR)) { goto err_get;
}
item->num_handles++;
if (!handle_is_sendable(item->handles[i])) {
rc = ERR_NOT_ALLOWED; goto err_send;
}
}
return ret;
err_send:
err_get: for (uint i = 0; i < item->num_handles; i++) {
handle_decref(item->handles[i]);
item->handles[i] = NULL;
}
item->num_handles = 0;
if (!item || item->state != MSG_ITEM_STATE_READ) return ERR_INVALID_ARGS;
list_delete(&item->node);
/* detach handles from table if any */ for (uint j = 0; j < item->num_handles; j++) {
ph[j] = item->handles[j];
item->handles[j] = NULL;
}
*phcnt = item->num_handles;
item->num_handles = 0;
/* put it on the head since it was just taken off here */
list_add_head(&mq->free_list, &item->node);
item->state = MSG_ITEM_STATE_FREE;
return NO_ERROR;
}
long __SYSCALL sys_send_msg(uint32_t handle_id, user_addr_t user_msg) { struct handle* chandle; struct ipc_msg_user tmp_msg; int ret; struct uctx* uctx = current_uctx();
/* copy message descriptor from user space */
ret = copy_from_user(&tmp_msg, user_msg, sizeof(struct ipc_msg_user)); if (unlikely(ret != NO_ERROR)) return (long)ret;
/* grab handle */
ret = uctx_handle_get(uctx, handle_id, &chandle); if (unlikely(ret != NO_ERROR)) return (long)ret;
ret = check_channel(chandle); if (likely(ret == NO_ERROR)) { struct ipc_chan* chan = containerof(chandle, struct ipc_chan, handle);
mutex_acquire(&chan->peer->mlock);
ret = msg_write_locked(chan, &tmp_msg, uctx);
mutex_release(&chan->peer->mlock); if (ret >= 0) { /* and notify target */
handle_notify(&chan->peer->handle);
}
}
handle_decref(chandle); return (long)ret;
}
int ipc_send_msg(struct handle* chandle, struct ipc_msg_kern* msg) { int ret;
if (!msg) return ERR_INVALID_ARGS;
ret = check_channel(chandle); if (likely(ret == NO_ERROR)) { struct ipc_chan* chan = containerof(chandle, struct ipc_chan, handle);
mutex_acquire(&chan->peer->mlock);
ret = msg_write_locked(chan, msg, NULL);
mutex_release(&chan->peer->mlock); if (ret >= 0) {
handle_notify(&chan->peer->handle);
}
} return ret;
}
long __SYSCALL sys_get_msg(uint32_t handle_id, user_addr_t user_msg_info) { struct handle* chandle; struct ipc_msg_info mi_kern; int ret;
/* grab handle */
ret = uctx_handle_get(current_uctx(), handle_id, &chandle); if (ret != NO_ERROR) return (long)ret;
/* check if channel handle is a valid one */
ret = check_channel(chandle); if (likely(ret == NO_ERROR)) { struct ipc_chan* chan = containerof(chandle, struct ipc_chan, handle);
mutex_acquire(&chan->mlock); /* peek next filled message */
ret = msg_peek_next_filled_locked(chan->msg_queue, &mi_kern); if (likely(ret == NO_ERROR)) { /* copy it to user space */ struct ipc_msg_info_user mi_user;
memset(&mi_user, 0, sizeof(mi_user));
mi_user.len = (user_size_t)mi_kern.len;
mi_user.id = mi_kern.id;
mi_user.num_handles = mi_kern.num_handles;
ret = copy_to_user(user_msg_info, &mi_user, sizeof(mi_user)); if (likely(ret == NO_ERROR)) { /* and make it readable */
msg_get_filled_locked(chan->msg_queue);
}
}
mutex_release(&chan->mlock);
}
handle_decref(chandle); return (long)ret;
}
int ipc_get_msg(struct handle* chandle, struct ipc_msg_info* msg_info) { int ret;
/* check if channel handle */
ret = check_channel(chandle); if (likely(ret == NO_ERROR)) { struct ipc_chan* chan = containerof(chandle, struct ipc_chan, handle);
mutex_acquire(&chan->mlock); /* peek next filled message */
ret = msg_peek_next_filled_locked(chan->msg_queue, msg_info); if (likely(ret == NO_ERROR)) { /* and make it readable */
msg_get_filled_locked(chan->msg_queue);
}
mutex_release(&chan->mlock);
} return ret;
}
long __SYSCALL sys_put_msg(uint32_t handle_id, uint32_t msg_id) { struct handle* chandle;
/* grab handle */ int ret = uctx_handle_get(current_uctx(), handle_id, &chandle); if (unlikely(ret != NO_ERROR)) return (long)ret;
/* and put it to rest */
ret = ipc_put_msg(chandle, msg_id);
handle_decref(chandle);
return (long)ret;
}
int ipc_put_msg(struct handle* chandle, uint32_t msg_id) { int ret;
/* check is channel handle is a valid one */
ret = check_channel(chandle); if (unlikely(ret != NO_ERROR)) return ret;
/* get msg descriptor from user space */
ret = copy_from_user(&msg, user_msg, sizeof(struct ipc_msg_user)); if (unlikely(ret != NO_ERROR)) return (long)ret;
/* grab handle */
ret = uctx_handle_get(uctx, handle_id, &chandle); if (unlikely(ret != NO_ERROR)) return (long)ret;
/* check if channel handle is a valid one */
ret = check_channel(chandle); if (ret == NO_ERROR) { struct ipc_chan* chan = containerof(chandle, struct ipc_chan, handle); struct handle* h[MAX_MSG_HANDLES];
uint hcnt = 0;
mutex_acquire(&chan->mlock);
ret = user_msg_read_locked(chan->msg_queue, msg_id, offset, &msg, h,
&hcnt);
mutex_release(&chan->mlock);
if (ret >= 0 && hcnt) { /* install into caller handle table and copy them out */ int rc = user_return_handles(uctx, msg.handles, h, hcnt); if (rc < 0) {
ret = rc;
}
/* drop references obtained in user_msg_read_locked */ for (uint i = 0; i < hcnt; i++)
handle_decref(h[i]);
}
}
handle_decref(chandle);
return (long)ret;
}
int ipc_read_msg(struct handle* chandle,
uint32_t msg_id,
uint32_t offset, struct ipc_msg_kern* msg) { int ret;
if (!msg) return ERR_INVALID_ARGS;
ret = check_channel(chandle); if (ret == NO_ERROR) { struct ipc_chan* chan = containerof(chandle, struct ipc_chan, handle);
mutex_acquire(&chan->mlock);
ret = kern_msg_read_locked(chan->msg_queue, msg_id, offset, msg);
mutex_release(&chan->mlock);
} return ret;
}
#else/* WITH_TRUSTY_IPC */
long __SYSCALL sys_send_msg(uint32_t handle_id, user_addr_t user_msg) { return (long)ERR_NOT_SUPPORTED;
}
long __SYSCALL sys_get_msg(uint32_t handle_id, user_addr_t user_msg_info) { return (long)ERR_NOT_SUPPORTED;
}
long __SYSCALL sys_put_msg(uint32_t handle_id, uint32_t msg_id) { return (long)ERR_NOT_SUPPORTED;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.