mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-21 14:37:50 +00:00
187 lines
4.1 KiB
C
187 lines
4.1 KiB
C
|
/*
|
||
|
* \brief IPC message buffer layout for NOVA
|
||
|
* \author Norman Feske
|
||
|
* \date 2009-10-02
|
||
|
*
|
||
|
* On NOVA, we use IPC to transmit plain data and for capability delegation.
|
||
|
* Therefore the message buffer contains both categories of payload. The
|
||
|
* capability-specific part are the members '_snd_pt*' (sending capability
|
||
|
* selectors) and '_rcv_pt*' (receiving capability selectors).
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Copyright (C) 2009-2011 Genode Labs GmbH
|
||
|
*
|
||
|
* This file is part of the Genode OS framework, which is distributed
|
||
|
* under the terms of the GNU General Public License version 2.
|
||
|
*/
|
||
|
|
||
|
#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
|
||
|
#define _INCLUDE__BASE__IPC_MSGBUF_H_
|
||
|
|
||
|
/* Genode includes */
|
||
|
#include <base/cap_sel_alloc.h>
|
||
|
|
||
|
/* NOVA includes */
|
||
|
#include <nova/syscalls.h>
|
||
|
|
||
|
namespace Genode {
|
||
|
|
||
|
class Msgbuf_base
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
enum { MAX_CAP_ARGS_LOG2 = 2, MAX_CAP_ARGS = 1 << MAX_CAP_ARGS_LOG2 };
|
||
|
|
||
|
protected:
|
||
|
|
||
|
size_t _size;
|
||
|
|
||
|
/**
|
||
|
* Number of portal-capability selectors to send
|
||
|
*/
|
||
|
size_t _snd_pt_sel_cnt;
|
||
|
|
||
|
/**
|
||
|
* Portal capability selectors to delegate
|
||
|
*/
|
||
|
int _snd_pt_sel[MAX_CAP_ARGS];
|
||
|
|
||
|
/**
|
||
|
* Base of portal receive window
|
||
|
*/
|
||
|
int _rcv_pt_base;
|
||
|
|
||
|
/**
|
||
|
* Read counter for unmarshalling portal capability selectors
|
||
|
*/
|
||
|
int _rcv_pt_sel_cnt;
|
||
|
|
||
|
/**
|
||
|
* Flag set to true if receive window must be re-initialized
|
||
|
*/
|
||
|
bool _rcv_dirty;
|
||
|
|
||
|
char _msg_start[]; /* symbol marks start of message */
|
||
|
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
* Constructor
|
||
|
*/
|
||
|
Msgbuf_base() : _rcv_dirty(true)
|
||
|
{
|
||
|
rcv_reset();
|
||
|
snd_reset();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Begin of actual message buffer
|
||
|
*/
|
||
|
char buf[];
|
||
|
|
||
|
/**
|
||
|
* Return size of message buffer
|
||
|
*/
|
||
|
inline size_t size() const { return _size; }
|
||
|
|
||
|
/**
|
||
|
* Return address of message buffer
|
||
|
*/
|
||
|
inline void *addr() { return &_msg_start[0]; }
|
||
|
|
||
|
/**
|
||
|
* Reset portal capability selector payload
|
||
|
*/
|
||
|
inline void snd_reset() { _snd_pt_sel_cnt = 0; }
|
||
|
|
||
|
/**
|
||
|
* Append portal capability selector to message buffer
|
||
|
*/
|
||
|
inline bool snd_append_pt_sel(int pt_sel)
|
||
|
{
|
||
|
if (_snd_pt_sel_cnt >= MAX_CAP_ARGS - 1)
|
||
|
return false;
|
||
|
|
||
|
_snd_pt_sel[_snd_pt_sel_cnt++] = pt_sel;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return number of marshalled portal-capability selectors
|
||
|
*/
|
||
|
inline size_t snd_pt_sel_cnt() { return _snd_pt_sel_cnt; }
|
||
|
|
||
|
/**
|
||
|
* Return portal capability selector
|
||
|
*
|
||
|
* \param i index (0 ... 'pt_sel_cnt()' - 1)
|
||
|
* \return portal-capability selector, or
|
||
|
* -1 if index is invalid
|
||
|
*/
|
||
|
int snd_pt_sel(unsigned i) { return i < _snd_pt_sel_cnt ? _snd_pt_sel[i] : -1; }
|
||
|
|
||
|
/**
|
||
|
* Request current portal-receive window
|
||
|
*/
|
||
|
int rcv_pt_base() { return _rcv_pt_base; }
|
||
|
|
||
|
/**
|
||
|
* Reset portal-capability receive window
|
||
|
*/
|
||
|
void rcv_reset() { _rcv_pt_sel_cnt = 0; }
|
||
|
|
||
|
/**
|
||
|
* Return received portal-capability selector
|
||
|
*/
|
||
|
int rcv_pt_sel()
|
||
|
{
|
||
|
_rcv_dirty = true;
|
||
|
return _rcv_pt_base + _rcv_pt_sel_cnt++;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Return true if receive window must be re-initialized
|
||
|
*
|
||
|
* After reading portal selectors from the message buffer using
|
||
|
* 'rcv_pt_sel()', we assume that the IDC call populared the
|
||
|
* current receive window with one or more portal capabilities.
|
||
|
* To enable the reception of portal capability selectors for the
|
||
|
* next IDC, we need a fresh receive window.
|
||
|
*/
|
||
|
bool rcv_dirty() { return _rcv_dirty; }
|
||
|
|
||
|
/**
|
||
|
* Initialize receive window for portal capability selectors
|
||
|
*
|
||
|
* \param utcb UTCB of designated receiver thread
|
||
|
*
|
||
|
* Depending on the 'rcv_dirty' state of the message buffer, this
|
||
|
* function allocates a fresh receive window and clears 'rcv_dirty'.
|
||
|
*/
|
||
|
void rcv_prepare_pt_sel_window(Nova::Utcb *utcb)
|
||
|
{
|
||
|
if (rcv_dirty()) {
|
||
|
_rcv_pt_base = cap_selector_allocator()->alloc(MAX_CAP_ARGS_LOG2);
|
||
|
_rcv_dirty = false;
|
||
|
}
|
||
|
|
||
|
/* register receive window at the UTCB */
|
||
|
utcb->crd_rcv = Nova::Obj_crd(rcv_pt_base(),MAX_CAP_ARGS_LOG2);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
template <unsigned BUF_SIZE>
|
||
|
class Msgbuf : public Msgbuf_base
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
char buf[BUF_SIZE];
|
||
|
|
||
|
Msgbuf() { _size = BUF_SIZE; }
|
||
|
};
|
||
|
}
|
||
|
|
||
|
#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
|