Statistics
| Branch: | Tag: | Revision:

root / xseg / xtypes / xobj.c @ d8a852fa

History | View | Annotate | Download (7.5 kB)

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