aos/include/aos/lmp_chan.h
Daniel Schwyn 6d444bf552 Main handout
Signed-off-by: Daniel Schwyn <daniel.schwyn@inf.ethz.ch>
2022-03-03 14:57:51 +01:00

169 lines
5.1 KiB
C

/**
* \file
* \brief Bidirectional LMP channel
*/
/*
* Copyright (c) 2009, 2010, 2011, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
* ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
*/
#ifndef BARRELFISH_LMP_CHAN_H
#define BARRELFISH_LMP_CHAN_H
#include <sys/cdefs.h>
#include <aos/waitset.h>
#include <aos/lmp_endpoints.h>
#include <assert.h>
__BEGIN_DECLS
struct lmp_chan;
struct event_queue_node;
/// A bidirectional LMP channel
struct lmp_chan {
struct waitset_chanstate send_waitset; ///< State belonging to waitset (for send)
struct lmp_chan *next, *prev; ///< Next/prev in list of channels with send events
struct capref local_cap, remote_cap; ///< Capabilities to local/remote endpoints
struct lmp_endpoint *endpoint; ///< Incoming LMP endpoint (in dispatcher)
/// connection state
enum {LMP_DISCONNECTED, ///< Disconnected
LMP_BIND_WAIT, ///< Waiting for bind reply
LMP_MONITOR_ACCEPT, ///< Special case for monitor binding: waiting for cap
LMP_CONNECTED, ///< Connection established
} connstate;
size_t buflen_words; ///< requested LMP buffer length, in words
};
void lmp_chan_init(struct lmp_chan *lc);
void lmp_chan_destroy(struct lmp_chan *lc);
errval_t lmp_chan_accept(struct lmp_chan *lc, size_t buflen_words,
struct capref endpoint);
errval_t lmp_chan_register_send(struct lmp_chan *lc, struct waitset *ws,
struct event_closure closure);
errval_t lmp_chan_deregister_send(struct lmp_chan *lc);
void lmp_chan_migrate_send(struct lmp_chan *lc, struct waitset *ws);
errval_t lmp_chan_alloc_recv_slot(struct lmp_chan *lc);
void lmp_channels_retry_send_disabled(dispatcher_handle_t handle);
/**
* \brief Register an event handler to be notified when messages can be received
*
* In the future, call the closure on the given waitset when it is likely that
* a message can be received on the channel. A channel may only be registered
* with a single receive event handler on a single waitset at any one time.
*
* \param lc LMP channel
* \param ws Waitset
* \param closure Event handler
*/
static inline errval_t lmp_chan_register_recv(struct lmp_chan *lc,
struct waitset *ws,
struct event_closure closure)
{
return lmp_endpoint_register(lc->endpoint, ws, closure);
}
/**
* \brief Cancel an event registration made with lmp_chan_register_recv()
*
* \param lc LMP channel
*/
static inline errval_t lmp_chan_deregister_recv(struct lmp_chan *lc)
{
return lmp_endpoint_deregister(lc->endpoint);
}
/**
* \brief Migrate an event registration made with
* lmp_chan_register_recv() to a new waitset
*
* \param lc LMP channel
* \param ws New waitset
*/
static inline void lmp_chan_migrate_recv(struct lmp_chan *lc,
struct waitset *ws)
{
lmp_endpoint_migrate(lc->endpoint, ws);
}
/**
* \brief Receive a message from an LMP channel, if possible
*
* Non-blocking. May fail if no message is available.
*
* \param lc LMP channel
* \param msg LMP message buffer, to be filled-in
* \param cap If non-NULL, filled-in with location of received capability, if any
*/
static inline errval_t lmp_chan_recv(struct lmp_chan *lc,
struct lmp_recv_msg *msg,
struct capref *cap)
{
assert(msg != NULL);
assert(msg->buf.buflen == LMP_MSG_LENGTH);
return lmp_endpoint_recv(lc->endpoint, &msg->buf, cap);
}
/**
* \brief Check if a channel has data to receive
*/
static inline bool lmp_chan_can_recv(struct lmp_chan *lc)
{
assert(lc);
assert(lc->endpoint);
return lmp_endpoint_can_recv(lc->endpoint);
}
/**
* \brief Set the receive capability slot for an LMP channel
*
* \param lc LMP channel
* \param slot Receive slot
*/
static inline void lmp_chan_set_recv_slot(struct lmp_chan *lc,
struct capref slot)
{
lmp_endpoint_set_recv_slot(lc->endpoint, slot);
}
/**
* \brief Is the given error value a transient LMP error
*
* Returns true iff the given error code indicates a transient
* LMP send error condition that may succeed on a subsequent retry.
*/
static inline bool lmp_err_is_transient(errval_t err)
{
enum err_code ec = err_no(err);
return ec == SYS_ERR_LMP_BUF_OVERFLOW
|| ec == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_LOOKUP
|| ec == SYS_ERR_LMP_CAPTRANSFER_DST_CNODE_INVALID
|| ec == SYS_ERR_LMP_CAPTRANSFER_DST_SLOT_OCCUPIED
|| ec == SYS_ERR_LMP_TARGET_DISABLED;
}
/**
* \brief Get a receiving chanstate of LMP channel
*/
static inline struct waitset_chanstate * lmp_chan_get_receiving_channel(struct lmp_chan *chan)
{
assert(chan->endpoint);
return &chan->endpoint->waitset_state;
}
#include <aos/lmp_chan_arch.h>
__END_DECLS
#endif // BARRELFISH_LMP_CHAN_H