| |
| |
| |
| |
| |
| |
| #include <dalist/dalist.h> |
| #include "dalist_impl.h" |
| |
| |
| static void * dalist_alloc(struct dalist_ex * dlist); |
| |
| static int dalist_memfn_internal( |
| struct dalist_ex * dlist, |
| void ** addr, |
| size_t * alloc_size); |
| |
| |
| dalist_api |
| int dalist_get_free_node( |
| struct dalist_ex * dlist, |
| void ** fnode) |
| { |
| int ret; |
| struct dalist_node * nfree; |
| |
| |
| *fnode = (void *)0; |
| |
| if (dlist->free) |
| |
| nfree = (struct dalist_node *)dlist->free; |
| else |
| nfree = (struct dalist_node *)dalist_alloc(dlist); |
| |
| if (nfree) { |
| *fnode = nfree; |
| dlist->free = nfree->next; |
| |
| if (nfree->next) |
| nfree->next->prev = 0; |
| |
| |
| dlist->info.free_nodes--; |
| |
| |
| nfree->prev = nfree->next = 0; |
| ret = DALIST_OK; |
| } else |
| ret = DALIST_EMEMFN; |
| |
| return ret; |
| } |
| |
| |
| dalist_api |
| int dalist_deposit_free_node( |
| struct dalist_ex * dlist, |
| void * fnode) |
| { |
| int ret; |
| struct dalist_node * nfree; |
| |
| if (fnode) { |
| nfree = (struct dalist_node *)fnode; |
| nfree->next = (struct dalist_node *)dlist->free; |
| |
| |
| nfree->prev = 0; |
| dlist->free = fnode; |
| |
| |
| dlist->info.free_nodes++; |
| ret = DALIST_OK; |
| } else { |
| ret = DALIST_ENODE; |
| } |
| |
| return ret; |
| } |
| |
| |
| dalist_api |
| int dalist_deposit_memory_block( |
| struct dalist_ex * dlist, |
| void * addr, |
| size_t alloc_size) |
| { |
| struct dalist_node * fnode; |
| struct dalist_node * fnode_next; |
| char * naddr; |
| char * naddr_next; |
| char * naddr_upper; |
| size_t node_size; |
| |
| |
| if (dlist->dblock_size == 0) |
| node_size = sizeof(struct dalist_node); |
| else |
| node_size = (size_t)&((struct dalist_node_ex *)0)->dblock |
| + dlist->dblock_size; |
| |
| |
| node_size += sizeof(uintptr_t)-1; |
| node_size |= sizeof(uintptr_t)-1; |
| node_size ^= sizeof(uintptr_t)-1; |
| |
| |
| if (alloc_size < node_size) |
| return DALIST_EMEMBLOCK; |
| |
| |
| naddr = (char *)addr; |
| naddr_next = naddr + node_size; |
| naddr_upper = naddr + alloc_size; |
| |
| |
| while ((naddr_next + node_size) < naddr_upper) { |
| fnode = (struct dalist_node *)naddr; |
| fnode_next = (struct dalist_node *)naddr_next; |
| |
| fnode->next = fnode_next; |
| fnode_next->prev = fnode; |
| |
| naddr += node_size; |
| naddr_next += node_size; |
| } |
| |
| |
| fnode = (struct dalist_node *)addr; |
| fnode_next = (struct dalist_node *)naddr; |
| |
| if (dlist->free) { |
| |
| fnode_next->next = (struct dalist_node *)dlist->free; |
| ((struct dalist_node *)dlist->free)->prev = fnode_next; |
| } else { |
| |
| fnode_next->next = 0; |
| } |
| |
| |
| fnode->prev = 0; |
| dlist->free = fnode; |
| |
| |
| dlist->info.free_nodes += (alloc_size / node_size); |
| |
| return DALIST_OK; |
| } |
| |
| |
| static void * __cdecl dalist_alloc(struct dalist_ex * dlist) |
| { |
| int ret; |
| void * addr; |
| size_t alloc_size; |
| memfn_custom * pmemfn; |
| struct dalist_node * fnode; |
| |
| |
| if (dlist->memfn_method == DALIST_MEMFN_CUSTOM) |
| pmemfn = (dalist_memfn_custom *)(uintptr_t)dlist->memfn_ptr; |
| else |
| pmemfn = dalist_memfn_internal; |
| |
| |
| fnode = 0; |
| ret = pmemfn(dlist,&addr,&alloc_size); |
| |
| |
| if (ret == DALIST_OK) { |
| if (dlist->memfn_method == DALIST_MEMFN_MALLOC) |
| fnode = (struct dalist_node *)addr; |
| else if (dalist_deposit_memory_block( |
| dlist, |
| addr, |
| alloc_size) == DALIST_OK) |
| fnode = (struct dalist_node *)dlist->free; |
| } |
| |
| return fnode; |
| } |
| |
| |
| static int __cdecl dalist_memfn_internal( |
| struct dalist_ex * dlist, |
| void ** address, |
| size_t * alloc_size) |
| { |
| int ret; |
| void * addr; |
| size_t size; |
| |
| memfn_mmap * pfn_mmap; |
| memfn_malloc * pfn_malloc; |
| memfn_allocvm * pfn_allocvm; |
| |
| switch (dlist->memfn_method) { |
| case DALIST_MEMFN_MALLOC: |
| if (dlist->dblock_size == 0) |
| size = sizeof(struct dalist_node); |
| else |
| size = (size_t)((struct dalist_node_ex *)0)->dblock |
| + dlist->dblock_size; |
| |
| pfn_malloc = (memfn_malloc *)(uintptr_t)dlist->memfn_ptr; |
| addr = pfn_malloc(size); |
| |
| if (addr) { |
| *address = addr; |
| *alloc_size = size; |
| ret = dlist->memfn_status = DALIST_OK; |
| } else { |
| ret = DALIST_EMEMFN; |
| dlist->memfn_status = dalist_errno(ret); |
| } |
| break; |
| |
| case DALIST_MEMFN_MMAP: |
| pfn_mmap = (memfn_mmap * )(uintptr_t)dlist->memfn_ptr; |
| |
| addr = pfn_mmap( |
| (void *)0, |
| dlist->lblock_size, |
| PROT_READ | PROT_WRITE, |
| MAP_ANON | MAP_SHARED, |
| 0,0); |
| |
| if (addr) { |
| *address = addr; |
| *alloc_size = dlist->lblock_size; |
| ret = dlist->memfn_status = DALIST_OK; |
| } else { |
| ret = DALIST_EMEMFN; |
| dlist->memfn_status = dalist_errno(ret); |
| } |
| break; |
| |
| case DALIST_MEMFN_NT_ALLOCATE_VIRTUAL_MEMORY: |
| addr = (void *)0; |
| size = dlist->lblock_size; |
| pfn_allocvm = (memfn_allocvm *)(uintptr_t)dlist->memfn_ptr; |
| |
| dlist->memfn_status = pfn_allocvm( |
| NT_CURRENT_PROCESS_HANDLE, |
| &addr, |
| 0, |
| &size, |
| NT_MEM_COMMIT, |
| NT_PAGE_READWRITE); |
| |
| if (dlist->memfn_status == NT_STATUS_SUCCESS) { |
| *address = addr; |
| *alloc_size = size; |
| ret = DALIST_OK; |
| } else { |
| ret = DALIST_EMEMFN; |
| } |
| break; |
| default: |
| ret = DALIST_EINTERNAL; |
| break; |
| } |
| |
| return ret; |
| } |