mt-waitset: adding masking of channels so a thread won't handle two messages at the...
[barrelfish] / include / flounder / flounder_support_ump.h
1 /**
2  * \file
3  * \brief Prototypes for use by flounder-generated stubs
4  */
5
6 /*
7  * Copyright (c) 2010, ETH Zurich.
8  * All rights reserved.
9  *
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.
13  */
14
15 #ifndef __FLOUNDER_SUPPORT_UMP_H
16 #define __FLOUNDER_SUPPORT_UMP_H
17
18 #include <sys/cdefs.h>
19
20 #include <barrelfish/ump_chan.h>
21 #include <flounder/flounder_support_caps.h>
22 #include <trace/trace.h>
23
24 __BEGIN_DECLS
25
26 /// Number of bits available for the message type in the header
27 #define FL_UMP_MSGTYPE_BITS (UMP_HEADER_BITS - UMP_INDEX_BITS)
28
29 /// Special message types
30 enum flounder_ump_msgtype {
31     FL_UMP_ACK = 0,
32     FL_UMP_BIND = 1,
33     FL_UMP_BIND_REPLY = 2,
34     FL_UMP_CAP_ACK = (1 << FL_UMP_MSGTYPE_BITS) - 1,
35 };
36
37 struct flounder_ump_state {
38     struct ump_chan chan;
39
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
44
45     struct flounder_cap_state capst; ///< State for indirect cap tx/rx machinery
46     uint32_t token;        ///< Outgoing message's token
47 };
48
49 void flounder_stub_ump_state_init(struct flounder_ump_state *s, void *binding);
50
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);
54
55 errval_t flounder_stub_ump_recv_string(volatile struct ump_message *msg,
56                                        char *str, size_t *pos, size_t *len,
57                                        size_t maxsize);
58
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);
62
63 errval_t flounder_stub_ump_recv_buf(volatile struct ump_message *msg,
64                                     void *buf, size_t *len, size_t *pos,
65                                     size_t maxsize);
66
67
68 /// Computes (from seq/ack numbers) whether we can currently send a non-ack
69 /// on the channel
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;
72     return r;
73 }
74
75 /// Computes (from seq/ack numbers) whether we can currently send an ack
76 /// on the channel
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;
79     return r;
80 }
81
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,
86                                                   int msgtype)
87 {
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;
98     s->next_id++;
99 }
100
101 /// Process a "control" word
102 static inline int flounder_stub_ump_control_process(struct flounder_ump_state *s,
103                                                     struct ump_control ctrl)
104 {
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;
111     s->seq_id++;
112     return ctrl.header >> UMP_INDEX_BITS;
113 }
114
115 /// Emit memory barrier needed between writing UMP payload and header
116 static inline void flounder_stub_ump_barrier(void)
117 {
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");
122 #else
123     /* use conservative GCC intrinsic */
124     __sync_synchronize();
125 #endif
126 }
127
128 /// Should we send an ACK?
129 static inline bool flounder_stub_ump_needs_ack(struct flounder_ump_state *s)
130 {
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);
135 }
136 /// Send an explicit ACK
137 static inline void flounder_stub_ump_send_ack(struct flounder_ump_state *s)
138 {
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;
144 }
145
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)
148 {
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;
154 }
155
156 __END_DECLS
157
158 #endif // __FLOUNDER_SUPPORT_UMP_H