mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-17 06:38:28 +00:00
committed by
Norman Feske
parent
f128a52e8b
commit
575a81a633
@ -18,6 +18,10 @@
|
|||||||
#include <kernel/interface.h>
|
#include <kernel/interface.h>
|
||||||
#include <base/native_capability.h>
|
#include <base/native_capability.h>
|
||||||
#include <base/stdint.h>
|
#include <base/stdint.h>
|
||||||
|
#include <util/string.h>
|
||||||
|
|
||||||
|
/* base-hw includes */
|
||||||
|
#include <kernel/log.h>
|
||||||
|
|
||||||
namespace Genode
|
namespace Genode
|
||||||
{
|
{
|
||||||
@ -49,12 +53,11 @@ namespace Genode
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Message that is communicated between user threads
|
* Message that is communicated between user threads
|
||||||
|
*
|
||||||
|
* \param MAX_SIZE maximum size the object is allowed to take
|
||||||
*/
|
*/
|
||||||
struct Ipc_msg
|
template <size_t MAX_SIZE>
|
||||||
{
|
struct Ipc_msg;
|
||||||
size_t size;
|
|
||||||
uint8_t data[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message that is communicated from a thread creator to the new thread
|
* Message that is communicated from a thread creator to the new thread
|
||||||
@ -115,6 +118,115 @@ namespace Genode
|
|||||||
struct Native_pd_args { };
|
struct Native_pd_args { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <Genode::size_t MAX_SIZE>
|
||||||
|
class Genode::Ipc_msg
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t _data_size;
|
||||||
|
uint8_t _data[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return size of payload-preceding meta data
|
||||||
|
*/
|
||||||
|
size_t _header_size() const { return (addr_t)_data - (addr_t)this; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return maximum payload size
|
||||||
|
*/
|
||||||
|
size_t _max_data_size() const { return MAX_SIZE - _header_size(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return size of header and current payload
|
||||||
|
*/
|
||||||
|
size_t _size() const { return _header_size() + _data_size; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information about current await-request operation
|
||||||
|
*
|
||||||
|
* \return buf_base base of receive buffer
|
||||||
|
* \return buf_size size of receive buffer
|
||||||
|
*/
|
||||||
|
void info_about_await_request(void * & buf_base, size_t & buf_size)
|
||||||
|
{
|
||||||
|
buf_base = this;
|
||||||
|
buf_size = MAX_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information about current send-request operation
|
||||||
|
*
|
||||||
|
* \return msg_base base of complete send-message data
|
||||||
|
* \return msg_size size of complete send-message data
|
||||||
|
* \return buf_base base of receive buffer
|
||||||
|
* \return buf_size size of receive buffer
|
||||||
|
*/
|
||||||
|
void info_about_send_request(void * & msg_base, size_t & msg_size,
|
||||||
|
void * & buf_base, size_t & buf_size)
|
||||||
|
{
|
||||||
|
msg_base = this;
|
||||||
|
msg_size = _size();
|
||||||
|
buf_base = this;
|
||||||
|
buf_size = MAX_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get information about current send-reply operation
|
||||||
|
*
|
||||||
|
* \return msg_base base of complete send-message data
|
||||||
|
* \return msg_size size of complete send-message data
|
||||||
|
*/
|
||||||
|
void info_about_send_reply(void * & msg_base, size_t & msg_size)
|
||||||
|
{
|
||||||
|
msg_base = this;
|
||||||
|
msg_size = _size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install message that shall be send
|
||||||
|
*
|
||||||
|
* \param data base of payload
|
||||||
|
* \param raw_data_size size of payload without preceding name
|
||||||
|
* \param name local name that shall precede raw payload
|
||||||
|
*/
|
||||||
|
void prepare_send(void * const data, size_t raw_data_size,
|
||||||
|
unsigned const name)
|
||||||
|
{
|
||||||
|
/* limit data size */
|
||||||
|
enum { NAME_SIZE = sizeof(name) };
|
||||||
|
size_t const data_size = raw_data_size + NAME_SIZE;
|
||||||
|
if (data_size > _max_data_size()) {
|
||||||
|
kernel_log() << __func__ << ": oversized message outgoing\n";
|
||||||
|
raw_data_size = _max_data_size() - NAME_SIZE;
|
||||||
|
}
|
||||||
|
/* copy data */
|
||||||
|
*(unsigned *)_data = name;
|
||||||
|
void * const raw_data_dst = (void *)((addr_t)_data + NAME_SIZE);
|
||||||
|
void * const raw_data_src = (void *)((addr_t)data + NAME_SIZE);
|
||||||
|
memcpy(raw_data_dst, raw_data_src, raw_data_size);
|
||||||
|
_data_size = data_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read out message that was received
|
||||||
|
*
|
||||||
|
* \param buf_base base of read buffer
|
||||||
|
* \param buf_size size of read buffer
|
||||||
|
*/
|
||||||
|
void finish_receive(void * const buf_base, size_t const buf_size)
|
||||||
|
{
|
||||||
|
/* limit data size */
|
||||||
|
if (_data_size > buf_size) {
|
||||||
|
kernel_log() << __func__ << ": oversized message incoming\n";
|
||||||
|
_data_size = buf_size;
|
||||||
|
}
|
||||||
|
/* copy data */
|
||||||
|
memcpy(buf_base, _data, _data_size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Genode::Startup_msg
|
class Genode::Startup_msg
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -140,40 +252,17 @@ class Genode::Startup_msg
|
|||||||
|
|
||||||
struct Genode::Native_utcb
|
struct Genode::Native_utcb
|
||||||
{
|
{
|
||||||
|
enum { SIZE = 1 << MIN_MAPPING_SIZE_LOG2 };
|
||||||
|
|
||||||
union {
|
union {
|
||||||
uint8_t data[1 << MIN_MAPPING_SIZE_LOG2];
|
uint8_t data[SIZE];
|
||||||
Ipc_msg ipc_msg;
|
Ipc_msg<SIZE> ipc_msg;
|
||||||
Startup_msg startup_msg;
|
Startup_msg startup_msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
void call_await_request_msg(void * & buf_base, size_t & buf_size)
|
size_t size() const { return SIZE; }
|
||||||
{
|
|
||||||
buf_base = base();
|
|
||||||
buf_size = size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void call_send_request_msg(void * & msg_base, size_t & msg_size,
|
void * base() const { return (void *)data; }
|
||||||
void * & buf_base, size_t & buf_size)
|
|
||||||
{
|
|
||||||
msg_base = ipc_msg_base();
|
|
||||||
msg_size = ipc_msg_size();
|
|
||||||
buf_base = base();
|
|
||||||
buf_size = size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void call_send_reply_msg(void * & msg_base, size_t & msg_size)
|
|
||||||
{
|
|
||||||
msg_base = ipc_msg_base();
|
|
||||||
msg_size = ipc_msg_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() { return sizeof(data) / sizeof(data[0]); }
|
|
||||||
void * base() { return &data; }
|
|
||||||
addr_t top() { return (addr_t)base() + size(); }
|
|
||||||
void * ipc_msg_base() { return &ipc_msg; }
|
|
||||||
size_t ipc_msg_size() { return ipc_msg_header_size() + ipc_msg.size; }
|
|
||||||
size_t ipc_msg_max_size() { return top() - (addr_t)&ipc_msg; }
|
|
||||||
size_t ipc_msg_header_size() { return (addr_t)ipc_msg.data - (addr_t)&ipc_msg; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _BASE__NATIVE_TYPES_H_ */
|
#endif /* _BASE__NATIVE_TYPES_H_ */
|
||||||
|
@ -35,46 +35,6 @@ enum
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/***************
|
|
||||||
** Utilities **
|
|
||||||
***************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy message from the callers UTCB to message buffer
|
|
||||||
*/
|
|
||||||
static void utcb_to_msgbuf(Msgbuf_base * const msgbuf)
|
|
||||||
{
|
|
||||||
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
|
||||||
size_t msg_size = utcb->ipc_msg.size;
|
|
||||||
if (msg_size > msgbuf->size()) {
|
|
||||||
kernel_log() << "oversized IPC message\n";
|
|
||||||
msg_size = msgbuf->size();
|
|
||||||
}
|
|
||||||
memcpy(msgbuf->buf, utcb->ipc_msg.data, msg_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy message from message buffer to the callers UTCB
|
|
||||||
*/
|
|
||||||
static void msgbuf_to_utcb(Msgbuf_base * const msg_buf, size_t msg_size,
|
|
||||||
unsigned const local_name)
|
|
||||||
{
|
|
||||||
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
|
||||||
enum { NAME_SIZE = sizeof(local_name) };
|
|
||||||
size_t const ipc_msg_size = msg_size + NAME_SIZE;
|
|
||||||
if (ipc_msg_size > utcb->ipc_msg_max_size()) {
|
|
||||||
kernel_log() << "oversized IPC message\n";
|
|
||||||
msg_size = utcb->ipc_msg_max_size() - NAME_SIZE;
|
|
||||||
}
|
|
||||||
*(unsigned *)utcb->ipc_msg.data = local_name;
|
|
||||||
void * const utcb_msg = (void *)((addr_t)utcb->ipc_msg.data + NAME_SIZE);
|
|
||||||
void * const buf_msg = (void *)((addr_t)msg_buf->buf + NAME_SIZE);
|
|
||||||
memcpy(utcb_msg, buf_msg, msg_size);
|
|
||||||
utcb->ipc_msg.size = ipc_msg_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*****************
|
/*****************
|
||||||
** Ipc_ostream **
|
** Ipc_ostream **
|
||||||
*****************/
|
*****************/
|
||||||
@ -118,12 +78,13 @@ void Ipc_client::_call()
|
|||||||
{
|
{
|
||||||
/* send request and receive corresponding reply */
|
/* send request and receive corresponding reply */
|
||||||
unsigned const local_name = Ipc_ostream::_dst.local_name();
|
unsigned const local_name = Ipc_ostream::_dst.local_name();
|
||||||
msgbuf_to_utcb(_snd_msg, _write_offset, local_name);
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
|
utcb->ipc_msg.prepare_send(_snd_msg->buf, _write_offset, local_name);
|
||||||
if (Kernel::send_request_msg(Ipc_ostream::_dst.dst())) {
|
if (Kernel::send_request_msg(Ipc_ostream::_dst.dst())) {
|
||||||
PERR("failed to receive reply");
|
PERR("failed to receive reply");
|
||||||
throw Blocking_canceled();
|
throw Blocking_canceled();
|
||||||
}
|
}
|
||||||
utcb_to_msgbuf(_rcv_msg);
|
utcb->ipc_msg.finish_receive(_rcv_msg->buf, _rcv_msg->size());
|
||||||
|
|
||||||
/* reset unmarshaller */
|
/* reset unmarshaller */
|
||||||
_write_offset = _read_offset = RPC_OBJECT_ID_SIZE;
|
_write_offset = _read_offset = RPC_OBJECT_ID_SIZE;
|
||||||
@ -167,7 +128,8 @@ void Ipc_server::_wait()
|
|||||||
PERR("failed to receive request");
|
PERR("failed to receive request");
|
||||||
throw Blocking_canceled();
|
throw Blocking_canceled();
|
||||||
}
|
}
|
||||||
utcb_to_msgbuf(_rcv_msg);
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
|
utcb->ipc_msg.finish_receive(_rcv_msg->buf, _rcv_msg->size());
|
||||||
|
|
||||||
/* update server state */
|
/* update server state */
|
||||||
_prepare_next_reply_wait();
|
_prepare_next_reply_wait();
|
||||||
@ -176,8 +138,9 @@ void Ipc_server::_wait()
|
|||||||
|
|
||||||
void Ipc_server::_reply()
|
void Ipc_server::_reply()
|
||||||
{
|
{
|
||||||
|
unsigned const local_name = Ipc_ostream::_dst.local_name();
|
||||||
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
utcb->ipc_msg.size = _write_offset;
|
utcb->ipc_msg.prepare_send(_snd_msg->buf, _write_offset, local_name);
|
||||||
Kernel::send_reply_msg(0);
|
Kernel::send_reply_msg(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,12 +154,13 @@ void Ipc_server::_reply_wait()
|
|||||||
}
|
}
|
||||||
/* send reply and receive next request */
|
/* send reply and receive next request */
|
||||||
unsigned const local_name = Ipc_ostream::_dst.local_name();
|
unsigned const local_name = Ipc_ostream::_dst.local_name();
|
||||||
msgbuf_to_utcb(_snd_msg, _write_offset, local_name);
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
|
utcb->ipc_msg.prepare_send(_snd_msg->buf, _write_offset, local_name);
|
||||||
if (Kernel::send_reply_msg(1)) {
|
if (Kernel::send_reply_msg(1)) {
|
||||||
PERR("failed to receive request");
|
PERR("failed to receive request");
|
||||||
throw Blocking_canceled();
|
throw Blocking_canceled();
|
||||||
}
|
}
|
||||||
utcb_to_msgbuf(_rcv_msg);
|
utcb->ipc_msg.finish_receive(_rcv_msg->buf, _rcv_msg->size());
|
||||||
|
|
||||||
/* update server state */
|
/* update server state */
|
||||||
_prepare_next_reply_wait();
|
_prepare_next_reply_wait();
|
||||||
|
@ -456,7 +456,7 @@ void Thread::_call_await_request_msg()
|
|||||||
{
|
{
|
||||||
void * buf_base;
|
void * buf_base;
|
||||||
size_t buf_size;
|
size_t buf_size;
|
||||||
_utcb_phys->call_await_request_msg(buf_base, buf_size);
|
_utcb_phys->ipc_msg.info_about_await_request(buf_base, buf_size);
|
||||||
Ipc_node::await_request(buf_base, buf_size);
|
Ipc_node::await_request(buf_base, buf_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,8 +473,8 @@ void Thread::_call_send_request_msg()
|
|||||||
size_t msg_size;
|
size_t msg_size;
|
||||||
void * buf_base;
|
void * buf_base;
|
||||||
size_t buf_size;
|
size_t buf_size;
|
||||||
_utcb_phys->call_send_request_msg(msg_base, msg_size,
|
_utcb_phys->ipc_msg.info_about_send_request(msg_base, msg_size,
|
||||||
buf_base, buf_size);
|
buf_base, buf_size);
|
||||||
Ipc_node::send_request_await_reply(dst, msg_base, msg_size,
|
Ipc_node::send_request_await_reply(dst, msg_base, msg_size,
|
||||||
buf_base, buf_size);
|
buf_base, buf_size);
|
||||||
}
|
}
|
||||||
@ -484,7 +484,7 @@ void Thread::_call_send_reply_msg()
|
|||||||
{
|
{
|
||||||
void * msg_base;
|
void * msg_base;
|
||||||
size_t msg_size;
|
size_t msg_size;
|
||||||
_utcb_phys->call_send_reply_msg(msg_base, msg_size);
|
_utcb_phys->ipc_msg.info_about_send_reply(msg_base, msg_size);
|
||||||
Ipc_node::send_reply(msg_base, msg_size);
|
Ipc_node::send_reply(msg_base, msg_size);
|
||||||
bool const await_request_msg = user_arg_1();
|
bool const await_request_msg = user_arg_1();
|
||||||
if (await_request_msg) { _call_await_request_msg(); }
|
if (await_request_msg) { _call_await_request_msg(); }
|
||||||
|
Reference in New Issue
Block a user