summaryrefslogtreecommitdiff
path: root/src/lib/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/memory.c')
-rw-r--r--src/lib/memory.c83
1 files changed, 80 insertions, 3 deletions
diff --git a/src/lib/memory.c b/src/lib/memory.c
index 8a91d2d..b6e044a 100644
--- a/src/lib/memory.c
+++ b/src/lib/memory.c
@@ -26,6 +26,7 @@ memory_init(struct aplwc *aplwc)
aplwc->unaligned_data = NULL;
aplwc->size = 0;
aplwc->memptrs = NULL;
+ aplwc->rootptrs = NULL;
}
void
@@ -49,6 +50,7 @@ fixrefs(struct aplwc *aplwc, uint8_t *new, uint8_t *old)
struct chunk *c;
struct memory_ptr_frame *frame;
+ struct root_ptr *root;
size_t add, sub, i;
if(new > old){
@@ -89,6 +91,10 @@ fixrefs(struct aplwc *aplwc, uint8_t *new, uint8_t *old)
for(i = 0; i < frame->count; i++)
if(frame->ptrs[i])
FIX(*frame->ptrs[i]);
+
+ for(root = aplwc->rootptrs; root; root = root->link)
+ if(root->ptr)
+ FIX(root->ptr);
#undef FIX
#undef FIX_DATA
@@ -198,13 +204,71 @@ retry:
return new->data;
}
+struct aplwc_ref
+memory_root_new(struct aplwc *aplwc, void *p)
+{
+ struct aplwc_ref ref;
+ struct root_ptr *root;
+ size_t size;
+
+ clear_ref(&ref);
+ if(aplwc->fns.alloc == NULL){
+ aplwc->last_error = APLWC_OUT_OF_MEMORY;
+ goto end;
+ }
+
+ root = aplwc->fns.alloc(sizeof(*root), sizeof(*root), &size);
+ if(root == NULL){
+ aplwc->last_error = APLWC_OUT_OF_MEMORY;
+ goto end;
+ }
+
+ root->id = aplwc->rootptrs ? (aplwc->rootptrs->id+1) : 0;
+ root->ptr = p;
+ root->link = aplwc->rootptrs;
+ aplwc->rootptrs = root;
+
+ ref.id = root->id;
+ ref.aplwc = aplwc;
+end:
+ return ref;
+}
+
+void *
+memory_root_get(struct aplwc_ref ref)
+{
+ struct root_ptr *root;
+
+ if(!valid_ref(ref))
+ return NULL;
+
+ for(root = ref.aplwc->rootptrs; root; root = root->link)
+ if(root->id == ref.id)
+ return root->ptr;
+
+ return NULL;
+}
+
void
-memory_free_root(struct aplwc *aplwc, void *p)
+memory_root_free(struct aplwc_ref ref)
{
- if(NEVER(p == NULL))
+ struct aplwc *aplwc;
+ struct root_ptr **root, *tmp;
+
+ if(!valid_ref(ref))
return;
- UNUSED_PARAMETER(aplwc);
+ aplwc = ref.aplwc;
+
+ for(root = &aplwc->rootptrs; (*root); root = &(*root)->link){
+ if((*root)->id == ref.id){
+ tmp = *root;
+ *root = tmp->link;
+ if(aplwc->fns.dealloc)
+ aplwc->fns.dealloc(tmp);
+ break;
+ }
+ }
}
void
@@ -273,3 +337,16 @@ memory_alloc_aplwc_module(struct aplwc *aplwc)
p = alloc(aplwc, sizeof(struct aplwc_module), CHUNK_TAG_APLWC_MODULE);
return p;
}
+
+void
+clear_ref(struct aplwc_ref *ref)
+{
+ ref->id = -1;
+ ref->aplwc = NULL;
+}
+
+int
+valid_ref(struct aplwc_ref ref)
+{
+ return ref.id >= 0;
+}