small fixes in xseg-tool , filed
[archipelago] / xseg / xtypes / xobj.c
1 #include <xtypes/xobj.h>
2 #include <xtypes/xhash.h>
3 #include <xtypes/domain.h>
4
5 int xobj_handler_init(struct xobject_h *obj_h, void *container,
6                 uint32_t magic, uint64_t size, struct xheap *heap)
7 {
8         //uint64_t bytes;
9         xhash_t *xhash;
10         obj_h->magic = magic;
11         /* minimum object size */
12         if (size < sizeof(struct xobject))
13                 obj_h->obj_size = sizeof(struct xobject);
14         else
15                 obj_h->obj_size = size;
16
17         //TODO convert this to xset
18         /* request space of an xhash of sizeshift 3 */
19         xhash = (xhash_t *) xheap_allocate(heap, xhash_get_alloc_size(3));
20         if (!xhash)
21                 return -1;
22
23         //FIXME
24         /* but initialize an xhash with sizeshift based on
25          * allocated space. should be at least the above sizeshift
26          */
27         //bytes = xheap_get_chunk_size(xhash);
28         
29         xhash_init(xhash, 3);
30         obj_h->allocated = XPTR_MAKE(xhash, container);
31         obj_h->list = 0;
32         obj_h->flags = 0;
33         obj_h->heap = XPTR_MAKE(heap, container);
34         XPTRSET(&obj_h->container, container);
35         xlock_release(&obj_h->lock);
36         return 0;
37
38 }
39
40 int xobj_alloc_obj(struct xobject_h * obj_h, uint64_t nr)
41 {
42         void *container = XPTR(&obj_h->container);
43         struct xheap *heap = XPTR_TAKE(obj_h->heap, container);
44         struct xobject *obj = NULL;
45
46         unsigned long i = 0;
47
48         uint64_t used, bytes = nr * obj_h->obj_size;
49         xptr objptr;
50         xhash_t *allocated = XPTR_TAKE(obj_h->allocated, container);
51         int r;
52         
53         void *mem = xheap_allocate(heap, bytes);
54
55         if (!mem)
56                 return -1;
57
58         bytes = xheap_get_chunk_size(mem);
59 //      printf("memory: %lu\n", XPTR_MAKE(mem, container));
60         used = 0;
61         while (used + obj_h->obj_size < bytes) {
62 //              printf("obj_size: %llu, used: %llu, bytes: %llu\n", obj_h->obj_size, used, bytes);
63                 objptr = XPTR_MAKE(((unsigned long) mem) + used, container);
64 //              printf("objptr: %lu\n", objptr);
65                 obj = XPTR_TAKE(objptr, container);
66                 used += obj_h->obj_size;
67                 obj->magic = obj_h->magic;
68                 obj->size = obj_h->obj_size;
69                 obj->next = XPTR_MAKE(((unsigned long) mem) + used, container); //point to the next obj
70 //              printf("foo: %lx\n", &obj->next);
71                 
72                 i++;
73
74 retry:
75                 r = xhash_insert(allocated, objptr, objptr); //keep track of allocated objects
76                 //ugly
77                 if (r == -XHASH_ERESIZE) {
78                         ul_t sizeshift = grow_size_shift(allocated);
79 //                      printf("new sizeshift: %lu\n", sizeshift);
80                         uint64_t size;
81                         xhash_t *new;
82                         size = xhash_get_alloc_size(sizeshift); 
83 //                      printf("new size: %lu\n", size);
84 //                      printf("%llu\n", xheap_get_chunk_size(allocated));
85                         new = xheap_allocate(heap, size);
86 //                      printf("requested %llu, got %llu\n", size, xheap_get_chunk_size(new));
87                         if (!new) {
88                                 xheap_free(mem);
89                                 return -1;
90                         }
91                         xhash_resize(allocated, sizeshift, new);
92                         xheap_free(allocated);
93                         allocated = new;
94                         obj_h->allocated = XPTR_MAKE(allocated, container);
95                         goto retry;
96                 }
97         }
98         XSEGLOG("allocated %lu elements\n", i);
99         if (!obj)
100                 return -1;
101         objptr = obj_h->list;
102         obj->next = objptr; 
103         obj_h->list = XPTR_MAKE((unsigned long) mem, container);
104         return 0;
105 }
106
107 void xobj_put_obj(struct xobject_h * obj_h, void *ptr)
108 {
109         struct xobject *obj = (struct xobject *) ptr;
110         void *container = XPTR(&obj_h->container);
111         xptr list, objptr = XPTR_MAKE(obj, container);
112         xlock_acquire(&obj_h->lock, 1);
113         list = obj_h->list;
114         obj->next = list;
115         obj_h->list = objptr;
116         xlock_release(&obj_h->lock);
117 }
118
119 void * xobj_get_obj(struct xobject_h * obj_h, uint32_t flags)
120 {
121
122         void *container = XPTR(&obj_h->container);
123         struct xobject *obj = NULL;
124         int r;
125         xptr list, objptr;
126
127         xlock_acquire(&obj_h->lock, 1);
128 retry:
129         list = obj_h->list;
130         if (!list)
131                 goto alloc;
132         obj = XPTR_TAKE(list, container);
133         objptr = obj->next;
134         obj_h->list = objptr;
135         goto out;
136
137 alloc:
138         if (!(flags & X_ALLOC)) 
139                 goto out;
140         //allocate minimum 64 objects
141         r = xobj_alloc_obj(obj_h, 64);
142         if (r<0)
143                 goto out;
144         goto retry;
145 out: 
146         xlock_release(&obj_h->lock);
147         return obj;
148 }
149