diff options
Diffstat (limited to '')
-rw-r--r-- | src/msg/xio/XioPool.h | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/msg/xio/XioPool.h b/src/msg/xio/XioPool.h new file mode 100644 index 00000000..07fa7311 --- /dev/null +++ b/src/msg/xio/XioPool.h @@ -0,0 +1,218 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2014 CohortFS, LLC + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ +#ifndef XIO_POOL_H +#define XIO_POOL_H + +#include <atomic> +#include <vector> +#include <cstdlib> +#include <cstring> +#include <cstdint> + +extern "C" { +#include "libxio.h" +} + +#include "common/likely.h" + +static inline int xpool_alloc(struct xio_mempool *pool, uint64_t size, + struct xio_reg_mem* mp); +static inline void xpool_free(uint64_t size, struct xio_reg_mem* mp); + +class XioPool +{ +private: + struct xio_mempool *handle; + +public: + static bool trace_mempool; + static bool trace_msgcnt; + static const int MB = 8; + + struct xio_piece { + struct xio_reg_mem mp[1]; + struct xio_piece *next; + int s; + char payload[MB]; + } *first; + + explicit XioPool(struct xio_mempool *_handle) : + handle(_handle), first(0) + { + } + ~XioPool() + { + struct xio_piece *p; + while ((p = first)) { + first = p->next; + if (unlikely(trace_mempool)) { + memset(p->payload, 0xcf, p->s); // guard bytes + } + xpool_free(sizeof(struct xio_piece)+(p->s)-MB, p->mp); + } + } + void *alloc(size_t _s) + { + void *r; + struct xio_reg_mem mp[1]; + struct xio_piece *x; + int e = xpool_alloc(handle, (sizeof(struct xio_piece)-MB) + _s, mp); + if (e) { + r = 0; + } else { + x = reinterpret_cast<struct xio_piece *>(mp->addr); + *x->mp = *mp; + x->next = first; + x->s = _s; + first = x; + r = x->payload; + } + return r; + } +}; + +class XioPoolStats { +private: + enum pool_sizes { + SLAB_64 = 0, + SLAB_256, + SLAB_1024, + SLAB_PAGE, + SLAB_MAX, + SLAB_OVERFLOW, + NUM_SLABS, + }; + + std::atomic<unsigned> ctr_set[NUM_SLABS] = {}; + std::atomic<unsigned> msg_cnt = { 0 }; // send msgs + std::atomic<unsigned> hook_cnt = { 0 }; // recv msgs + +public: + void dump(const char* tag, uint64_t serial); + + void inc(uint64_t size) { + if (size <= 64) { + (ctr_set[SLAB_64])++; + return; + } + if (size <= 256) { + (ctr_set[SLAB_256])++; + return; + } + if (size <= 1024) { + (ctr_set[SLAB_1024])++; + return; + } + if (size <= 8192) { + (ctr_set[SLAB_PAGE])++; + return; + } + (ctr_set[SLAB_MAX])++; + } + + void dec(uint64_t size) { + if (size <= 64) { + (ctr_set[SLAB_64])--; + return; + } + if (size <= 256) { + (ctr_set[SLAB_256])--; + return; + } + if (size <= 1024) { + (ctr_set[SLAB_1024])--; + return; + } + if (size <= 8192) { + (ctr_set[SLAB_PAGE])--; + return; + } + (ctr_set[SLAB_MAX])--; + } + + void inc_overflow() { ctr_set[SLAB_OVERFLOW]++; } + void dec_overflow() { ctr_set[SLAB_OVERFLOW]--; } + + void inc_msgcnt() { + if (unlikely(XioPool::trace_msgcnt)) { + msg_cnt++; + } + } + + void dec_msgcnt() { + if (unlikely(XioPool::trace_msgcnt)) { + msg_cnt--; + } + } + + void inc_hookcnt() { + if (unlikely(XioPool::trace_msgcnt)) { + hook_cnt++; + } + } + + void dec_hookcnt() { + if (unlikely(XioPool::trace_msgcnt)) { + hook_cnt--; + } + } +}; + +extern XioPoolStats xp_stats; + +static inline int xpool_alloc(struct xio_mempool *pool, uint64_t size, + struct xio_reg_mem* mp) +{ + // try to allocate from the xio pool + int r = xio_mempool_alloc(pool, size, mp); + if (r == 0) { + if (unlikely(XioPool::trace_mempool)) + xp_stats += size; + return 0; + } + // fall back to malloc on errors + mp->addr = malloc(size); + ceph_assert(mp->addr); + mp->length = 0; + if (unlikely(XioPool::trace_mempool)) + xp_stats.inc_overflow(); + return 0; +} + +static inline void xpool_free(uint64_t size, struct xio_reg_mem* mp) +{ + if (mp->length) { + if (unlikely(XioPool::trace_mempool)) + xp_stats -= size; + xio_mempool_free(mp); + } else { // from malloc + if (unlikely(XioPool::trace_mempool)) + xp_stats.dec_overflow(); + free(mp->addr); + } +} + +#define xpool_inc_msgcnt() \ + do { xp_stats.inc_msgcnt(); } while (0) + +#define xpool_dec_msgcnt() \ + do { xp_stats.dec_msgcnt(); } while (0) + +#define xpool_inc_hookcnt() \ + do { xp_stats.inc_hookcnt(); } while (0) + +#define xpool_dec_hookcnt() \ + do { xp_stats.dec_hookcnt(); } while (0) + +#endif /* XIO_POOL_H */ |