3 * \brief Prototypes for use by flounder-generated stubs
7 * Copyright (c) 2010, ETH Zurich.
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
15 #ifndef __FLOUNDER_SUPPORT_UMP_H
16 #define __FLOUNDER_SUPPORT_UMP_H
18 #include <sys/cdefs.h>
20 #include <barrelfish/ump_chan.h>
21 #include <flounder/flounder_support_caps.h>
22 #include <trace/trace.h>
26 /// Number of bits available for the message type in the header
27 #define FL_UMP_MSGTYPE_BITS (UMP_HEADER_BITS - UMP_INDEX_BITS)
29 /// Special message types
30 enum flounder_ump_msgtype {
33 FL_UMP_BIND_REPLY = 2,
34 FL_UMP_CAP_ACK = (1 << FL_UMP_MSGTYPE_BITS) - 1,
37 struct flounder_ump_state {
40 ump_index_t next_id; ///< Sequence number of next message to be sent
41 ump_index_t seq_id; ///< Last sequence number received from remote
42 ump_index_t ack_id; ///< Last sequence number acknowledged by remote
43 ump_index_t last_ack; ///< Last acknowledgement we sent to remote
45 struct flounder_cap_state capst; ///< State for indirect cap tx/rx machinery
46 uint32_t token; ///< Outgoing message's token
49 void flounder_stub_ump_state_init(struct flounder_ump_state *s, void *binding);
51 errval_t flounder_stub_ump_send_string(struct flounder_ump_state *s,
52 int msgnum, const char *str,
53 size_t *pos, size_t *len);
55 errval_t flounder_stub_ump_recv_string(volatile struct ump_message *msg,
56 char *str, size_t *pos, size_t *len,
59 errval_t flounder_stub_ump_send_buf(struct flounder_ump_state *s,
60 int msgnum, const void *buf,
61 size_t len, size_t *pos);
63 errval_t flounder_stub_ump_recv_buf(volatile struct ump_message *msg,
64 void *buf, size_t *len, size_t *pos,
68 /// Computes (from seq/ack numbers) whether we can currently send on the channel
69 static inline bool flounder_stub_ump_can_send(struct flounder_ump_state *s) {
70 bool r = (ump_index_t)(s->next_id - s->ack_id) <= s->chan.max_send_msgs;
74 #define ENABLE_MESSAGE_PASSING_TRACE 1
75 /// Prepare a "control" word (header for each UMP message fragment)
76 static inline void flounder_stub_ump_control_fill(struct flounder_ump_state *s,
77 struct ump_control *ctrl,
80 #if ENABLE_MESSAGE_PASSING_TRACE
81 trace_event_raw((((uint64_t)0xEA)<<56) |
82 ((uint64_t)s->chan.sendid << 12) |
83 (s->next_id & 0xffff));
84 #endif // ENABLE_MESSAGE_PASSING_TRACE
85 assert(s->chan.sendid != 0);
86 assert(msgtype < (1 << FL_UMP_MSGTYPE_BITS)); // check for overflow
87 ctrl->header = ((uintptr_t)msgtype << UMP_INDEX_BITS) | (uintptr_t)s->seq_id;
88 ctrl->token = s->token;
89 s->last_ack = s->seq_id;
93 /// Process a "control" word
94 static inline int flounder_stub_ump_control_process(struct flounder_ump_state *s,
95 struct ump_control ctrl)
97 #if ENABLE_MESSAGE_PASSING_TRACE
98 trace_event_raw( (((uint64_t)0xEB)<<56) |
99 ((uint64_t)s->chan.recvid << 12) |
100 (s->seq_id & 0xffff));
101 #endif // ENABLE_MESSAGE_PASSING_TRACE
102 s->ack_id = ctrl.header & UMP_INDEX_MASK;
104 return ctrl.header >> UMP_INDEX_BITS;
107 /// Emit memory barrier needed between writing UMP payload and header
108 static inline void flounder_stub_ump_barrier(void)
110 #if defined(__i386__) || defined(__x86_64__)
111 /* the x86 memory model ensures ordering of stores, so all we need to do
112 * is prevent the compiler from reordering the instructions */
113 __asm volatile ("" : : : "memory");
115 /* use conservative GCC intrinsic */
116 __sync_synchronize();
120 /// Should we send an ACK?
121 static inline bool flounder_stub_ump_needs_ack(struct flounder_ump_state *s)
123 // send a forced ACK if the channel is full
124 // FIXME: should probably send it only when "nearly" full
125 return (ump_index_t)(s->seq_id - s->last_ack) >=
126 (ump_index_t)(s->chan.max_recv_msgs - 1);
128 /// Send an explicit ACK
129 static inline void flounder_stub_ump_send_ack(struct flounder_ump_state *s)
131 assert(flounder_stub_ump_can_send(s));
132 struct ump_control ctrl;
133 volatile struct ump_message *msg = ump_chan_get_next(&s->chan, &ctrl);
134 flounder_stub_ump_control_fill(s, &ctrl, FL_UMP_ACK);
135 msg->header.control = ctrl;
138 /// Send a cap ACK (message that we are ready to receive caps)
139 static inline void flounder_stub_ump_send_cap_ack(struct flounder_ump_state *s)
141 assert(flounder_stub_ump_can_send(s));
142 struct ump_control ctrl;
143 volatile struct ump_message *msg = ump_chan_get_next(&s->chan, &ctrl);
144 flounder_stub_ump_control_fill(s, &ctrl, FL_UMP_CAP_ACK);
145 msg->header.control = ctrl;
150 #endif // __FLOUNDER_SUPPORT_UMP_H