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 a non-ack
70 static inline bool flounder_stub_ump_can_send(struct flounder_ump_state *s) {
71 bool r = (ump_index_t)(s->next_id - s->ack_id) < s->chan.max_send_msgs;
75 /// Computes (from seq/ack numbers) whether we can currently send an ack
77 static inline bool flounder_stub_ump_can_send_ack(struct flounder_ump_state *s) {
78 bool r = (ump_index_t)(s->next_id - s->ack_id) <= s->chan.max_send_msgs;
82 #define ENABLE_MESSAGE_PASSING_TRACE 1
83 /// Prepare a "control" word (header for each UMP message fragment)
84 static inline void flounder_stub_ump_control_fill(struct flounder_ump_state *s,
85 struct ump_control *ctrl,
88 #if ENABLE_MESSAGE_PASSING_TRACE
89 trace_event_raw((((uint64_t)0xEA)<<56) |
90 ((uint64_t)s->chan.sendid << 12) |
91 (s->next_id & 0xffff));
92 #endif // ENABLE_MESSAGE_PASSING_TRACE
93 assert(s->chan.sendid != 0);
94 assert(msgtype < (1 << FL_UMP_MSGTYPE_BITS)); // check for overflow
95 ctrl->header = ((uintptr_t)msgtype << UMP_INDEX_BITS) | (uintptr_t)s->seq_id;
96 ctrl->token = s->token;
97 s->last_ack = s->seq_id;
101 /// Process a "control" word
102 static inline int flounder_stub_ump_control_process(struct flounder_ump_state *s,
103 struct ump_control ctrl)
105 #if ENABLE_MESSAGE_PASSING_TRACE
106 trace_event_raw( (((uint64_t)0xEB)<<56) |
107 ((uint64_t)s->chan.recvid << 12) |
108 (s->seq_id & 0xffff));
109 #endif // ENABLE_MESSAGE_PASSING_TRACE
110 s->ack_id = ctrl.header & UMP_INDEX_MASK;
112 return ctrl.header >> UMP_INDEX_BITS;
115 /// Emit memory barrier needed between writing UMP payload and header
116 static inline void flounder_stub_ump_barrier(void)
118 #if defined(__i386__) || defined(__x86_64__)
119 /* the x86 memory model ensures ordering of stores, so all we need to do
120 * is prevent the compiler from reordering the instructions */
121 __asm volatile ("" : : : "memory");
123 /* use conservative GCC intrinsic */
124 __sync_synchronize();
128 /// Should we send an ACK?
129 static inline bool flounder_stub_ump_needs_ack(struct flounder_ump_state *s)
131 // send a forced ACK if the channel is full
132 // FIXME: should probably send it only when "nearly" full
133 return (ump_index_t)(s->seq_id - s->last_ack) >=
134 (ump_index_t)(s->chan.max_recv_msgs - 1);
136 /// Send an explicit ACK
137 static inline void flounder_stub_ump_send_ack(struct flounder_ump_state *s)
139 assert(flounder_stub_ump_can_send_ack(s));
140 struct ump_control ctrl;
141 volatile struct ump_message *msg = ump_chan_get_next(&s->chan, &ctrl);
142 flounder_stub_ump_control_fill(s, &ctrl, FL_UMP_ACK);
143 msg->header.control = ctrl;
146 /// Send a cap ACK (message that we are ready to receive caps)
147 static inline void flounder_stub_ump_send_cap_ack(struct flounder_ump_state *s)
149 assert(flounder_stub_ump_can_send(s));
150 struct ump_control ctrl;
151 volatile struct ump_message *msg = ump_chan_get_next(&s->chan, &ctrl);
152 flounder_stub_ump_control_fill(s, &ctrl, FL_UMP_CAP_ACK);
153 msg->header.control = ctrl;
158 #endif // __FLOUNDER_SUPPORT_UMP_H