├── config.h.in ├── perf ├── CMakeLists.txt ├── struct_objs_read.c ├── common.h ├── struct_objs_write.c └── common.c ├── src ├── pmvalloc.c ├── pmcalloc.c ├── pmsync.c ├── pmreport.c ├── pmaddress.c ├── pmdetach.c ├── pmkeys.c ├── CMakeLists.txt ├── pmalloc.c ├── pmalign.c ├── pmfree.c ├── pmattach.c ├── pmfunction.h ├── pmalloc.h ├── pmmap.c ├── pmrealloc.c ├── pminternal.h ├── pmcheck.c └── pmfunction.c ├── .gitignore ├── CMakeLists.txt ├── tests ├── CMakeLists.txt ├── check_common.h ├── test.c ├── check_pmalloc.c ├── check_pmrecycle.c ├── check_pmsimulate.c ├── check_pmclear.c └── check_common.c ├── CMakeModules └── FindCheck.cmake ├── README.md └── LICENSE /config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef GUARD 2 | #define GUARD 3 | 4 | #cmakedefine _CONFIG_HEADER_H_ 5 | 6 | #endif //GUARD 7 | -------------------------------------------------------------------------------- /perf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(struct_objs_write struct_objs_write.c common.c) 3 | add_executable(struct_objs_read struct_objs_read.c common.c) 4 | 5 | target_link_libraries (struct_objs_write LINK_PUBLIC pmalloc 6 | $<$:${LIBRT_LIBRARIES}>) 7 | target_link_libraries (struct_objs_read LINK_PUBLIC pmalloc 8 | $<$:${LIBRT_LIBRARIES}>) 9 | 10 | -------------------------------------------------------------------------------- /src/pmvalloc.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Allocate memory on a page boundary 3 | 4 | *****************************************************************************************/ 5 | 6 | #include "pminternal.h" 7 | 8 | static size_t pagesize; 9 | 10 | void * pmvalloc(void *md, size_t size) { 11 | if (pagesize == 0) { 12 | pagesize = getpagesize(); 13 | } 14 | 15 | return (pmalign(md, pagesize, size)); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /src/pmcalloc.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persist Memory allocator. 3 | *****************************************************************************************/ 4 | 5 | #include "pminternal.h" 6 | 7 | void * pmcalloc(void * md, size_t nmemb, size_t size) { 8 | register void * result; 9 | 10 | if ((result = pmalloc(md, nmemb * size)) != NULL) { 11 | memset(result, 0, nmemb * size); 12 | } 13 | return (result); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/pmsync.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | 3 | *****************************************************************************************/ 4 | 5 | #include "pminternal.h" 6 | 7 | int pmsync(void *md, void *addr, size_t length) { 8 | struct mdesc *mdp = (struct mdesc *) md; 9 | int result = -1; 10 | if (mdp->mempoolbase < (char*)addr && length > 0) { 11 | result = msync(addr, length, MS_SYNC); 12 | } 13 | return (result); 14 | } 15 | -------------------------------------------------------------------------------- /src/pmreport.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Report statistical information. 3 | 4 | *****************************************************************************************/ 5 | 6 | #include "pmfunction.h" 7 | #include "pminternal.h" 8 | 9 | 10 | size_t report_used_inbyte(struct mdesc * mdp) 11 | { 12 | assert(NULL != mdp); 13 | return mdp -> mblkstats.bytes_used; 14 | } 15 | 16 | size_t report_free_inbyte(struct mdesc * mdp) 17 | { 18 | assert(NULL != mdp); 19 | return mdp -> mblkstats.bytes_free; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | *~ 3 | *.lo 4 | *.o 5 | *.la 6 | *.so 7 | *.data 8 | *.dat 9 | *.bak 10 | libtool 11 | aclocal.m4 12 | configure 13 | dist 14 | m4 15 | Makefile 16 | Makefile.in 17 | ar-lib 18 | compile 19 | config.guess 20 | config.sub 21 | depcomp 22 | install-sh 23 | ltmain.sh 24 | missing 25 | .libs 26 | .deps 27 | config.h 28 | config.log 29 | config.status 30 | stamp-h1 31 | autom4te.cache 32 | tests/check_pmalloc 33 | tmp/ 34 | *.log 35 | perf/struct_objs_read 36 | perf/struct_objs_write 37 | tests/check_pmclear 38 | tests/check_pmrecycle 39 | tests/check_pmsimulate 40 | build/ 41 | .* 42 | 43 | -------------------------------------------------------------------------------- /src/pmaddress.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Support portable address conversion. 3 | 4 | *****************************************************************************************/ 5 | 6 | #include "pminternal.h" 7 | 8 | inline void * p_addr(void *md, void *addr) { 9 | struct mdesc *mdp = (struct mdesc *) md; 10 | return NULL == addr ? NULL : addr - (size_t) (mdp->mempoolbase); 11 | } 12 | 13 | inline void * e_addr(void *md, void *addr) { 14 | struct mdesc *mdp = (struct mdesc *) md; 15 | return NULL == addr ? NULL : (size_t) addr + mdp->mempoolbase; 16 | } 17 | 18 | inline void * b_addr(void *md) { 19 | struct mdesc *mdp = (struct mdesc *) md; 20 | return mdp->mempoolbase; 21 | } 22 | -------------------------------------------------------------------------------- /src/pmdetach.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Finish access to a persist memory allocator managed region. 3 | *****************************************************************************************/ 4 | 5 | #include "pmfunction.h" 6 | #include "pminternal.h" 7 | 8 | void *pmalloc_detach(void *md) { 9 | struct mdesc mtemp; 10 | 11 | if (md != NULL) { 12 | 13 | mtemp = *(struct mdesc *) md; 14 | 15 | if ((mtemp.morespace(&mtemp, mtemp.mempoolbase - mtemp.limitpos)) 16 | == NULL) { 17 | *(struct mdesc *) md = mtemp; 18 | } else { 19 | if (mtemp.flags & PMALLOC_DEVZERO) { 20 | close(mtemp.mappingfd); 21 | } 22 | md = NULL; 23 | } 24 | } 25 | 26 | return (md); 27 | } 28 | -------------------------------------------------------------------------------- /src/pmkeys.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | 3 | *****************************************************************************************/ 4 | 5 | #include "pminternal.h" 6 | 7 | int pmalloc_setkey(void *md, int keyidx, void *key) { 8 | struct mdesc *mdp = (struct mdesc *) md; 9 | int result = 0; 10 | 11 | if ((mdp != NULL) && (keyidx >= 0) && (keyidx < PMALLOC_KEYS)) { 12 | mdp->persistkeys[keyidx] = key; 13 | result++; 14 | } 15 | return (result); 16 | } 17 | 18 | void * pmalloc_getkey(void *md, int keyidx) { 19 | struct mdesc *mdp = (struct mdesc *) md; 20 | void * keyval = NULL; 21 | 22 | if ((mdp != NULL) && (keyidx >= 0) && (keyidx < PMALLOC_KEYS)) { 23 | keyval = mdp->persistkeys[keyidx]; 24 | } 25 | return (keyval); 26 | } 27 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIB_OUTPUT_NAME pmalloc) 2 | set(LIB_STATIC_OUTPUT_NAME ${LIB_OUTPUT_NAME}_static) 3 | 4 | set (CMAKE_POSITION_INDEPENDENT_CODE TRUE) 5 | 6 | aux_source_directory(. DIR_LIB_SRCS) 7 | 8 | add_library(${LIB_OUTPUT_NAME} SHARED ${DIR_LIB_SRCS}) 9 | add_library(${LIB_STATIC_OUTPUT_NAME} STATIC ${DIR_LIB_SRCS}) 10 | 11 | set_target_properties(${LIB_OUTPUT_NAME} PROPERTIES VERSION 1.8.0 SOVERSION 1) 12 | set_target_properties(${LIB_STATIC_OUTPUT_NAME} PROPERTIES VERSION 1.8.0 SOVERSION 1) 13 | 14 | target_include_directories(${LIB_OUTPUT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 15 | target_include_directories(${LIB_STATIC_OUTPUT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) 16 | 17 | install(TARGETS ${LIB_OUTPUT_NAME} LIBRARY DESTINATION lib) 18 | install(TARGETS ${LIB_STATIC_OUTPUT_NAME} ARCHIVE DESTINATION lib) 19 | 20 | install(FILES pmalloc.h DESTINATION include) 21 | 22 | -------------------------------------------------------------------------------- /src/pmalloc.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persist Memory allocator 3 | 4 | *****************************************************************************************/ 5 | 6 | #include "pmfunction.h" 7 | #include "pminternal.h" 8 | 9 | void * pmalloc(void *md, size_t size) { 10 | assert(NULL != md); 11 | struct mdesc *mdp = (struct mdesc *) md; 12 | void *result = NULL; 13 | 14 | if (size == 0) { 15 | return (NULL); 16 | } 17 | 18 | if (!(mdp->flags & PMALLOC_INITIALIZED)) { 19 | if (!initialize(mdp)) { 20 | return (NULL); 21 | } 22 | } 23 | 24 | if (size < sizeof(struct list)) { 25 | size = sizeof(struct list); 26 | } 27 | 28 | if ( 0 ) { // (BLOCKSIZE / 2) { 29 | result = allocate_blockfrag(mdp, size); 30 | } else { 31 | size_t blocks = BLOCKIFY(size); 32 | result = allocate_blocks(mdp, blocks); 33 | } 34 | 35 | return (result); 36 | } 37 | -------------------------------------------------------------------------------- /src/pmalign.c: -------------------------------------------------------------------------------- 1 | #include "pmfunction.h" 2 | #include "pminternal.h" 3 | 4 | void *pmalign(void *md, size_t alignment, size_t size) { 5 | void * result; 6 | unsigned long int adj; 7 | struct alignlist *ablist; 8 | struct mdesc *mdp = (struct mdesc *) md; 9 | 10 | if ((result = pmalloc(md, size + alignment - 1)) != NULL) { 11 | adj = RESIDUAL(result, alignment); 12 | if (adj != 0) { 13 | for (ablist = mdp->aligned_blocks; ablist != NULL; 14 | ablist = ablist->next) { 15 | if (ablist->alignedaddr == NULL) { 16 | break; 17 | } 18 | } 19 | if (ablist == NULL) { 20 | ablist = (struct alignlist *) pmalloc(md, 21 | sizeof(struct alignlist)); 22 | if (ablist == NULL) { 23 | pmfree(md, result); 24 | return (NULL); 25 | } 26 | ablist->next = mdp->aligned_blocks; 27 | mdp->aligned_blocks = ablist; 28 | } 29 | ablist->unalignedaddr = result; 30 | result = ablist->alignedaddr = (char *) result + alignment - adj; 31 | } 32 | } 33 | return (result); 34 | } 35 | -------------------------------------------------------------------------------- /src/pmfree.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | 3 | *****************************************************************************************/ 4 | 5 | #include "pmfunction.h" 6 | #include "pminternal.h" 7 | 8 | void __pmalloc_free(struct mdesc *mdp, void *addr) { 9 | size_t block = BLOCK(addr); 10 | 11 | int fragtype = mdp->mblkinfo[block].inuse.fragtype; 12 | switch (fragtype) { 13 | case 0: 14 | free_blocks(mdp, block); 15 | break; 16 | 17 | default: 18 | free_blockfrag(mdp, block, fragtype, addr); 19 | break; 20 | } 21 | } 22 | 23 | void pmfree(void *md, void *addr) { 24 | struct mdesc *mdp = (struct mdesc *) md; 25 | register struct alignlist *l; 26 | 27 | if (addr != NULL) { 28 | for (l = mdp->aligned_blocks; l != NULL; l = l->next) { 29 | if (l->alignedaddr == addr) { 30 | l->alignedaddr = NULL; 31 | addr = l->unalignedaddr; 32 | break; 33 | } 34 | } 35 | __pmalloc_free(mdp, addr); 36 | // if (check_heap_free_info(mdp) < 0) exit(1); 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.11) 2 | project(pmalloc) 3 | 4 | configure_file ( 5 | "${PROJECT_SOURCE_DIR}/config.h.in" 6 | "${PROJECT_BINARY_DIR}/config.h" 7 | ) 8 | include_directories(${PROJECT_BINARY_DIR}) 9 | 10 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeModules/") 11 | set(pmalloc_VERSION_MAJOR 1) 12 | set(pmalloc_VERSION_MINOR 8) 13 | set(CMAKE_BUILD_TYPE "Release") 14 | set(CMAKE_C_FLAGS_DEBUG "$ENV{CFLAGS} -O0 -Wall -rdynamic -g -ggdb") 15 | set(CMAKE_C_FLAGS_RELEASE "$ENV{CFLAGS} -O3 -Wall") 16 | set(CMAKE_MACOSX_RPATH 1) 17 | 18 | find_library(LIBRT_LIBRARIES rt) 19 | 20 | find_package(Threads REQUIRED) 21 | include_directories(${CMAKE_THREAD_LIBS_INIT}) 22 | 23 | enable_testing() 24 | add_subdirectory(src) 25 | add_subdirectory(perf) 26 | add_subdirectory(tests) 27 | 28 | include (InstallRequiredSystemLibraries) 29 | set (CPACK_RESOURCE_FILE_LICENSE 30 | "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") 31 | set (CPACK_PACKAGE_VERSION_MAJOR "${pmalloc_VERSION_MAJOR}") 32 | set (CPACK_PACKAGE_VERSION_MINOR "${pmalloc_VERSION_MINOR}") 33 | include (CPack) 34 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_testing() 2 | find_package(Check REQUIRED) 3 | include_directories(${CHECK_INCLUDE_DIRS}) 4 | set(LIBS ${LIBS} ${CHECK_LIBRARIES} pmalloc $<$:${LIBRT_LIBRARIES}>) 5 | include_directories(. ../src) 6 | 7 | if( APPLE ) 8 | link_directories( "/opt/local/lib" ) 9 | endif( APPLE ) 10 | 11 | add_executable(check_pmsimulate check_pmsimulate.c check_common.c) 12 | target_link_libraries(check_pmsimulate ${LIBS}) 13 | add_test(check_pmsimulate ${CMAKE_CURRENT_BINARY_DIR}/check_pmsimulate) 14 | 15 | add_executable(check_pmrecycle check_pmrecycle.c check_common.c) 16 | target_link_libraries(check_pmrecycle ${LIBS}) 17 | add_test(check_pmrecycle ${CMAKE_CURRENT_BINARY_DIR}/check_pmrecycle) 18 | 19 | add_executable(check_pmclear check_pmclear.c check_common.c) 20 | target_link_libraries(check_pmclear ${LIBS}) 21 | add_test(check_pmclear ${CMAKE_CURRENT_BINARY_DIR}/check_pmclear) 22 | 23 | add_executable(check_pmalloc check_pmalloc.c check_common.c) 24 | target_link_libraries(check_pmalloc ${LIBS}) 25 | add_test(check_pmalloc ${CMAKE_CURRENT_BINARY_DIR}/check_pmalloc) 26 | 27 | -------------------------------------------------------------------------------- /tests/check_common.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Declare all check related functions 3 | 4 | *****************************************************************************************/ 5 | 6 | #ifndef __CHECK_COMMON_H 7 | #define __CHECK_COMMON_H 1 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define ANSI_COLOR_RED "\x1b[31m" 15 | #define ANSI_COLOR_GREEN "\x1b[32m" 16 | #define ANSI_COLOR_YELLOW "\x1b[33m" 17 | #define ANSI_COLOR_BLUE "\x1b[34m" 18 | #define ANSI_COLOR_MAGENTA "\x1b[35m" 19 | #define ANSI_COLOR_CYAN "\x1b[36m" 20 | #define ANSI_COLOR_RESET "\x1b[0m" 21 | 22 | void init_random(); 23 | 24 | int number_binary_length(size_t num); 25 | 26 | size_t random_number(size_t min_num, size_t max_num); 27 | 28 | void clear_keydata(void *md, long pattern[], size_t count); 29 | 30 | size_t refill_keydata(void *md, size_t sz); 31 | 32 | void gen_pattern(long pattern[], size_t count, int mode); 33 | 34 | int free_keydata(void *md, long keyidx); 35 | 36 | #endif /* __CHECK_COMMON_H */ 37 | -------------------------------------------------------------------------------- /perf/struct_objs_read.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | #define PM_CAPACITY 1024LL * 1024 * 1024 * 10 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | /* size_t emp_count = 0; */ 8 | 9 | if (argc != 2) { 10 | printf("Usage: %s filename", argv[0]); 11 | exit(-1); 12 | } 13 | 14 | char *fn = argv[1]; 15 | 16 | assert(NULL != fn); 17 | 18 | printf("Start the example reading struct objects from %s . \n", fn); 19 | 20 | int fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); 21 | if(fd < 0) { 22 | printf(ANSI_COLOR_RED "Open data file failure." ANSI_COLOR_RESET); 23 | return 1; 24 | } 25 | 26 | void *md = pmalloc_attach(fd, NULL, PM_CAPACITY); 27 | assert(NULL != md); 28 | 29 | init_roles(md); 30 | 31 | struct employee_t* emp_root = NULL; 32 | 33 | int cidx; 34 | 35 | for (cidx = COMPANY_MIN_INDEX; cidx <= COMPANY_MAX_INDEX; ++cidx) { 36 | printf(ANSI_COLOR_GREEN "Show company %d. \n" ANSI_COLOR_RESET, cidx); 37 | emp_root = pmalloc_getkey(md, cidx); 38 | if (NULL != emp_root) { 39 | print_employees(md, emp_root, 0); 40 | } 41 | } 42 | 43 | pmalloc_detach(md); 44 | close(fd); 45 | printf("PM Closed.\n"); 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /tests/test.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persistent Memory Library Tests 3 | 4 | *****************************************************************************************/ 5 | 6 | #define _LARGEFILE64_SOURCE 7 | #define _FILE_OFFSET_BITS 64 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | int random_number(int min_num, int max_num); 15 | 16 | int main() 17 | { 18 | char buf = 0; 19 | int fd = open("ds2.data", O_CREAT|O_RDWR|O_LARGEFILE, S_IRUSR|S_IWUSR); 20 | if(fd < 0) 21 | return 1; 22 | off_t off = lseek(fd, (2LL<<42) + 10, SEEK_SET); 23 | write (fd, &buf, 1); 24 | 25 | close(fd); 26 | printf("Hello world... %zx \n", off); 27 | return 0; 28 | } 29 | 30 | int random_number(int min_num, int max_num) 31 | { 32 | int result=0,low_num=0,hi_num=0; 33 | if(min_num 7 | #include 8 | #include "pmalloc.h" 9 | #include "check_common.h" 10 | 11 | int main() 12 | { 13 | /*srand(time(NULL));*/ 14 | int fd = open("pmalloc_test.dat", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); 15 | if(fd < 0) 16 | return 1; 17 | void *md = pmalloc_attach(fd, NULL, 1024LL * 1024 * 1024 * 10); 18 | 19 | void *key = NULL; 20 | int i; 21 | 22 | /*key = pmalloc_getkey(md, 3); 23 | pmfree(md, key); 24 | pmalloc_setkey(md, 3, NULL);*/ 25 | 26 | for (i = 0; i < 16; ++i) 27 | { 28 | key = pmalloc_getkey(md, i); 29 | if (NULL != key) 30 | printf("Prekey... %p --> %s %lu\n", key, (char*)key, sizeof(size_t)); 31 | else break; 32 | } 33 | 34 | 35 | 36 | void *data = pmalloc(md, 0x1000 * 5); 37 | if (NULL != data) { 38 | sprintf(data, "output data row %d", i); 39 | pmalloc_setkey(md, i, data); 40 | } 41 | 42 | size_t sz; 43 | do { 44 | sz = 0x1000 * random_number(1, 200); 45 | printf("Allocating %zx... \n", sz); 46 | } while (NULL != pmalloc(md, sz)); 47 | 48 | pmalloc_detach(md); 49 | close(fd); 50 | printf("Hello world... %p \n",data); 51 | return 0; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /perf/common.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Declare all examples related functions 3 | 4 | *****************************************************************************************/ 5 | 6 | #ifndef __COMMON_H 7 | #define __COMMON_H 1 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "pmalloc.h" 16 | 17 | #define ANSI_COLOR_RED "\x1b[31m" 18 | #define ANSI_COLOR_GREEN "\x1b[32m" 19 | #define ANSI_COLOR_YELLOW "\x1b[33m" 20 | #define ANSI_COLOR_BLUE "\x1b[34m" 21 | #define ANSI_COLOR_MAGENTA "\x1b[35m" 22 | #define ANSI_COLOR_CYAN "\x1b[36m" 23 | #define ANSI_COLOR_RESET "\x1b[0m" 24 | 25 | #define ROLES_PKEYID 200 26 | #define COMPANY_MIN_INDEX 1 27 | #define COMPANY_MAX_INDEX 100 28 | 29 | unsigned int init_random(unsigned int seed); 30 | 31 | int number_binary_length(size_t num); 32 | 33 | size_t random_number(size_t min_num, size_t max_num); 34 | 35 | void clear_keydata(void *md, long pattern[], size_t count); 36 | 37 | size_t refill_keydata(void *md, size_t sz); 38 | 39 | void gen_pattern(long pattern[], size_t count, int mode); 40 | 41 | void alloc_result(void *ptr); 42 | 43 | /*******************************************/ 44 | 45 | typedef struct employee_t { 46 | char* name; 47 | int age; 48 | char* role; 49 | struct employee_t **members; 50 | int mcount; 51 | } employee_t; 52 | 53 | extern char **g_roles; 54 | 55 | void init_roles(void *md); 56 | 57 | size_t gen_employees(void *md, struct employee_t** pemp, int avail_deep); 58 | 59 | void print_employees(void *md, struct employee_t* emp, int deep); 60 | 61 | 62 | #endif /* __COMMON_H */ 63 | -------------------------------------------------------------------------------- /src/pmattach.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Initialization for access to a persistent memory allocator managed pool. 3 | Persist Memory allocator 4 | 5 | *****************************************************************************************/ 6 | 7 | #include "pmfunction.h" 8 | #include "pminternal.h" 9 | 10 | void * pmalloc_attach(int fd, void *baseaddr, size_t initial_size) { 11 | struct mdesc mtemp; 12 | struct mdesc *mdp; 13 | void * mbase; 14 | struct stat sbuf; 15 | 16 | if (fd >= 0) { 17 | if (fstat(fd, &sbuf) < 0) { 18 | return (NULL); 19 | } else if (sbuf.st_size > 0) { 20 | return ((void *) reuse_mempool(fd)); 21 | } 22 | } 23 | 24 | mdp = &mtemp; 25 | memset((char *) mdp, 0, sizeof(mtemp)); 26 | strncpy(mdp->magicwords, PMALLOC_MAGIC, PMALLOC_MAGIC_SIZE); 27 | mdp->headersize = sizeof(mtemp); 28 | mdp->version = PMALLOC_VERSION; 29 | mdp->morespace = __pmalloc_map_morespace; 30 | mdp->mappingfd = fd; 31 | mdp->mempoolbase = mdp->watermarkpos = mdp->limitpos = baseaddr; 32 | 33 | if (mdp->mappingfd < 0) { 34 | #ifdef HAVE_MMAP_ANON 35 | mdp->flags |= MMALLOC_ANON; 36 | #else 37 | #ifdef HAVE_MMAP_DEV_ZERO 38 | if ((mdp -> mappingfd = open ("/dev/zero", O_RDWR)) < 0) 39 | { 40 | return (NULL); 41 | } 42 | else 43 | { 44 | mdp -> flags |= PMALLOC_DEVZERO; 45 | } 46 | #else 47 | return NULL; 48 | #endif 49 | #endif 50 | } 51 | 52 | if ((mbase = mdp->morespace(mdp, sizeof(mtemp) + initial_size)) != NULL) { 53 | memcpy(mbase, mdp, sizeof(mtemp)); 54 | mdp = (struct mdesc *) mbase; 55 | mdp->morespace(mdp, -initial_size); 56 | } else { 57 | if (mdp->flags & PMALLOC_DEVZERO) { 58 | close(mdp->mappingfd); 59 | } 60 | mdp = NULL; 61 | } 62 | 63 | return ((void *) mdp); 64 | } 65 | -------------------------------------------------------------------------------- /src/pmfunction.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persist Memory allocator 3 | *****************************************************************************************/ 4 | 5 | #ifndef PMFUNCTION_H 6 | #define PMFUNCTION_H 1 7 | 8 | #include "config.h" 9 | #include "pminternal.h" 10 | 11 | #define PMALLOC_DEVZERO (1 << 0) 12 | 13 | #define PMALLOC_INITIALIZED (1 << 1) 14 | 15 | #define PMALLOC_PMCHECK_USED (1 << 2) 16 | 17 | #define PMALLOC_ANON (1 << 3) 18 | 19 | #define PMALLOC_FILE (1 << 4) 20 | 21 | #define REBASE_ADDRESS(A, O) ((void*)(A) + (O)) 22 | 23 | #ifndef MIN 24 | # define MIN(A, B) ((A) < (B) ? (A) : (B)) 25 | #endif 26 | 27 | #define BLOCKSIZE ((unsigned int) 1 << BLOCKLOG) 28 | #define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) 29 | 30 | #define RESIDUAL(addr, bsize) ((size_t) ((size_t)addr % (bsize))) 31 | 32 | #define BLOCK(A) (((char *) (A) - mdp -> mblkinfobase) / BLOCKSIZE + 1) 33 | 34 | #define ADDRESS(B) ((void *) (((B) - 1) * BLOCKSIZE + mdp -> mblkinfobase)) 35 | 36 | #ifndef HAVE_MEMMOVE 37 | # undef memmove 38 | # define memmove(dst,src,len) bcopy(src,dst,len) 39 | #endif 40 | 41 | #define INITMPOOLSIZE (INT_BIT > 16 ? 4 * 1024 * 1024 : 64 * 1024) 42 | 43 | void rebase_mdesc_infos(struct mdesc * mdp, void *e_addr, void *o_addr); 44 | 45 | struct mdesc *reuse_mempool(int); 46 | 47 | int initialize(struct mdesc *); 48 | 49 | void *morespace(struct mdesc *, size_t); 50 | 51 | void *align(struct mdesc *, size_t); 52 | 53 | void *allocate_blockfrag(struct mdesc *mdp, size_t size); 54 | 55 | void *allocate_blocks(struct mdesc *mdp, size_t blocks); 56 | 57 | void free_blocks(struct mdesc *mdp, size_t block); 58 | 59 | void free_blockfrag(struct mdesc *mdp, size_t block, int fraglog, void *addr); 60 | 61 | #endif /* PMFUNCTION_H */ 62 | -------------------------------------------------------------------------------- /perf/struct_objs_write.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | #define PM_CAPACITY 1024LL * 1024 * 1024 * 10 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | size_t emp_count = 0; 8 | 9 | if (argc != 3) { 10 | printf("Usage: %s filename deep", argv[0]); 11 | exit(-1); 12 | } 13 | 14 | char *fn = argv[1]; 15 | int deep = atoi(argv[2]); 16 | 17 | assert(NULL != fn); 18 | assert(deep > 0); 19 | 20 | printf("Start the example writing struct objects into %s with deep %d. \n", fn, deep); 21 | 22 | int fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); 23 | if(fd < 0) { 24 | printf(ANSI_COLOR_RED "Open data file failure." ANSI_COLOR_RESET); 25 | return 1; 26 | } 27 | 28 | void *md = pmalloc_attach(fd, NULL, PM_CAPACITY); 29 | assert(NULL != md); 30 | 31 | printf("Seed is %u \n", init_random(0)); 32 | 33 | init_roles(md); 34 | 35 | struct employee_t* emp_root = NULL; 36 | 37 | size_t ecnt; 38 | 39 | int cidx; 40 | for (cidx = COMPANY_MIN_INDEX; cidx <= COMPANY_MAX_INDEX; ++cidx) { 41 | emp_root = NULL; 42 | ecnt = gen_employees(md, &emp_root, deep); 43 | emp_count += ecnt; 44 | alloc_result(emp_root); 45 | pmalloc_setkey(md, cidx, emp_root); 46 | printf(ANSI_COLOR_GREEN "Generated %zx employees for company %d. \n" ANSI_COLOR_RESET, 47 | emp_count, cidx); 48 | } 49 | 50 | printf(ANSI_COLOR_BLUE "Generated %zx employees totally. \n" ANSI_COLOR_RESET, emp_count); 51 | 52 | for (cidx = COMPANY_MIN_INDEX; cidx <= COMPANY_MAX_INDEX; ++cidx) { 53 | printf(ANSI_COLOR_GREEN "Show company %d. \n" ANSI_COLOR_RESET, cidx); 54 | emp_root = pmalloc_getkey(md, cidx); 55 | if (NULL != emp_root) { 56 | print_employees(md, emp_root, 0); 57 | } 58 | } 59 | 60 | pmalloc_detach(md); 61 | close(fd); 62 | printf("PM Closed.\n"); 63 | return 0; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/pmalloc.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persist Memory allocator 3 | *****************************************************************************************/ 4 | 5 | #ifndef PMALLOC_H 6 | #define PMALLOC_H 1 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define PMALLOC_MIN_POOL_SIZE ((size_t)(1024 * 1024 * 16)) /* min pool size: 16MB */ 21 | 22 | #define PMALLOC_KEYS 255 23 | 24 | extern void *pmopen(const char *fn, void *baseaddr, size_t initial_size); 25 | 26 | extern void pmclose(void* md); 27 | 28 | extern long pmcapacity(void* md); 29 | 30 | extern void * pmalloc(void *, size_t); 31 | 32 | extern void * pmalloc_check(void *, size_t, void *); 33 | 34 | extern void * pmrealloc(void *, void *, size_t); 35 | 36 | extern void * pmrealloc_check(void *, void *, size_t, void *); 37 | 38 | extern void * pmcalloc(void *, size_t, size_t); 39 | 40 | extern void * pmcalloc_check(void *, size_t, size_t, void *); 41 | 42 | extern void pmfree(void *, void *); 43 | 44 | extern void pmfree_check(void *, void *, void *); 45 | 46 | extern void * pmalign(void *, size_t, size_t); 47 | 48 | extern void * pmvalloc(void *, size_t); 49 | 50 | extern void pmcheck(void *, void (*)(void *, void *, int)); 51 | 52 | extern struct mempoolstats pmstats(void *); 53 | 54 | extern void * pmalloc_attach(int, void *, size_t); 55 | 56 | extern void * pmalloc_detach(void *); 57 | 58 | extern int pmalloc_setkey(void *, int, void *); 59 | 60 | extern void * pmalloc_getkey(void *, int); 61 | 62 | extern int pmalloc_errno(void *); 63 | 64 | extern int pmtrace(void); 65 | 66 | extern int pmsync(void *, void *, size_t); 67 | 68 | extern void * p_addr(void *, void *); 69 | 70 | extern void * e_addr(void *, void *); 71 | 72 | extern void * b_addr(void *); 73 | 74 | #endif /* PMALLOC_H */ 75 | -------------------------------------------------------------------------------- /CMakeModules/FindCheck.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the CHECK libraries 2 | # Once done this will define 3 | # 4 | # CHECK_FOUND - system has check 5 | # CHECK_INCLUDE_DIRS - the check include directory 6 | # CHECK_LIBRARIES - check library 7 | # 8 | # Copyright (c) 2007 Daniel Gollub 9 | # Copyright (c) 2007-2009 Bjoern Ricks 10 | # 11 | # Redistribution and use is allowed according to the terms of the New 12 | # BSD license. 13 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 14 | 15 | 16 | INCLUDE( FindPkgConfig ) 17 | 18 | IF ( Check_FIND_REQUIRED ) 19 | SET( _pkgconfig_REQUIRED "REQUIRED" ) 20 | ELSE( Check_FIND_REQUIRED ) 21 | SET( _pkgconfig_REQUIRED "" ) 22 | ENDIF ( Check_FIND_REQUIRED ) 23 | 24 | IF ( CHECK_MIN_VERSION ) 25 | PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check>=${CHECK_MIN_VERSION} ) 26 | ELSE ( CHECK_MIN_VERSION ) 27 | PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check ) 28 | ENDIF ( CHECK_MIN_VERSION ) 29 | 30 | # Look for CHECK include dir and libraries 31 | IF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND ) 32 | 33 | FIND_PATH( CHECK_INCLUDE_DIRS check.h ) 34 | 35 | FIND_LIBRARY( CHECK_LIBRARIES NAMES check ) 36 | 37 | IF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES ) 38 | SET( CHECK_FOUND 1 ) 39 | IF ( NOT Check_FIND_QUIETLY ) 40 | MESSAGE ( STATUS "Found CHECK: ${CHECK_LIBRARIES}" ) 41 | ENDIF ( NOT Check_FIND_QUIETLY ) 42 | ELSE ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES ) 43 | IF ( Check_FIND_REQUIRED ) 44 | MESSAGE( FATAL_ERROR "Could NOT find CHECK" ) 45 | ELSE ( Check_FIND_REQUIRED ) 46 | IF ( NOT Check_FIND_QUIETLY ) 47 | MESSAGE( STATUS "Could NOT find CHECK" ) 48 | ENDIF ( NOT Check_FIND_QUIETLY ) 49 | ENDIF ( Check_FIND_REQUIRED ) 50 | ENDIF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES ) 51 | ENDIF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND ) 52 | 53 | # Hide advanced variables from CMake GUIs 54 | MARK_AS_ADVANCED( CHECK_INCLUDE_DIRS CHECK_LIBRARIES ) 55 | 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A portable persistent memory allocation library. 2 | 3 | ### Features: 4 | * Optimized memory layout arrangement 5 | * persistent key-value pair storage (fixed length) 6 | * portable address support 7 | * in-place structured data persistence 8 | 9 | ### How to use it ? 10 | #### setup a memory descriptor for persistent memory pool 11 | ```c 12 | /* attache to a file hander */ 13 | void *md = pmalloc_attach(fd, NULL, PM_CAPACITY); 14 | /* capture error */ 15 | assert(NULL != md); 16 | .... 17 | /* close it */ 18 | pmalloc_detach(md); 19 | ``` 20 | 21 | #### manipulate persistent memory blocks 22 | ```c 23 | for (i = 0; i < 16; ++i) 24 | { 25 | /* fetch persistent key values */ 26 | key = pmalloc_getkey(md, i); 27 | if (NULL != key) 28 | printf("Prekey... %p --> %s %lu\n", key, (char*)key, sizeof(size_t)); 29 | else break; 30 | } 31 | ... 32 | /* allocate a memory block with specified size */ 33 | void *data = pmalloc(md, 0x1000 * 5); 34 | if (NULL != data) { 35 | sprintf(data, "output data row %d", i); 36 | /* put it on key-value pair store */ 37 | pmalloc_setkey(md, i, data); 38 | } 39 | ... 40 | /* retrieve a persisted memory block from key-value pair store with a specified key */ 41 | keydata = pmalloc_getkey(md, keyidx); 42 | if (NULL != keydata) { 43 | /* free up an allocated block 44 | pmfree(md, keydata); 45 | pmalloc_setkey(md, keyidx, NULL); 46 | printf(ANSI_COLOR_GREEN "Released original key data at %p! \n" ANSI_COLOR_RESET, keydata); 47 | } else 48 | printf(ANSI_COLOR_CYAN "No original key data set in this key slot! \n" ANSI_COLOR_RESET); 49 | ``` 50 | 51 | ### How to Build it ? 52 | ##### Please install the following check module first for unit test compiling.
http://libcheck.github.io/check/web/install.html 53 | ```sh 54 | $ mkdir build 55 | $ cd build 56 | $ cmake .. 57 | $ make 58 | $ sudo make install 59 | ``` 60 | 61 | ### How to package it ? 62 | ```sh 63 | $ cd build 64 | $ cpack -C CPackConfig.cmake 65 | ``` 66 | -------------------------------------------------------------------------------- /src/pmmap.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Support for functions that uses mmap. 3 | 4 | *****************************************************************************************/ 5 | 6 | #include "pmfunction.h" 7 | #include "pminternal.h" 8 | 9 | static size_t pagesize = 0; 10 | 11 | #define PAGE_ALIGN(addr) \ 12 | (void *) (((long)(addr) + pagesize - 1) & ~(pagesize - 1)) 13 | 14 | void * __pmalloc_map_morespace(struct mdesc *mdp, ptrdiff_t size) { 15 | void * result = NULL; 16 | /* off_t foffset; */ 17 | size_t mapbytes; 18 | void *moveto; 19 | void *mapto; 20 | char buf = 0; 21 | 22 | if (pagesize == 0) { 23 | pagesize = getpagesize(); 24 | } 25 | if (size == 0) { 26 | result = mdp->watermarkpos; 27 | } else if (size < 0) { 28 | if (mdp->watermarkpos + size >= mdp->mempoolbase) { 29 | result = (void *) mdp->watermarkpos; 30 | mdp->watermarkpos += size; 31 | } 32 | } else { 33 | if (mdp->watermarkpos + size > mdp->limitpos) { 34 | if (0 == mdp->limitpos) { /*Initial memory pool*/ 35 | assert(mdp->watermarkpos == 0); 36 | moveto = PAGE_ALIGN(size); 37 | mapbytes = (size_t) moveto; 38 | 39 | if (!(mdp->flags & (PMALLOC_DEVZERO | PMALLOC_ANON))) { 40 | lseek(mdp->mappingfd, mapbytes - 1, SEEK_SET); 41 | if (write(mdp->mappingfd, &buf, 1) != 1) 42 | return NULL; 43 | } 44 | mapto = mmap(NULL, mapbytes, PROT_READ | PROT_WRITE, 45 | MAP_SHARED, mdp->mappingfd, 0); 46 | if (mapto != MAP_FAILED) /* initial */ 47 | { 48 | mdp->mempoolbase = mdp->watermarkpos = result = mapto; 49 | mdp->watermarkpos += size; 50 | mdp->limitpos = PAGE_ALIGN(mdp->watermarkpos); 51 | } 52 | } 53 | } else { 54 | result = (void *) mdp->watermarkpos; 55 | mdp->watermarkpos += size; 56 | } 57 | } 58 | return (result); 59 | } 60 | 61 | void * __pmalloc_remap_mempool(struct mdesc *mdp) { 62 | void* base; 63 | 64 | base = mmap(mdp->mempoolbase, (size_t) (mdp->limitpos - mdp->mempoolbase), 65 | PROT_READ | PROT_WRITE, MAP_SHARED, mdp->mappingfd, 0); 66 | if (base == MAP_FAILED) { 67 | fprintf(stderr, "Mapping ERROR:(%d) %s \n", errno, strerror(errno)); 68 | } 69 | return base; 70 | } 71 | -------------------------------------------------------------------------------- /tests/check_pmrecycle.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persistent Memory Library Tests 3 | 4 | *****************************************************************************************/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "pmalloc.h" 10 | #include "check_common.h" 11 | 12 | #define LEAK_SLOTS 1 13 | #define USE_SLOTS 2 14 | 15 | #define PM_CAPACITY 1024LL * 1024 * 1024 * 10 16 | 17 | int main() 18 | { 19 | printf("Start checking test using %d leak slots\n", LEAK_SLOTS); 20 | //srand(time(NULL)); 21 | init_random(); 22 | int fd = open("pmrecycle_ds.dat", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); 23 | if(fd < 0) { 24 | printf(ANSI_COLOR_RED "Open test data file failure." ANSI_COLOR_RESET); 25 | return 1; 26 | } 27 | 28 | void *md = pmalloc_attach(fd, NULL, PM_CAPACITY); 29 | 30 | long keyidx = -1; 31 | 32 | size_t sz; 33 | 34 | void *data = NULL, *keydata = NULL; 35 | 36 | do { 37 | keyidx = random_number(0, USE_SLOTS - 1 + LEAK_SLOTS); 38 | printf("key index is %ld, ", keyidx); 39 | 40 | if (keyidx < USE_SLOTS) { 41 | keydata = pmalloc_getkey(md, keyidx); 42 | if (NULL != keydata) { 43 | pmfree(md, keydata); 44 | pmalloc_setkey(md, keyidx, NULL); 45 | printf(ANSI_COLOR_GREEN "Released original key data at %p! \n" ANSI_COLOR_RESET, keydata); 46 | } else 47 | printf(ANSI_COLOR_CYAN "No original key data set in this key slot! \n" ANSI_COLOR_RESET); 48 | } else 49 | printf(ANSI_COLOR_MAGENTA "out of range! \n" ANSI_COLOR_RESET); 50 | 51 | sz = random_number(1, PM_CAPACITY / 3); //sz = sz < 0x4000 ? 0x4000 : sz; 52 | 53 | data = pmalloc(md, sz); 54 | 55 | if (NULL != data) 56 | printf(ANSI_COLOR_BLUE "Allocated a pm block size %zx in %p \n" ANSI_COLOR_RESET, sz, data); 57 | else 58 | break; 59 | 60 | pmalloc_setkey(md, keyidx, data); 61 | 62 | }while(1); 63 | 64 | pmalloc_detach(md); 65 | close(fd); 66 | printf("PM Closed.\n"); 67 | return 0; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/pmrealloc.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | 3 | *****************************************************************************************/ 4 | 5 | #include "pmfunction.h" 6 | #include "pminternal.h" 7 | 8 | void *pmrealloc(void *md, void *ptr, size_t size) { 9 | struct mdesc *mdp = (struct mdesc *) md; 10 | void * result; 11 | int type; 12 | size_t block, blocks, oldlimit; 13 | 14 | if (size == 0) { 15 | if (ptr == NULL) 16 | return NULL; 17 | pmfree(md, ptr); 18 | return (pmalloc(md, 0)); 19 | } else if (ptr == NULL) { 20 | return (pmalloc(md, size)); 21 | } 22 | 23 | block = BLOCK(ptr); 24 | 25 | type = mdp->mblkinfo[block].inuse.fragtype; 26 | switch (type) { 27 | case 0: 28 | if (size <= BLOCKSIZE / 2) { 29 | result = pmalloc(md, size); 30 | if (result != NULL) { 31 | memcpy(result, ptr, size); 32 | pmfree(md, ptr); 33 | return (result); 34 | } 35 | } 36 | 37 | blocks = BLOCKIFY(size); 38 | if (blocks < mdp->mblkinfo[block].inuse.info.sizeinblock) { 39 | mdp->mblkinfo[block + blocks].inuse.fragtype = 0; 40 | mdp->mblkinfo[block + blocks].inuse.info.sizeinblock = 41 | mdp->mblkinfo[block].inuse.info.sizeinblock - blocks; 42 | mdp->mblkinfo[block].inuse.info.sizeinblock = blocks; 43 | pmfree(md, ADDRESS(block + blocks)); 44 | result = ptr; 45 | } else if (blocks == mdp->mblkinfo[block].inuse.info.sizeinblock) { 46 | result = ptr; 47 | } else { 48 | blocks = mdp->mblkinfo[block].inuse.info.sizeinblock; 49 | oldlimit = mdp->mblkinfoidxlimit; 50 | mdp->mblkinfoidxlimit = 0; 51 | pmfree(md, ptr); 52 | mdp->mblkinfoidxlimit = oldlimit; 53 | result = pmalloc(md, size); 54 | if (result == NULL) { 55 | pmalloc(md, blocks * BLOCKSIZE); 56 | return (NULL); 57 | } 58 | if (ptr != result) { 59 | memmove(result, ptr, blocks * BLOCKSIZE); 60 | } 61 | } 62 | break; 63 | 64 | default: 65 | if (size > (size_t) (1 << (type - 1)) && size <= (size_t) (1 << type)) { 66 | result = ptr; 67 | } else { 68 | result = pmalloc(md, size); 69 | if (result == NULL) { 70 | return (NULL); 71 | } 72 | memcpy(result, ptr, MIN(size, (size_t ) 1 << type)); 73 | pmfree(md, ptr); 74 | } 75 | break; 76 | } 77 | 78 | return (result); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /tests/check_pmsimulate.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persistent Memory Library Tests 3 | 4 | *****************************************************************************************/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "pmalloc.h" 10 | #include "check_common.h" 11 | 12 | #define PM_CAPACITY 1024LL * 1024 * 1024 * 10 13 | #define PM_MAX_ALLOCSIZE 1024LL * 20 //1024 * 200 14 | #define PM_MIN_ALLOCSIZE 1LL 15 | #define MAX_FREE_COUNT PMALLOC_KEYS 16 | #define MAX_ALLOC_COUNT 200 17 | #define SIMULATE_COUNT 10000 18 | 19 | int main() 20 | { 21 | printf("Start checking test simulate %d times in max block size %lld . \n", SIMULATE_COUNT, PM_MAX_ALLOCSIZE); 22 | int fd = open("pmsimulate_ds.dat", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); 23 | if(fd < 0) { 24 | printf(ANSI_COLOR_RED "Open test data file failure." ANSI_COLOR_RESET); 25 | return 1; 26 | } 27 | 28 | void *md = pmalloc_attach(fd, NULL, PM_CAPACITY); 29 | assert(NULL != md); 30 | 31 | init_random(); 32 | 33 | void *data; 34 | size_t sz; 35 | long simcnt, i, alloccnt, freecnt, cnt, maxalloccnt, maxfreecnt; 36 | for (simcnt = 0; simcnt < SIMULATE_COUNT; ++simcnt) { 37 | cnt = 0; 38 | maxalloccnt = random_number(1, MAX_ALLOC_COUNT); 39 | for (alloccnt = 0; alloccnt < maxalloccnt; ++alloccnt) { 40 | for(i = 0; i < PMALLOC_KEYS; ++i) if (NULL == pmalloc_getkey(md, i)) break; 41 | if (i < PMALLOC_KEYS) { 42 | sz = random_number(PM_MIN_ALLOCSIZE, PM_MAX_ALLOCSIZE); 43 | data = pmalloc(md, sz); 44 | if (NULL == data) break; 45 | pmalloc_setkey(md, i, data); 46 | ++cnt; 47 | printf(ANSI_COLOR_BLUE "(Size %zx) Allocated data at %p with key %ld \n" ANSI_COLOR_RESET, sz, data, i); 48 | } else break; 49 | } 50 | printf(ANSI_COLOR_MAGENTA "Allocated %ld memory blocks \n" ANSI_COLOR_RESET, cnt); 51 | 52 | cnt = 0; 53 | maxfreecnt = random_number(1, MAX_FREE_COUNT); 54 | for (freecnt = 0; freecnt < maxfreecnt; ++freecnt) { 55 | i = random_number(0, PMALLOC_KEYS); 56 | if(free_keydata(md, i) == 0) ++cnt; 57 | } 58 | printf(ANSI_COLOR_MAGENTA "Freed %ld memory blocks \n" ANSI_COLOR_RESET, cnt); 59 | } 60 | 61 | pmalloc_detach(md); 62 | close(fd); 63 | printf("PM Closed.\n"); 64 | return 0; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /src/pminternal.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Declare all pmalloc related functions 3 | 4 | *****************************************************************************************/ 5 | 6 | #ifndef __PMINTERNAL_H 7 | #define __PMINTERNAL_H 1 8 | 9 | #include "pmalloc.h" 10 | 11 | #define PMALLOC_MAGIC "pmalloc_bigdata1" 12 | #define PMALLOC_MAGIC_SIZE 32 13 | #define PMALLOC_VERSION 2 14 | 15 | #define INT_BIT (CHAR_BIT * sizeof(int)) 16 | 17 | #define BLOCKLOG (INT_BIT > 16 ? 12 : 9) 18 | 19 | #define FINAL_FREE_BLOCKS 8 20 | 21 | #define MALLOC_SEARCH_START mdp -> mblkinfosearchindex 22 | 23 | typedef union { 24 | struct { 25 | int fragtype; 26 | union { 27 | struct { 28 | size_t nfreefrags; 29 | size_t firstfragidxinlist; 30 | } frag; 31 | size_t sizeinblock; 32 | } info; 33 | } inuse; 34 | struct { 35 | size_t size; 36 | size_t next; 37 | size_t prev; 38 | } free; 39 | } malloc_info; 40 | 41 | struct alignlist { 42 | struct alignlist *next; 43 | void *alignedaddr; 44 | void *unalignedaddr; 45 | }; 46 | 47 | struct list { 48 | struct list *next; 49 | struct list *prev; 50 | }; 51 | 52 | struct mempoolstats { 53 | size_t bytes_total; 54 | size_t chunks_used; 55 | size_t bytes_used; 56 | size_t chunks_free; 57 | size_t bytes_free; 58 | }; 59 | 60 | struct mdesc { 61 | char magicwords[PMALLOC_MAGIC_SIZE]; 62 | 63 | unsigned int headersize; 64 | 65 | unsigned char version; 66 | 67 | unsigned int flags; 68 | 69 | int saved_errno; 70 | 71 | void * (*morespace)(struct mdesc *, ptrdiff_t); 72 | 73 | void (*abortfunc)(void *, void *, int); 74 | 75 | size_t mblkinfosize; 76 | 77 | char *mblkinfobase; 78 | 79 | size_t mblkinfosearchindex; 80 | 81 | size_t mblkinfoidxlimit; 82 | 83 | malloc_info *mblkinfo; 84 | 85 | struct mempoolstats mblkstats; 86 | 87 | struct list fragblockhead[BLOCKLOG]; 88 | 89 | struct alignlist *aligned_blocks; 90 | 91 | char *mempoolbase; 92 | 93 | char *watermarkpos; 94 | 95 | char *limitpos; 96 | 97 | int mappingfd; 98 | 99 | void *persistkeys[PMALLOC_KEYS]; 100 | 101 | }; 102 | 103 | extern void __pmalloc_free(struct mdesc *, void *); 104 | 105 | extern struct mdesc *__pmalloc_default_mdp; 106 | 107 | extern void * __pmalloc_map_morespace(struct mdesc *, ptrdiff_t); 108 | 109 | extern void * __pmalloc_remap_mempool(struct mdesc *); 110 | 111 | extern void * pmalloc_attach(int, void *, size_t); 112 | 113 | extern void * pmalloc_detach(void *); 114 | 115 | extern void rebase_mdesc_infos(struct mdesc *, void *, void *); 116 | 117 | #endif /* __PMINTERNAL_H */ 118 | -------------------------------------------------------------------------------- /tests/check_pmclear.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persistent Memory Library Tests 3 | 4 | *****************************************************************************************/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "pmalloc.h" 10 | #include "check_common.h" 11 | 12 | #define PM_CAPACITY 1024LL * 1024 * 1024 * 10 13 | #define PM_MAX_ALLOCSIZE 1024LL * 1024 * 1024 * 8 14 | 15 | int main() 16 | { 17 | printf("Start checking test in block size %lld . \n", PM_MAX_ALLOCSIZE); 18 | int fd = open("pmclear_ds.dat", O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); 19 | if(fd < 0) { 20 | printf(ANSI_COLOR_RED "Open test data file failure." ANSI_COLOR_RESET); 21 | return 1; 22 | } 23 | 24 | void *md = pmalloc_attach(fd, NULL, PM_CAPACITY); 25 | 26 | init_random(); 27 | 28 | size_t sz = 0, cntsz = number_binary_length(PM_MAX_ALLOCSIZE), fcount, i; 29 | 30 | size_t counters[cntsz]; 31 | 32 | long fpattern[PMALLOC_KEYS]; 33 | 34 | int quitflag = 0; 35 | 36 | for(i = 0; i < cntsz; ++i) counters[i] = -1; 37 | 38 | for ( sz = 1; sz <= PM_MAX_ALLOCSIZE && !quitflag; sz *= 2) { 39 | gen_pattern(fpattern, PMALLOC_KEYS, 2); 40 | clear_keydata(md, fpattern, PMALLOC_KEYS); 41 | fcount = refill_keydata(md, sz); 42 | counters[number_binary_length(sz) - 1] = fcount; 43 | //system( "read -n 1 -s -p \"Press any key to continue...\"; echo" ); 44 | } 45 | for ( sz = 1; sz <= PM_MAX_ALLOCSIZE && !quitflag; sz *= 2) { 46 | gen_pattern(fpattern, PMALLOC_KEYS, 0); 47 | clear_keydata(md, fpattern, PMALLOC_KEYS); 48 | fcount = refill_keydata(md, sz); 49 | if (counters[number_binary_length(sz) - 1] != fcount) { 50 | printf(ANSI_COLOR_RED "Fill count error! %zx <> %zx \n" ANSI_COLOR_RESET, 51 | counters[number_binary_length(sz)], fcount); 52 | quitflag = 1; 53 | break; 54 | } 55 | //system( "read -n 1 -s -p \"Press any key to continue...\"; echo" ); 56 | } 57 | 58 | for ( sz = PM_MAX_ALLOCSIZE; sz > 0 && !quitflag; sz /= 2) { 59 | gen_pattern(fpattern, PMALLOC_KEYS, 2); 60 | clear_keydata(md, fpattern, PMALLOC_KEYS); 61 | fcount = refill_keydata(md, sz); 62 | if (counters[number_binary_length(sz) - 1] != fcount) { 63 | printf(ANSI_COLOR_RED "Fill count error! %zx <> %zx \n" ANSI_COLOR_RESET, 64 | counters[number_binary_length(sz)], fcount); 65 | quitflag = 1; 66 | break; 67 | } 68 | //system( "read -n 1 -s -p \"Press any key to continue...\"; echo" ); 69 | } 70 | for ( sz = PM_MAX_ALLOCSIZE; sz > 0 && !quitflag; sz /= 2) { 71 | gen_pattern(fpattern, PMALLOC_KEYS, 1); 72 | clear_keydata(md, fpattern, PMALLOC_KEYS); 73 | fcount = refill_keydata(md, sz); 74 | if (counters[number_binary_length(sz) - 1] != fcount) { 75 | printf(ANSI_COLOR_RED "Fill count error! %zx <> %zx \n" ANSI_COLOR_RESET, 76 | counters[number_binary_length(sz)], fcount); 77 | quitflag = 1; 78 | break; 79 | } 80 | //system( "read -n 1 -s -p \"Press any key to continue...\"; echo" ); 81 | } 82 | 83 | pmalloc_detach(md); 84 | close(fd); 85 | printf("PM Closed.\n"); 86 | return quitflag; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /src/pmcheck.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Debugging for pmalloc. 3 | 4 | *****************************************************************************************/ 5 | 6 | #include "pmfunction.h" 7 | #include "pminternal.h" 8 | 9 | extern void abort(void); 10 | 11 | #define MAGICWORD (unsigned int) 0xd4c2afe9 12 | #define MAGICWORDFREE (unsigned int) 0xff04feca 13 | #define MAGICBYTE ((char) 0xd7) 14 | 15 | struct hdr { 16 | union { 17 | void *desc; 18 | char pad[8]; 19 | } u; 20 | unsigned int size; 21 | unsigned int magic; 22 | }; 23 | 24 | static void checkhdr(struct mdesc *mdp, const struct hdr *hdr) { 25 | if (hdr->magic == MAGICWORDFREE) { 26 | (*mdp->abortfunc)((void*) (&hdr[1]), hdr->u.desc, -1); 27 | } else if (hdr->magic != MAGICWORD) { 28 | (*mdp->abortfunc)((void*) (&hdr[1]), hdr->u.desc, 0); 29 | } else if (((char*) &hdr[1])[hdr->size] != MAGICBYTE) { 30 | (*mdp->abortfunc)((void *) (&hdr[1]), hdr->u.desc, 1); 31 | } 32 | } 33 | 34 | void pmfree_check(void * md, void *ptr, void *desc) { 35 | struct hdr *hdr = ((struct hdr *) ptr) - 1; 36 | struct mdesc *mdp = (struct mdesc *) md; 37 | 38 | checkhdr(mdp, hdr); 39 | hdr->magic = MAGICWORDFREE; 40 | pmfree(md, (void *) hdr); 41 | } 42 | 43 | void *pmalloc_check(void *md, size_t size, void *desc) { 44 | struct hdr *hdr; 45 | /* struct mdesc *mdp = (struct mdesc *) md; */ 46 | size_t nbytes; 47 | 48 | nbytes = sizeof(struct hdr) + size + 1; 49 | hdr = (struct hdr *) pmalloc(md, nbytes); 50 | if (hdr != NULL) { 51 | hdr->size = size; 52 | hdr->u.desc = desc; 53 | hdr->magic = MAGICWORD; 54 | hdr++; 55 | *((char *) hdr + size) = MAGICBYTE; 56 | } 57 | return ((void *) hdr); 58 | } 59 | 60 | void *pmcalloc_check(void *md, size_t num, size_t size, void *desc) { 61 | register void * result; 62 | if ((result = pmalloc_check(md, num * size, desc)) != NULL) { 63 | bzero(result, num * size); 64 | } 65 | return (result); 66 | } 67 | 68 | void *pmrealloc_check(void *md, void *ptr, size_t size, void *desc) { 69 | struct hdr *hdr; 70 | struct mdesc *mdp = (struct mdesc *) md; 71 | size_t nbytes; 72 | 73 | if (ptr == NULL) 74 | return pmalloc_check(md, size, desc); 75 | hdr = ((struct hdr *) ptr) - 1; 76 | checkhdr(mdp, hdr); 77 | nbytes = sizeof(struct hdr) + size + 1; 78 | hdr = (struct hdr *) pmrealloc(md, (void *) hdr, nbytes); 79 | if (hdr != NULL) { 80 | hdr->size = size; 81 | hdr->u.desc = desc; 82 | hdr++; 83 | *((char *) hdr + size) = MAGICBYTE; 84 | } 85 | return ((void *) hdr); 86 | } 87 | 88 | static void default_abort(void *p, void *desc, int overflow) { 89 | abort(); 90 | } 91 | 92 | void pmcheck(void *md, void (*func)(void *, void *, int)) { 93 | struct mdesc *mdp = (struct mdesc *) md; 94 | 95 | mdp->abortfunc = (func != NULL ? func : default_abort); 96 | mdp->flags |= PMALLOC_PMCHECK_USED; 97 | } 98 | 99 | int check_heap_free_info(struct mdesc *md) { 100 | int ret = 0; 101 | size_t start, current, next; 102 | struct mdesc *mdp = md; 103 | fprintf(stderr, "\n"); 104 | 105 | start = current = MALLOC_SEARCH_START; 106 | do { 107 | next = mdp->mblkinfo[current].free.next; 108 | 109 | if (mdp->mblkinfo[next].free.prev != current) { 110 | fprintf(stderr, "CURRENT->NEXT->prev IS NOT CURRENT !!! \n"); 111 | ret = -1; 112 | break; 113 | } 114 | 115 | if (next == start) 116 | break; 117 | 118 | current = next; 119 | 120 | fprintf(stderr, "."); 121 | } while (1); 122 | 123 | fprintf(stderr, "\n"); 124 | return ret; 125 | } 126 | 127 | -------------------------------------------------------------------------------- /tests/check_common.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persistent Memory Library Tests 3 | 4 | *****************************************************************************************/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "pmalloc.h" 10 | #include "check_common.h" 11 | 12 | #ifdef __MACH__ 13 | #include 14 | #include 15 | #endif 16 | 17 | void init_random() 18 | { 19 | struct timespec ts; 20 | #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time 21 | clock_serv_t cclock; 22 | mach_timespec_t mts; 23 | host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); 24 | clock_get_time(cclock, &mts); 25 | mach_port_deallocate(mach_task_self(), cclock); 26 | ts.tv_sec = mts.tv_sec; 27 | ts.tv_nsec = mts.tv_nsec; 28 | #else 29 | clock_gettime(CLOCK_MONOTONIC, &ts); 30 | #endif 31 | srand((unsigned)ts.tv_nsec); 32 | } 33 | 34 | size_t random_number(size_t min_num, size_t max_num) 35 | { 36 | size_t result=0,low_num=0,hi_num=0; 37 | if(min_num> 1; 54 | ++ret; 55 | } 56 | return ret; 57 | } 58 | 59 | int free_keydata(void *md, long keyidx) 60 | { 61 | int ret = -1; 62 | void *keydata = pmalloc_getkey(md, keyidx); 63 | if (NULL != keydata) { 64 | pmfree(md, keydata); 65 | pmalloc_setkey(md, keyidx, NULL); 66 | printf(ANSI_COLOR_GREEN "Released original key data at %p with key %ld \n" ANSI_COLOR_RESET, keydata, keyidx); 67 | ret = 0; 68 | } 69 | return ret; 70 | } 71 | 72 | 73 | void clear_keydata(void *md, long pattern[], size_t count) 74 | { 75 | long keyidx = 0; 76 | 77 | for ( keyidx = 0; keyidx < count; ++keyidx) { 78 | free_keydata(md, keyidx); 79 | } 80 | } 81 | 82 | void gen_pattern(long pattern[], size_t count, int mode) 83 | { 84 | size_t idx; 85 | long val; 86 | switch (mode) 87 | { 88 | case 0: 89 | for ( idx = 0; idx < count; ++idx) pattern[idx] = (long)idx; 90 | break; 91 | case 1: 92 | val = 0; 93 | idx = count - 1; 94 | do { 95 | pattern[idx--] = val++; 96 | }while (idx != 0); //siz_t must be great or equal to zero 97 | break; 98 | case 2: 99 | for ( idx = 0; idx < count; ++idx) pattern[idx] = (long)idx; 100 | size_t swapidx; 101 | init_random(); 102 | for ( idx = 0; idx < count; ++idx) { 103 | swapidx = random_number(0, count); 104 | if (swapidx != idx) { 105 | val = pattern[idx]; 106 | pattern[idx] = pattern[swapidx]; 107 | pattern[swapidx] = val; 108 | } 109 | } 110 | break; 111 | default: 112 | ; 113 | } 114 | printf(ANSI_COLOR_CYAN "Free Pattern: " ANSI_COLOR_RESET); 115 | for( idx = 0; idx < count; ++idx) printf("%ld,",pattern[idx]); 116 | printf("\n" ANSI_COLOR_RESET); 117 | } 118 | 119 | size_t refill_keydata(void *md, size_t sz) 120 | { 121 | size_t fillcount = 0; 122 | 123 | long keyidx = 0; 124 | 125 | void *data = NULL; 126 | 127 | printf(ANSI_COLOR_CYAN "Set allocation size as %zx! \n" ANSI_COLOR_RESET, sz); 128 | 129 | for ( keyidx = 0; keyidx < PMALLOC_KEYS; ++keyidx) { 130 | data = pmalloc(md, sz); 131 | if (NULL != data) { 132 | pmalloc_setkey(md, keyidx, data); 133 | printf(ANSI_COLOR_BLUE "(Size %zx) Allocated data at %p with key %ld \n" ANSI_COLOR_RESET, sz, data, keyidx); 134 | ++fillcount; 135 | } else { 136 | printf(ANSI_COLOR_CYAN "Filled it up !!! \n" ANSI_COLOR_RESET); 137 | break; 138 | } 139 | } 140 | return fillcount; 141 | } 142 | -------------------------------------------------------------------------------- /perf/common.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persistent Memory Library Example 3 | 4 | *****************************************************************************************/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "pmalloc.h" 10 | #include "common.h" 11 | 12 | #ifdef __MACH__ 13 | #include 14 | #include 15 | #endif 16 | 17 | char **g_roles = NULL; 18 | 19 | unsigned int init_random(unsigned int seed) 20 | { 21 | unsigned int ret = seed; 22 | if (0 == seed) { 23 | struct timespec ts; 24 | #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time 25 | clock_serv_t cclock; 26 | mach_timespec_t mts; 27 | host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); 28 | clock_get_time(cclock, &mts); 29 | mach_port_deallocate(mach_task_self(), cclock); 30 | ts.tv_sec = mts.tv_sec; 31 | ts.tv_nsec = mts.tv_nsec; 32 | #else 33 | clock_gettime(CLOCK_MONOTONIC, &ts); 34 | #endif 35 | ret = (unsigned)ts.tv_nsec; 36 | } 37 | srand(ret); 38 | return ret; 39 | } 40 | 41 | size_t random_number(size_t min_num, size_t max_num) 42 | { 43 | size_t result=0,low_num=0,hi_num=0; 44 | if(min_num> 1; 61 | ++ret; 62 | } 63 | return ret; 64 | } 65 | 66 | int free_keydata(void *md, long keyidx) 67 | { 68 | int ret = -1; 69 | void *keydata = pmalloc_getkey(md, keyidx); 70 | if (NULL != keydata) { 71 | pmfree(md, keydata); 72 | pmalloc_setkey(md, keyidx, NULL); 73 | printf(ANSI_COLOR_GREEN "Released original key data at %p with key %ld \n" ANSI_COLOR_RESET, keydata, keyidx); 74 | ret = 0; 75 | } 76 | return ret; 77 | } 78 | 79 | 80 | void clear_keydata(void *md, long pattern[], size_t count) 81 | { 82 | long keyidx = 0; 83 | 84 | for ( keyidx = 0; keyidx < count; ++keyidx) { 85 | free_keydata(md, keyidx); 86 | } 87 | } 88 | 89 | void gen_pattern(long pattern[], size_t count, int mode) 90 | { 91 | size_t idx; 92 | long val; 93 | switch (mode) 94 | { 95 | case 0: 96 | for ( idx = 0; idx < count; ++idx) pattern[idx] = (long)idx; 97 | break; 98 | case 1: 99 | val = 0; 100 | idx = count - 1; 101 | do { 102 | pattern[idx--] = val++; 103 | }while (idx != 0); //siz_t must be great or equal to zero 104 | break; 105 | case 2: 106 | for ( idx = 0; idx < count; ++idx) pattern[idx] = (long)idx; 107 | size_t swapidx; 108 | init_random(0); 109 | for ( idx = 0; idx < count; ++idx) { 110 | swapidx = random_number(0, count); 111 | if (swapidx != idx) { 112 | val = pattern[idx]; 113 | pattern[idx] = pattern[swapidx]; 114 | pattern[swapidx] = val; 115 | } 116 | } 117 | break; 118 | default: 119 | ; 120 | } 121 | printf(ANSI_COLOR_CYAN "Free Pattern: " ANSI_COLOR_RESET); 122 | for( idx = 0; idx < count; ++idx) printf("%ld,",pattern[idx]); 123 | printf("\n" ANSI_COLOR_RESET); 124 | } 125 | 126 | size_t refill_keydata(void *md, size_t sz) 127 | { 128 | size_t fillcount = 0; 129 | 130 | long keyidx = 0; 131 | 132 | void *data = NULL; 133 | 134 | printf(ANSI_COLOR_CYAN "Set allocation size as %zx! \n" ANSI_COLOR_RESET, sz); 135 | 136 | for ( keyidx = 0; keyidx < PMALLOC_KEYS; ++keyidx) { 137 | data = pmalloc(md, sz); 138 | if (NULL != data) { 139 | pmalloc_setkey(md, keyidx, data); 140 | printf(ANSI_COLOR_BLUE "(Size %zx) Allocated data at %p with key %ld \n" ANSI_COLOR_RESET, sz, data, keyidx); 141 | ++fillcount; 142 | } else { 143 | printf(ANSI_COLOR_CYAN "Filled it up !!! \n" ANSI_COLOR_RESET); 144 | break; 145 | } 146 | } 147 | return fillcount; 148 | } 149 | 150 | /*******************************************/ 151 | 152 | void alloc_result(void *ptr) { 153 | if (NULL == ptr) { 154 | printf(ANSI_COLOR_RED "Out of Memory! \n" ANSI_COLOR_RESET); 155 | exit(-2); 156 | } 157 | } 158 | 159 | 160 | void init_roles(void *md) { 161 | g_roles = e_addr(md, pmalloc_getkey(md, ROLES_PKEYID)); 162 | 163 | if (NULL == g_roles) { 164 | g_roles = (char**)pmalloc(md, sizeof(char*) * 6); 165 | 166 | g_roles[0] = p_addr(md, pmalloc(md, 20)); 167 | alloc_result(g_roles[0]); 168 | sprintf(e_addr(md, g_roles[0]), "manager"); 169 | 170 | g_roles[1] = p_addr(md, pmalloc(md, 20)); 171 | alloc_result(g_roles[1]); 172 | sprintf(e_addr(md, g_roles[1]), "trainer"); 173 | 174 | g_roles[2] = p_addr(md, pmalloc(md, 20)); 175 | alloc_result(g_roles[2]); 176 | sprintf(e_addr(md, g_roles[2]), "engineer"); 177 | 178 | g_roles[3] = p_addr(md, pmalloc(md, 20)); 179 | alloc_result(g_roles[3]); 180 | sprintf(e_addr(md, g_roles[3]), "sales"); 181 | 182 | g_roles[4] = p_addr(md, pmalloc(md, 20)); 183 | alloc_result(g_roles[4]); 184 | sprintf(e_addr(md, g_roles[4]), "lawyer"); 185 | 186 | g_roles[5] = p_addr(md, pmalloc(md, 20)); 187 | alloc_result(g_roles[5]); 188 | sprintf(e_addr(md, g_roles[5]), "accountant"); 189 | 190 | pmalloc_setkey(md, ROLES_PKEYID, p_addr(md, g_roles)); 191 | } 192 | } 193 | 194 | size_t gen_employees(void *md, struct employee_t** pemp, int avail_deep) { 195 | size_t ret = 0; 196 | assert(NULL != pemp); 197 | 198 | struct employee_t* emp; 199 | emp = pmalloc(md, sizeof(struct employee_t)); 200 | alloc_result(emp); 201 | *pemp = p_addr(md, emp); 202 | 203 | emp->name = (char*)p_addr(md, pmcalloc(md, sizeof(char), random_number(200, 1000))); 204 | alloc_result(emp->name); 205 | sprintf(e_addr(md, emp->name), "employee %zx", random_number(0, 60000)); 206 | 207 | emp->age = random_number(24, 90); 208 | 209 | emp->role = g_roles[random_number(0 == avail_deep ? 1 : 0, 5)]; 210 | 211 | emp->members = NULL; 212 | 213 | emp->mcount = 0; 214 | 215 | if (g_roles[0] == emp->role) { // manager 216 | struct employee_t ** members = NULL; 217 | emp->mcount = random_number(1, 10); 218 | members = pmalloc(md, emp->mcount * sizeof(struct employee_t*)); 219 | alloc_result(members); 220 | int i; 221 | for (i = 0; i < emp->mcount; ++i) { 222 | ret += gen_employees(md, &members[i], avail_deep - 1); 223 | } 224 | emp->members = p_addr(md, members); 225 | } 226 | 227 | fprintf(stderr, "Generating %s, age: %d, role: %s, the number of members: %d \n", 228 | (char *)e_addr(md, emp->name), emp->age, (char *)e_addr(md, emp->role), emp->mcount); 229 | 230 | ++ret; 231 | 232 | return ret; 233 | } 234 | 235 | void print_employees(void *md, struct employee_t* emp, int deep) { 236 | assert(NULL != emp); 237 | struct employee_t* e_emp = e_addr(md, emp); 238 | int dp = deep; 239 | while (dp--) { 240 | printf("--"); 241 | } 242 | printf("%s, age: %d, role: %s, the number of members: %d \n", 243 | (char *)e_addr(md, e_emp->name), e_emp->age, (char *)e_addr(md, e_emp->role), e_emp->mcount); 244 | if (g_roles[0] == e_emp->role) { // manager 245 | int i; 246 | struct employee_t ** members = e_addr(md, e_emp->members); 247 | assert(NULL != members); 248 | for (i = 0; i < e_emp->mcount; ++i) { 249 | print_employees(md, members[i], deep + 1); 250 | } 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /src/pmfunction.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************************** 2 | Persist Memory allocator 3 | 4 | *****************************************************************************************/ 5 | 6 | #include "pmfunction.h" 7 | 8 | void rebase_mdesc_infos(struct mdesc * mdp, void *e_addr, void *o_addr) { 9 | if (e_addr == o_addr) 10 | return; 11 | printf("Rebase Address from %p to %p \n", o_addr, e_addr); 12 | //sleep(5); 13 | ptrdiff_t off; 14 | off = e_addr - o_addr; 15 | assert(mdp != NULL); 16 | mdp->mempoolbase = e_addr; 17 | mdp->mblkinfo = REBASE_ADDRESS(mdp->mblkinfo, off); 18 | mdp->watermarkpos = REBASE_ADDRESS(mdp->watermarkpos, off); 19 | mdp->limitpos = REBASE_ADDRESS(mdp->limitpos, off); 20 | mdp->mblkinfobase = REBASE_ADDRESS(mdp->mblkinfobase, off); 21 | size_t idx; 22 | 23 | /* not necessary to rebase all persistent key pointer since user do it instead more elegantly. 24 | for (idx = 0; idx < PMALLOC_KEYS; ++idx) { 25 | if (NULL != mdp -> keys[idx]) { 26 | mdp -> keys[idx] = REBASE_ADDRESS(mdp -> keys[idx], off); 27 | } 28 | } 29 | */ 30 | 31 | struct alignlist **pal = &mdp->aligned_blocks; 32 | while (NULL != *pal) { 33 | *pal = REBASE_ADDRESS(*pal, off); 34 | pal = &(*pal)->next; 35 | } 36 | 37 | for (idx = 0; idx < BLOCKLOG; ++idx) { 38 | struct list *plist = &mdp->fragblockhead[idx]; 39 | while (NULL != plist) { 40 | if (NULL != plist->next) { 41 | plist->next = REBASE_ADDRESS(plist->next, off); 42 | } 43 | if (NULL != plist->prev) { 44 | plist->prev = REBASE_ADDRESS(plist->prev, off); 45 | } 46 | plist = plist->next; 47 | } 48 | } 49 | } 50 | 51 | struct mdesc * reuse_mempool(int fd) { 52 | struct mdesc mtemp; 53 | struct mdesc *mdp = NULL; 54 | 55 | if ((lseek(fd, 0L, SEEK_SET) == 0) 56 | && (read(fd, (char *) &mtemp, sizeof(mtemp)) == sizeof(mtemp)) 57 | && (mtemp.headersize == sizeof(mtemp)) 58 | && (strcmp(mtemp.magicwords, PMALLOC_MAGIC) == 0) 59 | && (mtemp.version <= PMALLOC_VERSION)) { 60 | mtemp.mappingfd = fd; 61 | 62 | void * remap_base = __pmalloc_remap_mempool(&mtemp); 63 | if (remap_base != MAP_FAILED) { 64 | mdp = (struct mdesc *) remap_base; 65 | rebase_mdesc_infos(mdp, remap_base, mdp->mempoolbase); 66 | mdp->mappingfd = fd; 67 | mdp->morespace = __pmalloc_map_morespace; 68 | } 69 | } 70 | return (mdp); 71 | } 72 | 73 | void *align(struct mdesc * mdp, size_t size) { 74 | void * result; 75 | unsigned long int adj; 76 | 77 | result = mdp->morespace(mdp, size); 78 | adj = RESIDUAL(result, BLOCKSIZE); 79 | if (adj != 0) { 80 | adj = BLOCKSIZE - adj; 81 | mdp->morespace(mdp, adj); 82 | result = (char *) result + adj; 83 | } 84 | return (result); 85 | } 86 | 87 | int initialize(struct mdesc *mdp) { 88 | mdp->mblkinfosize = INITMPOOLSIZE / BLOCKSIZE; 89 | mdp->mblkinfo = (malloc_info *) align(mdp, 90 | mdp->mblkinfosize * sizeof(malloc_info)); 91 | if (mdp->mblkinfo == NULL) { 92 | return (0); 93 | } 94 | memset((void *) mdp->mblkinfo, 0, mdp->mblkinfosize * sizeof(malloc_info)); 95 | mdp->mblkinfo[0].free.size = 0; 96 | mdp->mblkinfo[0].free.next = mdp->mblkinfo[0].free.prev = 0; 97 | mdp->mblkinfosearchindex = 0; 98 | mdp->mblkinfobase = (char *) mdp->mblkinfo; 99 | mdp->flags |= PMALLOC_INITIALIZED; 100 | return (1); 101 | } 102 | 103 | void *morespace(struct mdesc *mdp, size_t size) { 104 | void * result; 105 | malloc_info *newinfo, *oldinfo; 106 | size_t newsize; 107 | 108 | result = align(mdp, size); 109 | if (result == NULL) { 110 | return (NULL); 111 | } 112 | 113 | if ((size_t) BLOCK((char * ) result + size) > mdp->mblkinfosize) { 114 | newsize = mdp->mblkinfosize; 115 | while ((size_t) BLOCK((char * ) result + size) > newsize) { 116 | newsize *= 2; 117 | } 118 | newinfo = (malloc_info *) align(mdp, newsize * sizeof(malloc_info)); 119 | if (newinfo == NULL) { 120 | mdp->morespace(mdp, -size); 121 | return (NULL); 122 | } 123 | memset((void *) newinfo, 0, newsize * sizeof(malloc_info)); 124 | memcpy((void *) newinfo, (void *) mdp->mblkinfo, 125 | mdp->mblkinfosize * sizeof(malloc_info)); 126 | oldinfo = mdp->mblkinfo; 127 | newinfo[BLOCK(oldinfo)].inuse.fragtype = 0; 128 | newinfo[BLOCK(oldinfo)].inuse.info.sizeinblock = BLOCKIFY( 129 | mdp->mblkinfosize * sizeof(malloc_info)); 130 | mdp->mblkinfo = newinfo; 131 | __pmalloc_free(mdp, (void *) oldinfo); 132 | mdp->mblkinfosize = newsize; 133 | } 134 | 135 | mdp->mblkinfoidxlimit = BLOCK((char * ) result + size); 136 | return (result); 137 | } 138 | 139 | void *allocate_blockfrag(struct mdesc *mdp, size_t size) 140 | { 141 | void * result = NULL; 142 | size_t block; 143 | register size_t i; 144 | struct list *next; 145 | register size_t log; 146 | 147 | log = 1; 148 | --size; 149 | while ((size /= 2) != 0) 150 | { 151 | ++log; 152 | } 153 | 154 | next = mdp -> fragblockhead[log].next; 155 | if (next != NULL) 156 | { 157 | result = (void *) next; 158 | next -> prev -> next = next -> next; 159 | if (next -> next != NULL) 160 | { 161 | next -> next -> prev = next -> prev; 162 | } 163 | block = BLOCK (result); 164 | if (--mdp -> mblkinfo[block].inuse.info.frag.nfreefrags != 0) 165 | { 166 | mdp -> mblkinfo[block].inuse.info.frag.firstfragidxinlist = 167 | RESIDUAL (next -> next, BLOCKSIZE) >> log; 168 | } 169 | 170 | mdp -> mblkstats.chunks_used++; 171 | mdp -> mblkstats.bytes_used += 1 << log; 172 | mdp -> mblkstats.chunks_free--; 173 | mdp -> mblkstats.bytes_free -= 1 << log; 174 | } 175 | else 176 | { 177 | result = allocate_blocks (mdp, 1); 178 | if (result != NULL) 179 | { 180 | for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i) 181 | { 182 | next = (struct list *) ((char *) result + (i << log)); 183 | next -> next = mdp -> fragblockhead[log].next; 184 | next -> prev = &mdp -> fragblockhead[log]; 185 | next -> prev -> next = next; 186 | if (next -> next != NULL) 187 | { 188 | next -> next -> prev = next; 189 | } 190 | } 191 | 192 | block = BLOCK (result); 193 | mdp -> mblkinfo[block].inuse.fragtype = log; 194 | mdp -> mblkinfo[block].inuse.info.frag.nfreefrags = i - 1; 195 | mdp -> mblkinfo[block].inuse.info.frag.firstfragidxinlist = i - 1; 196 | 197 | mdp -> mblkstats.chunks_free += (BLOCKSIZE >> log) - 1; 198 | mdp -> mblkstats.bytes_free += BLOCKSIZE - (1 << log); 199 | mdp -> mblkstats.bytes_used -= BLOCKSIZE - (1 << log); 200 | } 201 | } 202 | 203 | return result; 204 | } 205 | 206 | void *allocate_blocks(struct mdesc *mdp, size_t blocks) 207 | { 208 | void * result = NULL; 209 | size_t block, lastblocks, start; 210 | start = block = MALLOC_SEARCH_START; 211 | while (mdp -> mblkinfo[block].free.size < blocks) 212 | { 213 | block = mdp -> mblkinfo[block].free.next; 214 | if (block == start) 215 | { 216 | block = mdp -> mblkinfo[0].free.prev; 217 | lastblocks = mdp -> mblkinfo[block].free.size; 218 | if (mdp -> mblkinfoidxlimit != 0 && 219 | block + lastblocks == mdp -> mblkinfoidxlimit && 220 | mdp -> morespace (mdp, 0) == ADDRESS(block + lastblocks) && 221 | (morespace (mdp, (blocks - lastblocks) * BLOCKSIZE)) != NULL) 222 | { 223 | 224 | block = mdp -> mblkinfo[0].free.prev; 225 | 226 | mdp -> mblkinfo[block].free.size += (blocks - lastblocks); 227 | mdp -> mblkstats.bytes_free += 228 | (blocks - lastblocks) * BLOCKSIZE; 229 | continue; 230 | } 231 | result = morespace(mdp, blocks * BLOCKSIZE); 232 | if (result != NULL) 233 | { 234 | block = BLOCK (result); 235 | mdp -> mblkinfo[block].inuse.fragtype = 0; 236 | mdp -> mblkinfo[block].inuse.info.sizeinblock = blocks; 237 | mdp -> mblkstats.chunks_used++; 238 | mdp -> mblkstats.bytes_used += blocks * BLOCKSIZE; 239 | } 240 | return (result); 241 | } 242 | } 243 | 244 | result = ADDRESS(block); 245 | if (mdp -> mblkinfo[block].free.size > blocks) 246 | { 247 | mdp -> mblkinfo[block + blocks].free.size 248 | = mdp -> mblkinfo[block].free.size - blocks; 249 | mdp -> mblkinfo[block + blocks].free.next 250 | = mdp -> mblkinfo[block].free.next; 251 | mdp -> mblkinfo[block + blocks].free.prev 252 | = mdp -> mblkinfo[block].free.prev; 253 | mdp -> mblkinfo[mdp -> mblkinfo[block].free.prev].free.next 254 | = mdp -> mblkinfo[mdp -> mblkinfo[block].free.next].free.prev 255 | = mdp -> mblkinfosearchindex = block + blocks; 256 | } 257 | else 258 | { 259 | mdp -> mblkinfo[mdp -> mblkinfo[block].free.next].free.prev 260 | = mdp -> mblkinfo[block].free.prev; 261 | mdp -> mblkinfo[mdp -> mblkinfo[block].free.prev].free.next 262 | = mdp -> mblkinfosearchindex = mdp -> mblkinfo[block].free.next; 263 | mdp -> mblkstats.chunks_free--; 264 | } 265 | 266 | mdp -> mblkinfo[block].inuse.fragtype = 0; 267 | mdp -> mblkinfo[block].inuse.info.sizeinblock = blocks; 268 | mdp -> mblkstats.chunks_used++; 269 | mdp -> mblkstats.bytes_used += blocks * BLOCKSIZE; 270 | mdp -> mblkstats.bytes_free -= blocks * BLOCKSIZE; 271 | return result; 272 | } 273 | 274 | void free_blocks(struct mdesc *mdp, size_t block) 275 | { 276 | size_t blocks; 277 | register size_t i; 278 | /* struct list *prev, *next; */ 279 | mdp -> mblkstats.chunks_used--; 280 | mdp -> mblkstats.bytes_used -= 281 | mdp -> mblkinfo[block].inuse.info.sizeinblock * BLOCKSIZE; 282 | mdp -> mblkstats.bytes_free += 283 | mdp -> mblkinfo[block].inuse.info.sizeinblock * BLOCKSIZE; 284 | 285 | i = mdp -> mblkinfosearchindex; 286 | if (i > block) 287 | { 288 | while (i > block) 289 | { 290 | i = mdp -> mblkinfo[i].free.prev; 291 | } 292 | } 293 | else 294 | { 295 | do 296 | { 297 | i = mdp -> mblkinfo[i].free.next; 298 | } 299 | while ((i != 0) && (i < block)); 300 | i = mdp -> mblkinfo[i].free.prev; 301 | } 302 | 303 | if (block == i + mdp -> mblkinfo[i].free.size) 304 | { 305 | mdp -> mblkinfo[i].free.size += 306 | mdp -> mblkinfo[block].inuse.info.sizeinblock; 307 | block = i; 308 | } 309 | else 310 | { 311 | mdp -> mblkinfo[block].free.size = 312 | mdp -> mblkinfo[block].inuse.info.sizeinblock; 313 | mdp -> mblkinfo[block].free.next = mdp -> mblkinfo[i].free.next; 314 | mdp -> mblkinfo[block].free.prev = i; 315 | mdp -> mblkinfo[i].free.next = block; 316 | mdp -> mblkinfo[mdp -> mblkinfo[block].free.next].free.prev = block; 317 | mdp -> mblkstats.chunks_free++; 318 | } 319 | 320 | if (block + mdp -> mblkinfo[block].free.size == 321 | mdp -> mblkinfo[block].free.next) 322 | { 323 | mdp -> mblkinfo[block].free.size 324 | += mdp -> mblkinfo[mdp -> mblkinfo[block].free.next].free.size; 325 | mdp -> mblkinfo[block].free.next 326 | = mdp -> mblkinfo[mdp -> mblkinfo[block].free.next].free.next; 327 | mdp -> mblkinfo[mdp -> mblkinfo[block].free.next].free.prev = block; 328 | mdp -> mblkstats.chunks_free--; 329 | } 330 | 331 | blocks = mdp -> mblkinfo[block].free.size; 332 | if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> mblkinfoidxlimit 333 | && mdp -> morespace (mdp, 0) == ADDRESS (block + blocks)) 334 | { 335 | register size_t bytes = blocks * BLOCKSIZE; 336 | mdp -> mblkinfoidxlimit -= blocks; 337 | mdp -> morespace (mdp, -bytes); 338 | mdp -> mblkinfo[mdp -> mblkinfo[block].free.prev].free.next 339 | = mdp -> mblkinfo[block].free.next; 340 | mdp -> mblkinfo[mdp -> mblkinfo[block].free.next].free.prev 341 | = mdp -> mblkinfo[block].free.prev; 342 | block = mdp -> mblkinfo[block].free.prev; 343 | mdp -> mblkstats.chunks_free--; 344 | mdp -> mblkstats.bytes_free -= bytes; 345 | } 346 | 347 | mdp -> mblkinfosearchindex = block; 348 | } 349 | 350 | void free_blockfrag(struct mdesc *mdp, size_t block, int fraglog, void *addr) 351 | { 352 | /* size_t blocks; */ 353 | register size_t i; 354 | struct list *prev, *next; 355 | 356 | mdp -> mblkstats.chunks_used--; 357 | mdp -> mblkstats.bytes_used -= 1 << fraglog; 358 | mdp -> mblkstats.chunks_free++; 359 | mdp -> mblkstats.bytes_free += 1 << fraglog; 360 | 361 | prev = (struct list *) 362 | ((char *) ADDRESS(block) + 363 | (mdp -> mblkinfo[block].inuse.info.frag.firstfragidxinlist << fraglog)); 364 | 365 | if (mdp -> mblkinfo[block].inuse.info.frag.nfreefrags == 366 | (BLOCKSIZE >> fraglog) - 1) 367 | { 368 | next = prev; 369 | for (i = 1; i < (size_t) (BLOCKSIZE >> fraglog); ++i) 370 | { 371 | next = next -> next; 372 | } 373 | prev -> prev -> next = next; 374 | if (next != NULL) 375 | { 376 | next -> prev = prev -> prev; 377 | } 378 | mdp -> mblkinfo[block].inuse.fragtype = 0; 379 | mdp -> mblkinfo[block].inuse.info.sizeinblock = 1; 380 | 381 | mdp -> mblkstats.chunks_used++; 382 | mdp -> mblkstats.bytes_used += BLOCKSIZE; 383 | mdp -> mblkstats.chunks_free -= BLOCKSIZE >> fraglog; 384 | mdp -> mblkstats.bytes_free -= BLOCKSIZE; 385 | 386 | pmfree ((void *) mdp, (void *) ADDRESS(block)); 387 | } 388 | else if (mdp -> mblkinfo[block].inuse.info.frag.nfreefrags != 0) 389 | { 390 | next = (struct list *) addr; 391 | next -> next = prev -> next; 392 | next -> prev = prev; 393 | prev -> next = next; 394 | if (next -> next != NULL) 395 | { 396 | next -> next -> prev = next; 397 | } 398 | ++mdp -> mblkinfo[block].inuse.info.frag.nfreefrags; 399 | } 400 | else 401 | { 402 | prev = (struct list *) addr; 403 | mdp -> mblkinfo[block].inuse.info.frag.nfreefrags = 1; 404 | mdp -> mblkinfo[block].inuse.info.frag.firstfragidxinlist = 405 | RESIDUAL (addr, BLOCKSIZE) >> fraglog; 406 | prev -> next = mdp -> fragblockhead[fraglog].next; 407 | prev -> prev = &mdp -> fragblockhead[fraglog]; 408 | prev -> prev -> next = prev; 409 | if (prev -> next != NULL) 410 | { 411 | prev -> next -> prev = prev; 412 | } 413 | } 414 | } 415 | 416 | void *pmopen(const char *fn, void *baseaddr, size_t initial_size) 417 | { 418 | void *ret = NULL; 419 | assert(NULL != fn); 420 | int fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); 421 | if(fd >= 0) { 422 | ret = pmalloc_attach(fd, baseaddr, initial_size); 423 | } 424 | return ret; 425 | } 426 | 427 | long pmcapacity(void* md) 428 | { 429 | struct mdesc *mdp = (struct mdesc *) md; 430 | if (NULL == mdp->limitpos || NULL == mdp->mempoolbase || 431 | mdp->limitpos <= mdp->mempoolbase) { 432 | return 0L; 433 | } 434 | return mdp->limitpos - mdp->mempoolbase; 435 | } 436 | 437 | void pmclose(void* md) 438 | { 439 | struct mdesc *mdp = (struct mdesc *)md; 440 | assert(NULL != mdp); 441 | /* pmalloc_detach(md); */ 442 | close(mdp->mappingfd); 443 | } 444 | --------------------------------------------------------------------------------