1e8a1ed2f6d411e7b0bd6313ad339c3f63536234
[archipelago] / xseg / xseg / xseg.h
1 /*
2  * Copyright 2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *   2. Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials
14  *      provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * The views and conclusions contained in the software and
30  * documentation are those of the authors and should not be
31  * interpreted as representing official policies, either expressed
32  * or implied, of GRNET S.A.
33  */
34
35 #ifndef _XSEG_H
36 #define _XSEG_H
37
38 #ifndef XSEG_VERSION
39 #define XSEG_VERSION 2012022601
40 #endif
41
42 #ifndef XSEG_PAGE_SHIFT
43 #define XSEG_PAGE_SHIFT 12
44 #endif
45
46 #define XSEG_BASE (0x37fd0UL << XSEG_PAGE_SHIFT)
47 #define XSEG_BASE_AS_PTR ((void *)XSEG_BASE)
48 #define XSEG_BASE_AS_BUF ((char *)XSEG_BASE)
49 #define XSEG_OFFSET(base, ptr) ((unsigned long)(ptr) - (unsigned long)(base))
50 #define XSEG_PTR_CONVERT(ptr, src, dst) ((void *)((unsigned long)(dst) + XSEG_OFFSET(src, ptr)))
51 #define XSEG_TAKE_PTR(ptr, base) XSEG_PTR_CONVERT(ptr, XSEG_BASE, base)
52 #define XSEG_MAKE_PTR(ptr, base) XSEG_PTR_CONVERT(ptr, base, XSEG_BASE)
53
54 #include <sys/util.h>
55 #include <xtypes/xq.h>
56 #include <xtypes/xobj.h>
57 #include <xtypes/xhash.h>
58 #include <xtypes/xpool.h>
59
60 typedef uint64_t xserial;
61 typedef uint32_t xport;
62
63 #define NoSerial ((xserial)-1)
64 #define NoPort ((xport) -1)
65
66 #ifndef XSEG_DEF_REQS
67 #define XSEG_DEF_REQS 256
68 #endif
69
70 #ifndef XSEG_DEF_MAX_ALLOCATED_REQS
71 #define XSEG_DEF_MAX_ALLOCATED_REQS 1024
72 #endif
73
74 /* hard limit on max allocated requests per port */
75 //FIXME make this a dynamicly calculated value based
76 //on heap_size and request_h->size
77 #ifndef XSEG_MAX_ALLOCATED_REQS
78 #define XSEG_MAX_ALLOCATED_REQS 10000
79 #endif
80
81 #if XSEG_DEF_MAX_ALLOCATED_REQS > XSEG_MAX_ALLOCATED_REQS
82 #error "XSEG_DEF_MAX_ALLOCATED_REQS should be less than XSEG_MAX_ALLOCATED_REQS"
83 #endif
84
85 #if XSEG_DEF_REQS > XSEG_MAX_ALLOCATED_REQS
86 #error  "XSEG_DEF_REQS should me less than XSEG_MAX_ALLOCATED_REQS"
87 #endif
88
89 #ifndef MAX_PATH_LEN
90 #define MAX_PATH_LEN 32
91 #endif
92
93 #define XSEG_NAMESIZE 256
94 #define XSEG_TNAMESIZE 32
95
96 /* Peers and Segments
97  *
98  *  Segments are memory segments shared among peers.
99  *  Peers are local execution contexes that share a segment.
100  *
101  *  xseg_type and xseg_peer
102  *
103  *  A peer needs an xseg_type in order to
104  *  create or access a certain segment type,
105  *  and it needs an xseg_peer in order to
106  *  communicate with a certain type of peer.
107  *  Both segment and peer types are identified by name strings.
108  *
109  *  Note that each peer (that is, context) type will need
110  *  different code to access the same type of segment or peer.
111  *  Therefore each peer must have its own "customized" version
112  *  of the xseg library.
113  *
114  *  This is accomplished by mechanisms for registering both
115  *  xseg_type's and xseg_peer's. This can be done at both at build time
116  *  and at runtime, through a plugin-loading mechanism (where applicable).
117  *  The plugin namespace serves both segment and peer type namespace,
118  *  so if a segment type has the same name with a peer type,
119  *  they must be provided by the same plugin.
120  *
121  *  Note also that peers of different types may share the same segment.
122  *  Therefore each peer must know the type of each peer it needs to
123  *  communicate with, and have a driver for it.
124  *
125 */
126
127 struct xseg;
128 struct xseg_port;
129
130 #define XSEG_MAGIC      (0xcafe0000)
131 #define MAGIC_OBJH      (XSEG_MAGIC | 1)
132 #define MAGIC_REQ       (XSEG_MAGIC | 2)
133 #define MAGIC_PORT      (XSEG_MAGIC | 3)
134
135 struct xseg_operations {
136         void  (*mfree)(void *mem);
137         long  (*allocate)(const char *name, uint64_t size);
138         long  (*deallocate)(const char *name);
139         void *(*map)(const char *name, uint64_t size, struct xseg *seg);
140         void  (*unmap)(void *xseg, uint64_t size);
141 };
142
143 struct xseg_type {
144         struct xseg_operations ops;
145         char name[XSEG_TNAMESIZE];
146 };
147
148
149 struct xseg_peer_operations {
150         int   (*init_signal_desc)(struct xseg *xseg, void *sd);
151         void  (*quit_signal_desc)(struct xseg *xseg, void *sd);
152         void *(*alloc_data)(struct xseg *xseg);
153         void  (*free_data)(struct xseg *xseg, void *data);
154         void *(*alloc_signal_desc)(struct xseg *xseg, void *data);
155         void  (*free_signal_desc)(struct xseg *xseg, void *data, void *sd);
156         int   (*local_signal_init)(struct xseg *xseg, xport portno);
157         void  (*local_signal_quit)(struct xseg *xseg, xport portno);
158         int   (*remote_signal_init)(void);
159         void  (*remote_signal_quit)(void);
160         int   (*signal_join)(struct xseg *xseg);
161         int   (*signal_leave)(struct xseg *xseg);
162         int   (*prepare_wait)(struct xseg *xseg, uint32_t portno);
163         int   (*cancel_wait)(struct xseg *xseg, uint32_t portno);
164         int   (*wait_signal)(struct xseg *xseg, uint32_t usec_timeout);
165         int   (*signal)(struct xseg *xseg, uint32_t portno);
166         void *(*malloc)(uint64_t size);
167         void *(*realloc)(void *mem, uint64_t size);
168         void  (*mfree)(void *mem);
169 };
170
171 struct xseg_peer {
172         struct xseg_peer_operations peer_ops;
173         char name[XSEG_TNAMESIZE];
174 };
175
176 struct xseg_config {
177         uint64_t heap_size;     /* heap size in MB */
178         uint32_t nr_ports;
179         uint32_t page_shift;    /* the alignment unit */
180         char type[XSEG_TNAMESIZE]; /* zero-terminated identifier */
181         char name[XSEG_NAMESIZE];  /* zero-terminated identifier */
182 };
183
184 struct xseg_port {
185         struct xlock fq_lock;
186         struct xlock rq_lock;
187         struct xlock pq_lock;
188         xptr free_queue;
189         xptr request_queue;
190         xptr reply_queue;
191         uint64_t owner;
192         uint64_t peer_type;
193         uint32_t portno;
194         uint64_t max_alloc_reqs;
195         uint64_t alloc_reqs;
196         struct xlock port_lock;
197         xptr signal_desc;
198         uint32_t flags;
199 };
200
201 struct xseg_request;
202
203 struct xseg_task {
204         uint64_t epoch;
205         struct xseg_request *req;
206         xqindex *deps;
207         xqindex nr_deps;
208         xqindex __alloced_deps;
209 };
210
211 /* OPS */
212 #define X_PING      0
213 #define X_READ      1
214 #define X_WRITE     2
215 #define X_SYNC      3
216 #define X_TRUNCATE  4
217 #define X_DELETE    5
218 #define X_ACQUIRE   6
219 #define X_RELEASE   7
220 #define X_COPY      8
221 #define X_CLONE     9
222 #define X_COMMIT   10
223 #define X_INFO     11
224 #define X_MAPR     12
225 #define X_MAPW     13
226 #define X_OPEN     14
227 #define X_CLOSE    15
228 #define X_SNAPSHOT 16
229 #define X_HASH     17
230
231 /* REQ FLAGS */
232 #define XF_NOSYNC    (1 << 0)
233 #define XF_FLUSH     (1 << 1)
234 #define XF_FUA       (1 << 2)
235 #define XF_FORCE     (1 << 3)
236 #define XF_CONTADDR  (1 << 4)
237
238 /* PORT FLAGS */
239
240 #define CAN_ACCEPT   (1 << 0)
241 #define CAN_RECEIVE  (1 << 1)
242
243 /* STATES */
244 #define XS_SERVED       (1 << 0)
245 #define XS_FAILED       (1 << 1)
246
247 #define XS_ACCEPTED     (1 << 2)
248 #define XS_PENDING      (2 << 2)
249 #define XS_SERVING      (3 << 2)
250 #define XS_CONCLUDED    (3 << 2)
251
252 struct xseg_request {
253         xserial serial;
254         uint64_t offset;
255         uint64_t size; 
256         uint64_t serviced;
257         xptr data;
258         uint64_t datalen;
259         xptr target;
260         uint32_t targetlen;
261         uint32_t op;
262         volatile uint32_t state;
263         uint32_t flags;
264         xport src_portno;
265         xport transit_portno;
266         xport dst_portno;
267         xport effective_dst_portno;
268         struct xq path;
269         xqindex path_bufs[MAX_PATH_LEN];
270         /* pad */
271         xptr buffer;
272         uint64_t bufferlen;
273         xqindex task;
274         uint64_t priv;
275         struct timeval timestamp;
276         uint64_t elapsed;
277 };
278
279 struct xseg_shared {
280         uint64_t flags;
281         char (*peer_types)[XSEG_TNAMESIZE]; /* alignment? */
282         xptr *peer_type_data;
283         uint32_t nr_peer_types;
284 };
285
286 struct xseg_private {
287         struct xseg_type segment_type;
288         struct xseg_peer peer_type;
289         struct xseg_peer **peer_types;
290         void **peer_type_data;
291         uint32_t max_peer_types;
292         void (*wakeup)(uint32_t portno);
293         xhash_t *req_data;
294         struct xlock reqdatalock;
295 };
296
297 struct xseg_counters {
298         uint64_t avg_req_lat;
299         uint64_t req_cnt;
300 };
301
302 struct xseg {
303         uint64_t version;
304         uint64_t segment_size;
305         struct xseg *segment;
306         struct xheap *heap;
307         struct xobject_h *object_handlers;
308
309         struct xobject_h *request_h;
310         struct xobject_h *port_h;
311         xptr *ports;
312         xport *path_next, *dst_gw;
313
314         struct xseg_shared *shared;
315         struct xseg_private *priv;
316         uint32_t max_peer_types;
317         struct xseg_config config;
318         struct xseg_counters counters;
319 };
320
321 #define XSEG_F_LOCK 0x1
322
323 /* ================= XSEG REQUEST INTERFACE ================================= */
324 /*                     ___________________                         _________  */
325 /*                    /                   \                       /         \ */
326                 int    xseg_initialize      ( void                            );
327
328                 int    xseg_finalize        ( void                            );
329
330                 int    xseg_parse_spec      ( char                * spec,
331                                               struct xseg_config  * config    );
332
333    struct xseg_port *  xseg_bind_port       ( struct xseg         * xseg,
334                                               uint32_t              portno,
335                                               void                * sd        );
336
337     static uint32_t    xseg_portno          ( struct xseg         * xseg,
338                                               struct xseg_port    * port      );
339 /*                    \___________________/                       \_________/ */
340 /*                     ___________________                         _________  */
341 /*                    /                   \                       /         \ */
342                 int    xseg_register_type   ( struct xseg_type    * type      );
343                 int    xseg_unregister_type ( const char          * name      );
344
345                 int    xseg_register_peer   ( struct xseg_peer    * peer      );
346                 int    xseg_unregister_peer ( const char          * name      );
347
348                void    xseg_report_peer_types( void );
349
350             int64_t    xseg_enable_driver   ( struct xseg         * xseg,
351                                               const char          * name      );
352                 int    xseg_disable_driver  ( struct xseg         * xseg,
353                                               const char          * name      );
354 /*                    \___________________/                       \_________/ */
355 /*                     ___________________                         _________  */
356 /*                    /                   \                       /         \ */
357                 int    xseg_create          ( struct xseg_config  * cfg       );
358
359                void    xseg_destroy         ( struct xseg         * xseg      );
360 /*                    \___________________/                       \_________/ */
361 /*                     ___________________                         _________  */
362 /*                    /                   \                       /         \ */
363         struct xseg *  xseg_join            ( char                * segtype,
364                                               char                * segname,
365                                               char                * peertype,
366                                               void               (* wakeup    )
367                                              (uint32_t              portno   ));
368
369                void    xseg_leave           ( struct xseg         * xseg      );
370 /*                    \___________________/                       \_________/ */
371 /*                     ___________________                         _________  */
372 /*                    /                   \                       /         \ */
373                 int    xseg_alloc_requests  ( struct xseg         * xseg,
374                                               uint32_t              portno,
375                                               uint32_t              nr        );
376
377                 int    xseg_free_requests   ( struct xseg         * xseg,
378                                               uint32_t              portno,
379                                               int                   nr        );
380
381 struct xseg_request *  xseg_get_request     ( struct xseg         * xseg,
382                                               xport                 src_portno,
383                                               xport                 dst_portno,
384                                               uint32_t              flags     );
385
386                 int    xseg_put_request     ( struct xseg         * xseg,
387                                               struct xseg_request * xreq,
388                                               xport                 portno    );
389
390                 int    xseg_prep_request    ( struct xseg         * xseg,
391                                               struct xseg_request * xreq,
392                                               uint32_t              targetlen,
393                                               uint64_t              datalen  );
394 /*                    \___________________/                       \_________/ */
395 /*                     ___________________                         _________  */
396 /*                    /                   \                       /         \ */
397               xport    xseg_submit          ( struct xseg         * xseg,
398                                               struct xseg_request * xreq,      
399                                               xport                 portno,
400                                               uint32_t              flags     );
401
402 struct xseg_request *  xseg_receive         ( struct xseg         * xseg,
403                                               xport                 portno,    
404                                               uint32_t              flags     );
405 /*                    \___________________/                       \_________/ */
406 /*                     ___________________                         _________  */
407 /*                    /                   \                       /         \ */
408
409 struct xseg_request *  xseg_accept          ( struct xseg         * xseg,
410                                               xport                 portno,    
411                                               uint32_t              flags     );
412
413               xport    xseg_respond         ( struct xseg         * xseg,
414                                               struct xseg_request * xreq,
415                                               xport                 portno,
416                                               uint32_t              flags     );
417 /*                    \___________________/                       \_________/ */
418 /*                     ___________________                         _________  */
419 /*                    /                   \                       /         \ */
420                 int    xseg_prepare_wait    ( struct xseg         * xseg,
421                                               uint32_t              portno    );
422
423                 int    xseg_cancel_wait     ( struct xseg         * xseg,
424                                               uint32_t              portno    );
425
426                 int    xseg_wait_signal     ( struct xseg         * xseg,
427                                               uint32_t              utimeout  );
428
429                 int    xseg_signal          ( struct xseg         * xseg,
430                                               uint32_t              portno    );
431 /*                    \___________________/                       \_________/ */
432
433
434
435 /*                                                                            */
436 /* ================= XSEG REQUEST INTERFACE ================================= */
437
438 struct xseg_port* xseg_get_port(struct xseg *xseg, uint32_t portno);
439
440
441 extern char* xseg_get_data_nonstatic(struct xseg* xseg, struct xseg_request *req);
442 extern char* xseg_get_target_nonstatic(struct xseg* xseg, struct xseg_request *req);
443
444 static inline uint32_t xseg_portno(struct xseg *xseg, struct xseg_port *port)
445 {
446         return port->portno;
447 }
448 static inline char* xseg_get_target(struct xseg* xseg, struct xseg_request *req)
449 {
450         return (char *) XPTR_TAKE(req->target, xseg->segment);
451 }
452
453 static inline char* xseg_get_data(struct xseg* xseg, struct xseg_request *req)
454 {
455         return (char *) XPTR_TAKE(req->data, xseg->segment);
456 }
457
458 static inline void * xseg_get_signal_desc(struct xseg *xseg, struct xseg_port *port)
459 {
460         return (void *) XPTR_TAKE(port->signal_desc, xseg->segment);
461 }
462
463 struct xobject_h * xseg_get_objh(struct xseg *xseg, uint32_t magic, uint64_t size);
464 void xseg_put_objh(struct xseg *xseg, struct xobject_h *objh);
465
466 #define xseg_get_queue(__xseg, __port, __queue) \
467         ((struct xq *) XPTR_TAKE(__port->__queue, __xseg->segment))
468
469
470 int xseg_set_path_next(struct xseg *xseg, xport portno, xport next);
471
472 int xseg_set_req_data(struct xseg *xseg, struct xseg_request *xreq, void *data);
473 int xseg_get_req_data(struct xseg *xseg, struct xseg_request *xreq, void **data);
474
475 int xseg_init_local_signal(struct xseg *xseg, xport portno);
476 void xseg_quit_local_signal(struct xseg *xseg, xport portno);
477
478 int xseg_resize_request (struct xseg *xseg, struct xseg_request *req,
479                         uint32_t new_targetlen, uint64_t new_datalen);
480
481 int xseg_set_max_requests(struct xseg *xseg, xport portno, uint64_t nr_reqs);
482 uint64_t xseg_get_max_requests(struct xseg *xseg, xport portno);
483 uint64_t xseg_get_allocated_requests(struct xseg *xseg, xport portno);
484 int xseg_set_freequeue_size(struct xseg *xseg, xport portno, xqindex size,
485                                 uint32_t flags);
486
487 xport xseg_forward(struct xseg *xseg, struct xseg_request *req, xport new_dst,
488                 xport portno, uint32_t flags);
489
490 #endif