xcache: Explicitly set flag to use rm tables
[archipelago] / xseg / xtypes / xobj.c
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 #include <xtypes/xobj.h>
36 #include <xtypes/xhash.h>
37 #include <xtypes/domain.h>
38
39 int xobj_handler_init(struct xobject_h *obj_h, void *container,
40                 uint32_t magic, uint64_t size, struct xheap *heap)
41 {
42         //uint64_t bytes;
43         xhash_t *xhash;
44         obj_h->magic = magic;
45         /* minimum object size */
46         if (size < sizeof(struct xobject))
47                 obj_h->obj_size = sizeof(struct xobject);
48         else
49                 obj_h->obj_size = size;
50
51         //TODO convert this to xset
52         /* request space of an xhash of sizeshift 3 */
53         xhash = (xhash_t *) xheap_allocate(heap, xhash_get_alloc_size(3));
54         if (!xhash)
55                 return -1;
56
57         //FIXME
58         /* but initialize an xhash with sizeshift based on
59          * allocated space. should be at least the above sizeshift
60          */
61         //bytes = xheap_get_chunk_size(xhash);
62
63         xhash_init(xhash, 3, 0, INTEGER);
64         obj_h->allocated = XPTR_MAKE(xhash, container);
65         obj_h->list = 0;
66         obj_h->flags = 0;
67         obj_h->nr_free = 0;
68         obj_h->nr_allocated = 0;
69         obj_h->allocated_space = 0;
70         obj_h->heap = XPTR_MAKE(heap, container);
71         XPTRSET(&obj_h->container, container);
72         xlock_release(&obj_h->lock);
73         return 0;
74
75 }
76
77 int xobj_alloc_obj(struct xobject_h * obj_h, uint64_t nr)
78 {
79         void *container = XPTR(&obj_h->container);
80         struct xheap *heap = XPTR_TAKE(obj_h->heap, container);
81         struct xobject *obj = NULL;
82
83         uint64_t used, bytes = nr * obj_h->obj_size;
84         xptr ptr, objptr;
85         xhash_t *allocated = XPTR_TAKE(obj_h->allocated, container);
86         int r;
87
88         void *mem = xheap_allocate(heap, bytes);
89         if (!mem)
90                 return -1;
91
92         bytes = xheap_get_chunk_size(mem);
93         used = 0;
94         while (used + obj_h->obj_size < bytes) {
95                 objptr = XPTR_MAKE(((unsigned long) mem) + used, container);
96                 obj = XPTR_TAKE(objptr, container);
97                 used += obj_h->obj_size;
98                 obj->magic = obj_h->magic;
99                 obj->size = obj_h->obj_size;
100                 obj->next = XPTR_MAKE(((unsigned long) mem) + used, container); //point to the next obj
101         }
102         if (!obj)
103                 goto err;
104
105         /* keep track of allocated objects.
106          * Since the whole allocated space is split up into objects,
107          * we can calculate allocated objects from the allocated heap
108          * space and object size.
109          */
110         ptr = XPTR_MAKE(mem, container);
111         r = xhash_insert(allocated, ptr, ptr);
112         //ugly
113         if (r == -XHASH_ERESIZE) {
114                 xhashidx sizeshift = xhash_grow_size_shift(allocated);
115                 uint64_t size;
116                 xhash_t *new;
117                 size = xhash_get_alloc_size(sizeshift);
118                 new = xheap_allocate(heap, size);
119                 if (!new)
120                         goto err;
121                 xhash_resize(allocated, sizeshift, 0, new);
122                 xheap_free(allocated);
123                 allocated = new;
124                 obj_h->allocated = XPTR_MAKE(allocated, container);
125                 r = xhash_insert(allocated, ptr, ptr);
126         }
127         if (r < 0)
128                 goto err;
129
130         obj_h->allocated_space += bytes;
131         obj_h->nr_free += bytes/obj_h->obj_size;
132         obj_h->nr_allocated += bytes/obj_h->obj_size;
133         obj->next = obj_h->list;
134         obj_h->list = ptr;
135         return 0;
136
137 err:
138         xheap_free(mem);
139         return -1;
140
141 }
142 void xobj_put_obj(struct xobject_h * obj_h, void *ptr)
143 {
144         struct xobject *obj = (struct xobject *) ptr;
145         void *container = XPTR(&obj_h->container);
146         xptr list, objptr = XPTR_MAKE(obj, container);
147
148         xlock_acquire(&obj_h->lock, 1);
149         list = obj_h->list;
150         obj->magic = obj_h->magic;
151         obj->size = obj_h->obj_size;
152         obj->next = list;
153         obj_h->list = objptr;
154         obj_h->nr_free++;
155         xlock_release(&obj_h->lock);
156 }
157
158 void * xobj_get_obj(struct xobject_h * obj_h, uint32_t flags)
159 {
160
161         void *container = XPTR(&obj_h->container);
162         struct xobject *obj = NULL;
163         int r;
164         xptr list, objptr;
165
166         xlock_acquire(&obj_h->lock, 1);
167 retry:
168         list = obj_h->list;
169         if (!list)
170                 goto alloc;
171         obj = XPTR_TAKE(list, container);
172         objptr = obj->next;
173         obj_h->list = objptr;
174         obj_h->nr_free--;
175         goto out;
176
177 alloc:
178         if (!(flags & X_ALLOC))
179                 goto out;
180         //allocate minimum 64 objects
181         r = xobj_alloc_obj(obj_h, 64);
182         if (r<0)
183                 goto out;
184         goto retry;
185 out:
186         xlock_release(&obj_h->lock);
187         return obj;
188 }
189
190 /* lock must be held, while using iteration on object handler
191  * or we risk hash resize and invalid memory access
192  */
193 void xobj_iter_init(struct xobject_h *obj_h, struct xobject_iter *it)
194 {
195         void *container = XPTR(&obj_h->container);
196
197         xhash_t *allocated = XPTR_TAKE(obj_h->allocated, container);
198         it->obj_h = obj_h;
199         xhash_iter_init(allocated, &it->xhash_it);
200         it->chunk = NULL;
201         it->cnt = 0;
202 }
203
204 int xobj_iterate(struct xobject_h *obj_h, struct xobject_iter *it, void **obj)
205 {
206         int r = 0;
207         void *container = XPTR(&obj_h->container);
208         xhash_t *allocated = XPTR_TAKE(obj_h->allocated, container);
209         xhashidx key, val;
210
211         if (!it->chunk ||
212              it->cnt >= xheap_get_chunk_size(it->chunk)/obj_h->obj_size){
213                 r = xhash_iterate(allocated, &it->xhash_it, &key, &val);
214                 if (!r)
215                         return 0;
216                 it->chunk = XPTR_TAKE(key, container);
217                 it->cnt = 0;
218         }
219
220         *obj = (void *) ((unsigned long) it->chunk +
221                         (unsigned long) it->cnt * obj_h->obj_size);
222         it->cnt++;
223
224         return 1;
225
226 }
227
228 //FIXME make it smarter. aka check if ptr in mem chunk range and offset is
229 //consistent wit obj_size
230 int __xobj_check(struct xobject_h *obj_h, void *ptr)
231 {
232         xhash_iter_t it;
233         uint64_t i, nr_objs;
234         xhashidx key, val;
235         void *mem;
236         void *obj;
237         void *container = XPTR(&obj_h->container);
238         xhash_t *allocated = XPTR_TAKE(obj_h->allocated, container);
239         xhash_iter_init(allocated, &it);
240         while (xhash_iterate(allocated, &it, &key, &val)){
241                 mem = XPTR_TAKE(key, container);
242                 nr_objs = xheap_get_chunk_size(mem)/obj_h->obj_size;
243                 for (i = 0; i < nr_objs; i++) {
244                         obj = (void *) ((unsigned long) mem +
245                                         (unsigned long) i * obj_h->obj_size);
246                         if (obj == ptr) {
247                                 return 1;
248                         }
249                 }
250         }
251         return 0;
252 }
253
254 int xobj_check(struct xobject_h *obj_h, void *ptr)
255 {
256         int r;
257         xlock_acquire(&obj_h->lock, 1);
258         r = __xobj_check(obj_h, ptr);
259         xlock_release(&obj_h->lock);
260         return r;
261 }
262
263 int __xobj_isFree(struct xobject_h *obj_h, void *ptr)
264 {
265         void *container = XPTR(&obj_h->container);
266         xptr node;
267         struct xobject *obj;
268
269
270         node = obj_h->list;
271         while (node){
272                 obj = XPTR_TAKE(node, container);
273                 if (obj == ptr){
274                         return 1;
275                 }
276                 node = obj->next;
277         }
278
279
280         return 0;
281 }
282
283 int xobj_isFree(struct xobject_h *obj_h, void *ptr)
284 {
285         int r;
286         xlock_acquire(&obj_h->lock, 1);
287         r = __xobj_isFree(obj_h, ptr);
288         xlock_release(&obj_h->lock);
289         return r;
290 }
291
292
293 #ifdef __KERNEL__
294 #include <linux/module.h>
295 #include <xtypes/xobj_exports.h>
296 #endif