2864b016a0b40d93a922b34d2ea344afee95952b
[archipelago] / xseg / xseg / xseg.h
1 #ifndef _XSEG_H
2 #define _XSEG_H
3
4 #ifndef XSEG_VERSION
5 #define XSEG_VERSION 2012022601
6 #endif
7
8 #ifndef XSEG_PAGE_SHIFT
9 #define XSEG_PAGE_SHIFT 12
10 #endif
11
12 #define XSEG_BASE (0x37fd0UL << XSEG_PAGE_SHIFT)
13 #define XSEG_BASE_AS_PTR ((void *)XSEG_BASE)
14 #define XSEG_BASE_AS_BUF ((char *)XSEG_BASE)
15 #define XSEG_OFFSET(base, ptr) ((unsigned long)(ptr) - (unsigned long)(base))
16 #define XSEG_PTR_CONVERT(ptr, src, dst) ((void *)((unsigned long)(dst) + XSEG_OFFSET(src, ptr)))
17 #define XSEG_TAKE_PTR(ptr, base) XSEG_PTR_CONVERT(ptr, XSEG_BASE, base)
18 #define XSEG_MAKE_PTR(ptr, base) XSEG_PTR_CONVERT(ptr, base, XSEG_BASE)
19
20 #include <sys/util.h>
21 #include <xtypes/xq.h>
22 #include <xtypes/xobj.h>
23 #include <xtypes/xhash.h>
24
25 typedef uint64_t xserial;
26
27 #define NoSerial ((xserial)-1)
28
29 #ifndef XSEG_DEF_REQS
30 #define XSEG_DEF_REQS 512
31 #endif
32
33 /* Peers and Segments
34  *
35  *  Segments are memory segments shared among peers.
36  *  Peers are local execution contexes that share a segment.
37  *
38  *  xseg_type and xseg_peer
39  *
40  *  A peer needs an xseg_type in order to
41  *  create or access a certain segment type,
42  *  and it needs an xseg_peer in order to
43  *  communicate with a certain type of peer.
44  *  Both segment and peer types are identified by name strings.
45  *
46  *  Note that each peer (that is, context) type will need
47  *  different code to access the same type of segment or peer.
48  *  Therefore each peer must have its own "customized" version
49  *  of the xseg library.
50  *
51  *  This is accomplished by mechanisms for registering both
52  *  xseg_type's and xseg_peer's. This can be done at both at build time
53  *  and at runtime, through a plugin-loading mechanism (where applicable).
54  *  The plugin namespace serves both segment and peer type namespace,
55  *  so if a segment type has the same name with a peer type,
56  *  they must be provided by the same plugin.
57  *
58  *  Note also that peers of different types may share the same segment.
59  *  Therefore each peer must know the type of each peer it needs to
60  *  communicate with, and have a driver for it.
61  *
62 */
63
64 struct xseg;
65 struct xseg_port;
66
67 #define MAGIC_OBJH      1
68 #define MAGIC_REQ       2
69 #define MAGIC_PORT      3
70
71 struct xseg_operations {
72         void  (*mfree)(void *mem);
73         long  (*allocate)(const char *name, uint64_t size);
74         long  (*deallocate)(const char *name);
75         void *(*map)(const char *name, uint64_t size, struct xseg *seg);
76         void  (*unmap)(void *xseg, uint64_t size);
77 };
78
79 #define XSEG_NAMESIZE 256
80 #define XSEG_TNAMESIZE 32
81
82 struct xseg_type {
83         struct xseg_operations ops;
84         char name[XSEG_TNAMESIZE];
85 };
86
87 struct xseg_peer_operations {
88         int   (*signal_init)(void);
89         void  (*signal_quit)(void);
90         int   (*signal_join)(struct xseg *xseg);
91         int   (*signal_leave)(struct xseg *xseg);
92         int   (*prepare_wait)(struct xseg *xseg, uint32_t portno);
93         int   (*cancel_wait)(struct xseg *xseg, uint32_t portno);
94         int   (*wait_signal)(struct xseg *xseg, uint32_t usec_timeout);
95         int   (*signal)(struct xseg *xseg, uint32_t portno);
96         void *(*malloc)(uint64_t size);
97         void *(*realloc)(void *mem, uint64_t size);
98         void  (*mfree)(void *mem);
99 };
100
101 struct xseg_peer {
102         struct xseg_peer_operations peer_ops;
103         char name[XSEG_TNAMESIZE];
104 };
105
106 struct xseg_config {
107         uint64_t heap_size;     /* heap size in MB */
108         uint32_t nr_ports;
109         uint32_t page_shift;    /* the alignment unit */
110         char type[XSEG_TNAMESIZE]; /* zero-terminated identifier */
111         char name[XSEG_NAMESIZE];  /* zero-terminated identifier */
112 };
113
114 struct xseg_port {
115         xptr free_queue;
116         xptr request_queue;
117         xptr reply_queue;
118         uint64_t owner;
119         volatile uint64_t waitcue;
120         uint64_t peer_type;
121         uint32_t portno;
122 };
123
124 struct xseg_request;
125
126 struct xseg_task {
127         uint64_t epoch;
128         struct xseg_request *req;
129         xqindex *deps;
130         xqindex nr_deps;
131         xqindex __alloced_deps;
132 };
133
134 /* OPS */
135 #define X_PING      0
136 #define X_READ      1
137 #define X_WRITE     2
138 #define X_SYNC      3
139 #define X_TRUNCATE  4
140 #define X_DELETE    5
141 #define X_ACQUIRE   6
142 #define X_RELEASE   7
143 #define X_COPY      8
144 #define X_CLONE     9
145 #define X_COMMIT   10
146 #define X_INFO     11
147 #define X_MAPR     12
148 #define X_MAPW     13
149
150 /* FLAGS */
151 #define XF_NOSYNC (1 << 0)
152 #define XF_FLUSH  (1 << 1)
153 #define XF_FUA    (1 << 2)
154
155 /* STATES */
156 #define XS_SERVED       (1 << 0)
157 #define XS_FAILED       (1 << 1)
158
159 #define XS_ACCEPTED     (1 << 2)
160 #define XS_PENDING      (2 << 2)
161 #define XS_SERVING      (3 << 2)
162 #define XS_CONCLUDED    (3 << 2)
163
164 struct xseg_request {
165         xserial serial;
166         uint64_t offset;
167         uint64_t size; /* FIXME: why are there both size and datalen fields? */
168                 /* FIXME: why does filed use ->datalen instead of ->size? */
169         uint64_t serviced;
170         xptr data;
171         uint64_t datalen;
172         xptr target;
173         uint32_t targetlen;
174         uint32_t op;
175         uint32_t state;
176         uint32_t flags;
177         uint32_t portno;
178         /* pad */
179         xptr buffer;
180         uint64_t bufferlen;
181         xqindex task;
182         uint64_t priv;
183         struct timeval timestamp;
184         uint64_t elapsed;
185 };
186
187 struct xseg_shared {
188         uint64_t flags;
189         char (*peer_types)[XSEG_TNAMESIZE]; /* alignment? */
190         uint32_t nr_peer_types;
191 };
192
193 struct xseg_private {
194         struct xseg_type segment_type;
195         struct xseg_peer peer_type;
196         struct xseg_peer **peer_types;
197         uint32_t max_peer_types;
198         void (*wakeup)(struct xseg *xseg, uint32_t portno);
199 };
200
201 struct xseg_counters {
202         uint64_t avg_req_lat;
203         uint64_t req_cnt;
204 };
205
206 struct xseg {
207         uint64_t version;
208         uint64_t segment_size;
209         struct xseg *segment;
210         struct xheap *heap;
211         struct xobject_h *object_handlers;
212
213         struct xobject_h *request_h;
214         struct xobject_h *port_h;
215         xptr *ports;
216
217         struct xseg_shared *shared;
218         struct xseg_private *priv;
219         uint32_t max_peer_types;
220         struct xseg_config config;
221         struct xseg_counters counters;
222 };
223
224 #define XSEG_F_LOCK 0x1
225
226 /* ================= XSEG REQUEST INTERFACE ================================= */
227 /*                     ___________________                         _________  */
228 /*                    /                   \                       /         \ */
229                 int    xseg_initialize      ( void                            );
230
231                 int    xseg_finalize        ( void                            );
232
233                 int    xseg_parse_spec      ( char                * spec,
234                                               struct xseg_config  * config    );
235
236    struct xseg_port *  xseg_bind_port       ( struct xseg         * xseg,
237                                               uint32_t              portno    );
238
239     static uint32_t    xseg_portno          ( struct xseg         * xseg,
240                                               struct xseg_port    * port      );
241 /*                    \___________________/                       \_________/ */
242 /*                     ___________________                         _________  */
243 /*                    /                   \                       /         \ */
244                 int    xseg_register_type   ( struct xseg_type    * type      );
245                 int    xseg_unregister_type ( const char          * name      );
246
247                 int    xseg_register_peer   ( struct xseg_peer    * peer      );
248                 int    xseg_unregister_peer ( const char          * name      );
249
250                void    xseg_report_peer_types( void );
251
252             int64_t    xseg_enable_driver   ( struct xseg         * xseg,
253                                               const char          * name      );
254                 int    xseg_disable_driver  ( struct xseg         * xseg,
255                                               const char          * name      );
256 /*                    \___________________/                       \_________/ */
257 /*                     ___________________                         _________  */
258 /*                    /                   \                       /         \ */
259                 int    xseg_create          ( struct xseg_config  * cfg       );
260
261                void    xseg_destroy         ( struct xseg         * xseg      );
262 /*                    \___________________/                       \_________/ */
263 /*                     ___________________                         _________  */
264 /*                    /                   \                       /         \ */
265         struct xseg *  xseg_join            ( char                * segtype,
266                                               char                * segname,
267                                               char                * peertype,
268                                               void               (* wakeup    )
269                                              (struct xseg         * xseg,
270                                               uint32_t              portno   ));
271
272                void    xseg_leave           ( struct xseg         * xseg      );
273 /*                    \___________________/                       \_________/ */
274 /*                     ___________________                         _________  */
275 /*                    /                   \                       /         \ */
276                 int    xseg_alloc_requests  ( struct xseg         * xseg,
277                                               uint32_t              portno,
278                                               uint32_t              nr        );
279
280                 int    xseg_free_requests   ( struct xseg         * xseg,
281                                               uint32_t              portno,
282                                               int                   nr        );
283
284 struct xseg_request *  xseg_get_request     ( struct xseg         * xseg,
285                                               uint32_t              portno    );
286
287                 int    xseg_put_request     ( struct xseg         * xseg,
288                                               uint32_t              portno,
289                                               struct xseg_request * xreq      );
290
291                 int    xseg_prep_request    ( struct xseg         * xseg,
292                                               struct xseg_request * xreq,
293                                               uint32_t              targetlen,
294                                               uint64_t              datalen  );
295 /*                    \___________________/                       \_________/ */
296 /*                     ___________________                         _________  */
297 /*                    /                   \                       /         \ */
298             xserial    xseg_submit          ( struct xseg         * xseg,
299                                               uint32_t              portno,
300                                               struct xseg_request * xreq      );
301
302 struct xseg_request *  xseg_receive         ( struct xseg         * xseg,
303                                               uint32_t              portno    );
304 /*                    \___________________/                       \_________/ */
305 /*                     ___________________                         _________  */
306 /*                    /                   \                       /         \ */
307
308 struct xseg_request *  xseg_accept          ( struct xseg         * xseg,
309                                               uint32_t              portno    );
310
311             xserial    xseg_respond         ( struct xseg         * xseg,
312                                               uint32_t              portno,
313                                               struct xseg_request * xreq      );
314 /*                    \___________________/                       \_________/ */
315 /*                     ___________________                         _________  */
316 /*                    /                   \                       /         \ */
317                 int    xseg_prepare_wait    ( struct xseg         * xseg,
318                                               uint32_t              portno    );
319
320                 int    xseg_cancel_wait     ( struct xseg         * xseg,
321                                               uint32_t              portno    );
322
323                 int    xseg_wait_signal     ( struct xseg         * xseg,
324                                               uint32_t              utimeout  );
325
326                 int    xseg_signal          ( struct xseg         * xseg,
327                                               uint32_t              portno    );
328 /*                    \___________________/                       \_________/ */
329
330
331
332 /*                                                                            */
333 /* ================= XSEG REQUEST INTERFACE ================================= */
334
335 struct xseg_port* xseg_get_port(struct xseg *xseg, uint32_t portno);
336
337 static inline uint32_t xseg_portno(struct xseg *xseg, struct xseg_port *port)
338 {
339         return port->portno;
340 }
341
342 static inline char* xseg_get_target(struct xseg* xseg, struct xseg_request *req)
343 {
344         return (char *) XPTR_TAKE(req->target, xseg->segment);
345 }
346
347 static inline char* xseg_get_data(struct xseg* xseg, struct xseg_request *req)
348 {
349         return (char *) XPTR_TAKE(req->data, xseg->segment);
350 }
351
352 #define xseg_get_queue(__xseg, __port, queue) \
353         ((struct xq *) XPTR_TAKE(__port->queue, __xseg->segment))
354
355 #endif