1*a9643ea8Slogwang /*- 2*a9643ea8Slogwang * BSD LICENSE 3*a9643ea8Slogwang * 4*a9643ea8Slogwang * Copyright(c) 2015 Intel Corporation. All rights reserved. 5*a9643ea8Slogwang * All rights reserved. 6*a9643ea8Slogwang * 7*a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without 8*a9643ea8Slogwang * modification, are permitted provided that the following conditions 9*a9643ea8Slogwang * are met: 10*a9643ea8Slogwang * 11*a9643ea8Slogwang * * Redistributions of source code must retain the above copyright 12*a9643ea8Slogwang * notice, this list of conditions and the following disclaimer. 13*a9643ea8Slogwang * * Redistributions in binary form must reproduce the above copyright 14*a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in 15*a9643ea8Slogwang * the documentation and/or other materials provided with the 16*a9643ea8Slogwang * distribution. 17*a9643ea8Slogwang * * Neither the name of Intel Corporation nor the names of its 18*a9643ea8Slogwang * contributors may be used to endorse or promote products derived 19*a9643ea8Slogwang * from this software without specific prior written permission. 20*a9643ea8Slogwang * 21*a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*a9643ea8Slogwang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*a9643ea8Slogwang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24*a9643ea8Slogwang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25*a9643ea8Slogwang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26*a9643ea8Slogwang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27*a9643ea8Slogwang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28*a9643ea8Slogwang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29*a9643ea8Slogwang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30*a9643ea8Slogwang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31*a9643ea8Slogwang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32*a9643ea8Slogwang */ 33*a9643ea8Slogwang #ifndef LTHREAD_OBJCACHE_H_ 34*a9643ea8Slogwang #define LTHREAD_OBJCACHE_H_ 35*a9643ea8Slogwang 36*a9643ea8Slogwang #include <string.h> 37*a9643ea8Slogwang 38*a9643ea8Slogwang #include <rte_per_lcore.h> 39*a9643ea8Slogwang #include <rte_malloc.h> 40*a9643ea8Slogwang #include <rte_memory.h> 41*a9643ea8Slogwang 42*a9643ea8Slogwang #include "lthread_int.h" 43*a9643ea8Slogwang #include "lthread_diag.h" 44*a9643ea8Slogwang #include "lthread_queue.h" 45*a9643ea8Slogwang 46*a9643ea8Slogwang 47*a9643ea8Slogwang RTE_DECLARE_PER_LCORE(struct lthread_sched *, this_sched); 48*a9643ea8Slogwang 49*a9643ea8Slogwang struct lthread_objcache { 50*a9643ea8Slogwang struct lthread_queue *q; 51*a9643ea8Slogwang size_t obj_size; 52*a9643ea8Slogwang int prealloc_size; 53*a9643ea8Slogwang char name[LT_MAX_NAME_SIZE]; 54*a9643ea8Slogwang 55*a9643ea8Slogwang DIAG_COUNT_DEFINE(rd); 56*a9643ea8Slogwang DIAG_COUNT_DEFINE(wr); 57*a9643ea8Slogwang DIAG_COUNT_DEFINE(prealloc); 58*a9643ea8Slogwang DIAG_COUNT_DEFINE(capacity); 59*a9643ea8Slogwang DIAG_COUNT_DEFINE(available); 60*a9643ea8Slogwang }; 61*a9643ea8Slogwang 62*a9643ea8Slogwang /* 63*a9643ea8Slogwang * Create a cache 64*a9643ea8Slogwang */ 65*a9643ea8Slogwang static inline struct 66*a9643ea8Slogwang lthread_objcache *_lthread_objcache_create(const char *name, 67*a9643ea8Slogwang size_t obj_size, 68*a9643ea8Slogwang int prealloc_size) 69*a9643ea8Slogwang { 70*a9643ea8Slogwang struct lthread_objcache *c = 71*a9643ea8Slogwang rte_malloc_socket(NULL, sizeof(struct lthread_objcache), 72*a9643ea8Slogwang RTE_CACHE_LINE_SIZE, 73*a9643ea8Slogwang rte_socket_id()); 74*a9643ea8Slogwang if (c == NULL) 75*a9643ea8Slogwang return NULL; 76*a9643ea8Slogwang 77*a9643ea8Slogwang c->q = _lthread_queue_create("cache queue"); 78*a9643ea8Slogwang if (c->q == NULL) { 79*a9643ea8Slogwang rte_free(c); 80*a9643ea8Slogwang return NULL; 81*a9643ea8Slogwang } 82*a9643ea8Slogwang c->obj_size = obj_size; 83*a9643ea8Slogwang c->prealloc_size = prealloc_size; 84*a9643ea8Slogwang 85*a9643ea8Slogwang if (name != NULL) 86*a9643ea8Slogwang strncpy(c->name, name, LT_MAX_NAME_SIZE); 87*a9643ea8Slogwang c->name[sizeof(c->name)-1] = 0; 88*a9643ea8Slogwang 89*a9643ea8Slogwang DIAG_COUNT_INIT(c, rd); 90*a9643ea8Slogwang DIAG_COUNT_INIT(c, wr); 91*a9643ea8Slogwang DIAG_COUNT_INIT(c, prealloc); 92*a9643ea8Slogwang DIAG_COUNT_INIT(c, capacity); 93*a9643ea8Slogwang DIAG_COUNT_INIT(c, available); 94*a9643ea8Slogwang return c; 95*a9643ea8Slogwang } 96*a9643ea8Slogwang 97*a9643ea8Slogwang /* 98*a9643ea8Slogwang * Destroy an objcache 99*a9643ea8Slogwang */ 100*a9643ea8Slogwang static inline int 101*a9643ea8Slogwang _lthread_objcache_destroy(struct lthread_objcache *c) 102*a9643ea8Slogwang { 103*a9643ea8Slogwang if (_lthread_queue_destroy(c->q) == 0) { 104*a9643ea8Slogwang rte_free(c); 105*a9643ea8Slogwang return 0; 106*a9643ea8Slogwang } 107*a9643ea8Slogwang return -1; 108*a9643ea8Slogwang } 109*a9643ea8Slogwang 110*a9643ea8Slogwang /* 111*a9643ea8Slogwang * Allocate an object from an object cache 112*a9643ea8Slogwang */ 113*a9643ea8Slogwang static inline void * 114*a9643ea8Slogwang _lthread_objcache_alloc(struct lthread_objcache *c) 115*a9643ea8Slogwang { 116*a9643ea8Slogwang int i; 117*a9643ea8Slogwang void *data; 118*a9643ea8Slogwang struct lthread_queue *q = c->q; 119*a9643ea8Slogwang size_t obj_size = c->obj_size; 120*a9643ea8Slogwang int prealloc_size = c->prealloc_size; 121*a9643ea8Slogwang 122*a9643ea8Slogwang data = _lthread_queue_remove(q); 123*a9643ea8Slogwang 124*a9643ea8Slogwang if (data == NULL) { 125*a9643ea8Slogwang DIAG_COUNT_INC(c, prealloc); 126*a9643ea8Slogwang for (i = 0; i < prealloc_size; i++) { 127*a9643ea8Slogwang data = 128*a9643ea8Slogwang rte_zmalloc_socket(NULL, obj_size, 129*a9643ea8Slogwang RTE_CACHE_LINE_SIZE, 130*a9643ea8Slogwang rte_socket_id()); 131*a9643ea8Slogwang if (data == NULL) 132*a9643ea8Slogwang return NULL; 133*a9643ea8Slogwang 134*a9643ea8Slogwang DIAG_COUNT_INC(c, available); 135*a9643ea8Slogwang DIAG_COUNT_INC(c, capacity); 136*a9643ea8Slogwang _lthread_queue_insert_mp(q, data); 137*a9643ea8Slogwang } 138*a9643ea8Slogwang data = _lthread_queue_remove(q); 139*a9643ea8Slogwang } 140*a9643ea8Slogwang DIAG_COUNT_INC(c, rd); 141*a9643ea8Slogwang DIAG_COUNT_DEC(c, available); 142*a9643ea8Slogwang return data; 143*a9643ea8Slogwang } 144*a9643ea8Slogwang 145*a9643ea8Slogwang /* 146*a9643ea8Slogwang * free an object to a cache 147*a9643ea8Slogwang */ 148*a9643ea8Slogwang static inline void 149*a9643ea8Slogwang _lthread_objcache_free(struct lthread_objcache *c, void *obj) 150*a9643ea8Slogwang { 151*a9643ea8Slogwang DIAG_COUNT_INC(c, wr); 152*a9643ea8Slogwang DIAG_COUNT_INC(c, available); 153*a9643ea8Slogwang _lthread_queue_insert_mp(c->q, obj); 154*a9643ea8Slogwang } 155*a9643ea8Slogwang 156*a9643ea8Slogwang 157*a9643ea8Slogwang 158*a9643ea8Slogwang #endif /* LTHREAD_OBJCACHE_H_ */ 159