xseg.h 17 KB
Newer Older
Filippos Giannakos's avatar
Filippos Giannakos committed
1
/*
Filippos Giannakos's avatar
Filippos Giannakos committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15
Copyright (C) 2010-2014 GRNET S.A.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
Filippos Giannakos's avatar
Filippos Giannakos committed
16 17
 */

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
#ifndef _XSEG_H
#define _XSEG_H

#ifndef XSEG_PAGE_SHIFT
#define XSEG_PAGE_SHIFT 12
#endif

#define XSEG_BASE (0x37fd0UL << XSEG_PAGE_SHIFT)
#define XSEG_BASE_AS_PTR ((void *)XSEG_BASE)
#define XSEG_BASE_AS_BUF ((char *)XSEG_BASE)
#define XSEG_OFFSET(base, ptr) ((unsigned long)(ptr) - (unsigned long)(base))
#define XSEG_PTR_CONVERT(ptr, src, dst) ((void *)((unsigned long)(dst) + XSEG_OFFSET(src, ptr)))
#define XSEG_TAKE_PTR(ptr, base) XSEG_PTR_CONVERT(ptr, XSEG_BASE, base)
#define XSEG_MAKE_PTR(ptr, base) XSEG_PTR_CONVERT(ptr, base, XSEG_BASE)

33 34
#include <stdint.h>
#include <sys/time.h>
35
#include <xseg/version.h>
36
#include <xseg/util.h>
37
#include <xseg/xlock.h>
38 39 40 41
#include <xseg/xq.h>
#include <xseg/xobj.h>
#include <xseg/xhash.h>
#include <xseg/xpool.h>
42 43

typedef uint64_t xserial;
44
typedef uint32_t xport;
45

46
#define NoSerial ((xserial)-1)
47
#define NoPort ((xport) -1)
48
#define NoOwner ((uint64_t)-1)
49

50
#ifndef XSEG_DEF_REQS
51
#define XSEG_DEF_REQS 256
52 53
#endif

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#ifndef XSEG_DEF_MAX_ALLOCATED_REQS
#define XSEG_DEF_MAX_ALLOCATED_REQS 1024
#endif

/* hard limit on max allocated requests per port */
//FIXME make this a dynamicly calculated value based
//on heap_size and request_h->size
#ifndef	XSEG_MAX_ALLOCATED_REQS
#define XSEG_MAX_ALLOCATED_REQS 10000
#endif

#if XSEG_DEF_MAX_ALLOCATED_REQS > XSEG_MAX_ALLOCATED_REQS
#error "XSEG_DEF_MAX_ALLOCATED_REQS should be less than XSEG_MAX_ALLOCATED_REQS"
#endif

#if XSEG_DEF_REQS > XSEG_MAX_ALLOCATED_REQS
#error	"XSEG_DEF_REQS should me less than XSEG_MAX_ALLOCATED_REQS"
#endif

73 74 75 76
#ifndef MAX_PATH_LEN
#define MAX_PATH_LEN 32
#endif

77 78 79
#define XSEG_NAMESIZE 256
#define XSEG_TNAMESIZE 32

80
/* Peers and Segments
81
 *
82 83 84
 *  Segments are memory segments shared among peers.
 *  Peers are local execution contexes that share a segment.
 *
85
 *  xseg_type and xseg_peer
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
 *
 *  A peer needs an xseg_type in order to
 *  create or access a certain segment type,
 *  and it needs an xseg_peer in order to
 *  communicate with a certain type of peer.
 *  Both segment and peer types are identified by name strings.
 *
 *  Note that each peer (that is, context) type will need
 *  different code to access the same type of segment or peer.
 *  Therefore each peer must have its own "customized" version
 *  of the xseg library.
 *
 *  This is accomplished by mechanisms for registering both
 *  xseg_type's and xseg_peer's. This can be done at both at build time
 *  and at runtime, through a plugin-loading mechanism (where applicable).
 *  The plugin namespace serves both segment and peer type namespace,
 *  so if a segment type has the same name with a peer type,
 *  they must be provided by the same plugin.
 *
 *  Note also that peers of different types may share the same segment.
 *  Therefore each peer must know the type of each peer it needs to
 *  communicate with, and have a driver for it.
 *
*/

111
struct xseg;
112 113
struct xseg_port;

114 115 116 117
#define XSEG_MAGIC	(0xcafe0000)
#define MAGIC_OBJH 	(XSEG_MAGIC | 1)
#define MAGIC_REQ 	(XSEG_MAGIC | 2)
#define MAGIC_PORT 	(XSEG_MAGIC | 3)
118

119 120 121 122
struct xseg_operations {
	void  (*mfree)(void *mem);
	long  (*allocate)(const char *name, uint64_t size);
	long  (*deallocate)(const char *name);
123
	void *(*map)(const char *name, uint64_t size, struct xseg *seg);
124 125 126 127 128 129 130 131
	void  (*unmap)(void *xseg, uint64_t size);
};

struct xseg_type {
	struct xseg_operations ops;
	char name[XSEG_TNAMESIZE];
};

132

133
struct xseg_peer_operations {
134 135 136 137 138 139
	int   (*init_signal_desc)(struct xseg *xseg, void *sd);
	void  (*quit_signal_desc)(struct xseg *xseg, void *sd);
	void *(*alloc_data)(struct xseg *xseg);
	void  (*free_data)(struct xseg *xseg, void *data);
	void *(*alloc_signal_desc)(struct xseg *xseg, void *data);
	void  (*free_signal_desc)(struct xseg *xseg, void *data, void *sd);
140 141
	int   (*local_signal_init)(struct xseg *xseg, xport portno);
	void  (*local_signal_quit)(struct xseg *xseg, xport portno);
142 143
	int   (*remote_signal_init)(void);
	void  (*remote_signal_quit)(void);
144 145 146 147
	int   (*signal_join)(struct xseg *xseg);
	int   (*signal_leave)(struct xseg *xseg);
	int   (*prepare_wait)(struct xseg *xseg, uint32_t portno);
	int   (*cancel_wait)(struct xseg *xseg, uint32_t portno);
Filippos Giannakos's avatar
Filippos Giannakos committed
148
	int   (*wait_signal)(struct xseg *xseg, void *sd, uint32_t usec_timeout);
149
	int   (*signal)(struct xseg *xseg, uint32_t portno);
150 151 152 153 154 155 156 157 158 159 160
	void *(*malloc)(uint64_t size);
	void *(*realloc)(void *mem, uint64_t size);
	void  (*mfree)(void *mem);
};

struct xseg_peer {
	struct xseg_peer_operations peer_ops;
	char name[XSEG_TNAMESIZE];
};

struct xseg_config {
161
	uint64_t heap_size;	/* heap size in MB */
162
	uint32_t nr_ports;
163
	uint32_t dynports;
164 165 166 167 168 169
	uint32_t page_shift;	/* the alignment unit */
	char type[XSEG_TNAMESIZE]; /* zero-terminated identifier */
	char name[XSEG_NAMESIZE];  /* zero-terminated identifier */
};

struct xseg_port {
170 171 172
	struct xlock fq_lock;
	struct xlock rq_lock;
	struct xlock pq_lock;
173 174 175
	xptr free_queue;
	xptr request_queue;
	xptr reply_queue;
gtsouk's avatar
gtsouk committed
176
	uint64_t owner;
177
	uint64_t peer_type;
Filippos Giannakos's avatar
Filippos Giannakos committed
178
	uint32_t portno;
179 180 181
	uint64_t max_alloc_reqs;
	uint64_t alloc_reqs;
	struct xlock port_lock;
182
	xptr signal_desc;
183
	uint32_t flags;
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
};

struct xseg_request;

struct xseg_task {
	uint64_t epoch;
	struct xseg_request *req;
	xqindex *deps;
	xqindex nr_deps;
	xqindex __alloced_deps;
};

/* OPS */
#define X_PING      0
#define X_READ      1
#define X_WRITE     2
#define X_SYNC      3
#define X_TRUNCATE  4
#define X_DELETE    5
#define X_ACQUIRE   6
#define X_RELEASE   7
#define X_COPY      8
#define X_CLONE     9
#define X_COMMIT   10
208
#define X_INFO     11
209 210
#define X_MAPR     12
#define X_MAPW     13
Giannakos Filippos's avatar
Giannakos Filippos committed
211 212
#define X_OPEN     14
#define X_CLOSE    15
Filippos Giannakos's avatar
Filippos Giannakos committed
213
#define	X_SNAPSHOT 16
214
#define X_HASH	   17
215
#define X_CREATE   18
216
#define X_RENAME   19
217
#define X_FLUSH    20
Filippos Giannakos's avatar
Filippos Giannakos committed
218
#define X_UPDATE   21
219

220 221 222 223 224
/* REQ FLAGS */
#define XF_NOSYNC    (1 << 0)
#define XF_FLUSH     (1 << 1)
#define XF_FUA       (1 << 2)
#define XF_FORCE     (1 << 3)
225
#define XF_ASSUMEV0  (1 << 4)
226 227 228 229 230

/* PORT FLAGS */

#define CAN_ACCEPT   (1 << 0)
#define CAN_RECEIVE  (1 << 1)
231 232

/* STATES */
gtsouk's avatar
gtsouk committed
233 234
#define XS_SERVED	(1 << 0)
#define XS_FAILED	(1 << 1)
235

gtsouk's avatar
gtsouk committed
236 237 238 239
#define XS_ACCEPTED	(1 << 2)
#define XS_PENDING	(2 << 2)
#define XS_SERVING	(3 << 2)
#define XS_CONCLUDED	(3 << 2)
240 241 242 243

struct xseg_request {
	xserial serial;
	uint64_t offset;
244
	uint64_t size;
245
	uint64_t serviced;
246
	uint64_t v0_size;
247
	xptr data;
248
	uint64_t datalen;
249
	xptr target;
250
	uint32_t targetlen;
251
	uint32_t op;
252
	volatile uint32_t state;
253
	uint32_t flags;
254
	xport src_portno;
255
	xport transit_portno;
256
	xport dst_portno;
257
	xport effective_dst_portno;
258 259
	struct xq path;
	xqindex path_bufs[MAX_PATH_LEN];
260
	/* pad */
261
	xptr buffer;
262
	uint64_t bufferlen;
263
	xqindex task;
gtsouk's avatar
gtsouk committed
264
	uint64_t priv;
265 266
	struct timeval timestamp;
	uint64_t elapsed;
267 268 269
};

struct xseg_shared {
gtsouk's avatar
gtsouk committed
270
	uint64_t flags;
gtsouk's avatar
gtsouk committed
271
	char (*peer_types)[XSEG_TNAMESIZE]; /* alignment? */
272
	xptr *peer_type_data;
273
	uint32_t nr_peer_types;
274
	struct xlock segment_lock;
275 276
};

277 278 279 280
struct xseg_private {
	struct xseg_type segment_type;
	struct xseg_peer peer_type;
	struct xseg_peer **peer_types;
281
	void **peer_type_data;
282
	uint32_t max_peer_types;
283
	void (*wakeup)(uint32_t portno);
284
	xhash_t *req_data;
285
	struct xlock reqdatalock;
286 287
};

288 289 290 291 292
struct xseg_counters {
	uint64_t avg_req_lat;
	uint64_t req_cnt;
};

293 294
struct xseg {
	uint64_t version;
295 296
	uint64_t segment_size;
	struct xseg *segment;
297 298
	struct xheap *heap;
	struct xobject_h *object_handlers;
299

300 301 302
	struct xobject_h *request_h;
	struct xobject_h *port_h;
	xptr *ports;
303
	xport *path_next, *dst_gw;
304

305
	struct xseg_shared *shared;
306
	struct xseg_private *priv;
307
	uint32_t max_peer_types;
308
	struct xseg_config config;
309
	struct xseg_counters counters;
310 311 312 313 314 315 316
};

#define XSEG_F_LOCK 0x1

/* ================= XSEG REQUEST INTERFACE ================================= */
/*                     ___________________                         _________  */
/*                    /                   \                       /         \ */
317 318 319
                int    xseg_initialize      ( void                            );

                int    xseg_finalize        ( void                            );
320 321 322 323

                int    xseg_parse_spec      ( char                * spec,
                                              struct xseg_config  * config    );

324
   struct xseg_port *  xseg_bind_port       ( struct xseg         * xseg,
325 326
                                              uint32_t              portno,
					      void		  * sd        );
327 328 329 330 331 332 333 334 335 336 337 338 339 340

    static uint32_t    xseg_portno          ( struct xseg         * xseg,
                                              struct xseg_port    * port      );
/*                    \___________________/                       \_________/ */
/*                     ___________________                         _________  */
/*                    /                   \                       /         \ */
                int    xseg_register_type   ( struct xseg_type    * type      );
                int    xseg_unregister_type ( const char          * name      );

                int    xseg_register_peer   ( struct xseg_peer    * peer      );
                int    xseg_unregister_peer ( const char          * name      );

               void    xseg_report_peer_types( void );

341 342
            int64_t    xseg_enable_driver   ( struct xseg         * xseg,
                                              const char          * name      );
343
                int    xseg_disable_driver  ( struct xseg         * xseg,
344
                                              const char          * name      );
345 346 347 348 349 350 351 352 353
/*                    \___________________/                       \_________/ */
/*                     ___________________                         _________  */
/*                    /                   \                       /         \ */
                int    xseg_create          ( struct xseg_config  * cfg       );

               void    xseg_destroy         ( struct xseg         * xseg      );
/*                    \___________________/                       \_________/ */
/*                     ___________________                         _________  */
/*                    /                   \                       /         \ */
354 355 356
        struct xseg *  xseg_join            ( const char          * segtype,
                                              const char          * segname,
                                              const char          * peertype,
357
                                              void               (* wakeup    )
358
                                             (uint32_t              portno   ));
359 360 361 362 363 364 365 366 367 368 369 370 371 372

               void    xseg_leave           ( struct xseg         * xseg      );
/*                    \___________________/                       \_________/ */
/*                     ___________________                         _________  */
/*                    /                   \                       /         \ */
                int    xseg_alloc_requests  ( struct xseg         * xseg,
                                              uint32_t              portno,
                                              uint32_t              nr        );

                int    xseg_free_requests   ( struct xseg         * xseg,
                                              uint32_t              portno,
                                              int                   nr        );

struct xseg_request *  xseg_get_request     ( struct xseg         * xseg,
373
                                              xport                 src_portno,
374 375
					      xport                 dst_portno,
					      uint32_t              flags     );
376 377

                int    xseg_put_request     ( struct xseg         * xseg,
378 379
                                              struct xseg_request * xreq,
                                              xport                 portno    );
380

381 382
                int    xseg_prep_request    ( struct xseg	  * xseg,
					      struct xseg_request * xreq,
383 384
                                              uint32_t              targetlen,
                                              uint64_t              datalen  );
385 386 387
/*                    \___________________/                       \_________/ */
/*                     ___________________                         _________  */
/*                    /                   \                       /         \ */
388
              xport    xseg_submit          ( struct xseg         * xseg,
389
                                              struct xseg_request * xreq,
390 391
                                              xport                 portno,
					      uint32_t              flags     );
392 393

struct xseg_request *  xseg_receive         ( struct xseg         * xseg,
394
                                              xport                 portno,
Giannakos Filippos's avatar
Giannakos Filippos committed
395
					      uint32_t		    flags     );
396 397 398 399 400
/*                    \___________________/                       \_________/ */
/*                     ___________________                         _________  */
/*                    /                   \                       /         \ */

struct xseg_request *  xseg_accept          ( struct xseg         * xseg,
401
                                              xport                 portno,
Giannakos Filippos's avatar
Giannakos Filippos committed
402
					      uint32_t		    flags     );
403

404 405 406 407
              xport    xseg_respond         ( struct xseg         * xseg,
                                              struct xseg_request * xreq,
                                              xport                 portno,
                                              uint32_t              flags     );
408 409 410 411 412 413 414 415 416 417
/*                    \___________________/                       \_________/ */
/*                     ___________________                         _________  */
/*                    /                   \                       /         \ */
                int    xseg_prepare_wait    ( struct xseg         * xseg,
                                              uint32_t              portno    );

                int    xseg_cancel_wait     ( struct xseg         * xseg,
                                              uint32_t              portno    );

                int    xseg_wait_signal     ( struct xseg         * xseg,
Filippos Giannakos's avatar
Filippos Giannakos committed
418
					      void 		  * sd,
419 420 421 422 423
                                              uint32_t              utimeout  );

                int    xseg_signal          ( struct xseg         * xseg,
                                              uint32_t              portno    );
/*                    \___________________/                       \_________/ */
424 425 426



427 428 429
/*                                                                            */
/* ================= XSEG REQUEST INTERFACE ================================= */

430
struct xseg_port* xseg_get_port(struct xseg *xseg, uint32_t portno);
431

432 433 434

extern char* xseg_get_data_nonstatic(struct xseg* xseg, struct xseg_request *req);
extern char* xseg_get_target_nonstatic(struct xseg* xseg, struct xseg_request *req);
Filippos Giannakos's avatar
Filippos Giannakos committed
435
extern void* xseg_get_signal_desc_nonstatic(struct xseg *xseg, struct xseg_port *port);
436

437 438
static inline uint32_t xseg_portno(struct xseg *xseg, struct xseg_port *port)
{
Filippos Giannakos's avatar
Filippos Giannakos committed
439
	return port->portno;
440
}
Filippos Giannakos's avatar
Filippos Giannakos committed
441 442 443 444 445 446 447 448 449
static inline char* xseg_get_target(struct xseg* xseg, struct xseg_request *req)
{
	return (char *) XPTR_TAKE(req->target, xseg->segment);
}

static inline char* xseg_get_data(struct xseg* xseg, struct xseg_request *req)
{
	return (char *) XPTR_TAKE(req->data, xseg->segment);
}
450

451 452 453 454 455
static inline void * xseg_get_signal_desc(struct xseg *xseg, struct xseg_port *port)
{
	return (void *) XPTR_TAKE(port->signal_desc, xseg->segment);
}

456 457 458
struct xobject_h * xseg_get_objh(struct xseg *xseg, uint32_t magic, uint64_t size);
void xseg_put_objh(struct xseg *xseg, struct xobject_h *objh);

459 460
#define xseg_get_queue(__xseg, __port, __queue) \
	((struct xq *) XPTR_TAKE(__port->__queue, __xseg->segment))
461

462

463
int xseg_set_path_next(struct xseg *xseg, xport portno, xport next);
464

465 466
int xseg_set_req_data(struct xseg *xseg, struct xseg_request *xreq, void *data);
int xseg_get_req_data(struct xseg *xseg, struct xseg_request *xreq, void **data);
467

468 469
int xseg_init_local_signal(struct xseg *xseg, xport portno);
void xseg_quit_local_signal(struct xseg *xseg, xport portno);
470 471 472 473

int xseg_resize_request (struct xseg *xseg, struct xseg_request *req,
			uint32_t new_targetlen, uint64_t new_datalen);

474 475 476 477 478 479
int xseg_set_max_requests(struct xseg *xseg, xport portno, uint64_t nr_reqs);
uint64_t xseg_get_max_requests(struct xseg *xseg, xport portno);
uint64_t xseg_get_allocated_requests(struct xseg *xseg, xport portno);
int xseg_set_freequeue_size(struct xseg *xseg, xport portno, xqindex size,
				uint32_t flags);

480 481
xport xseg_forward(struct xseg *xseg, struct xseg_request *req, xport new_dst,
		xport portno, uint32_t flags);
482

483 484 485
struct xseg_port *xseg_bind_dynport(struct xseg *xseg);
int xseg_leave_dynport(struct xseg *xseg, struct xseg_port *port);
extern uint32_t xseg_portno_nonstatic(struct xseg *xseg, struct xseg_port *port);
486
#endif