| | |
| | | static void *place(void *bp, size_t size); |
| | | static void *find_fit(size_t size); |
| | | static void *coalesce(void *bp); |
| | | static void rm_fblock(void *bp); |
| | | static inline void rm_fblock(void *bp); |
| | | static void insert_fblock (void *bp); |
| | | |
| | | static void *mem_sbrk(int incr); |
| | |
| | | SemUtil::inc(mutex); |
| | | return aptr; |
| | | } else { |
| | | SemUtil::inc(mutex); |
| | | err_msg(0, "mm_malloc : out of memery\n"); |
| | | return NULL; |
| | | } |
| | |
| | | *} |
| | | */ |
| | | |
| | | |
| | | size_t size = GET_SIZE(HDRP(ptr)); |
| | | SemUtil::dec(mutex); |
| | | size_t size = GET_SIZE(HDRP(ptr)); |
| | | PUT(HDRP(ptr), PACK(size, 0)); |
| | | PUT(FTRP(ptr), PACK(size, 0)); |
| | | coalesce(ptr); |
| | |
| | | return first; |
| | | } |
| | | |
| | | hashtable_t * mm_get_hashtable() { |
| | | return hashtable; |
| | | } |
| | | |
| | | /* |
| | | * mm_init - Initialize the memory manager |
| | | */ |
| | | bool mm_init2(size_t offset, void **addr) |
| | | { |
| | | |
| | | //已经初始化过了 |
| | | SemUtil::dec(mutex); |
| | | if (shmid != -1){ |
| | | *addr = shmp; |
| | | SemUtil::inc(mutex); |
| | | return false; |
| | | } |
| | | |
| | | bool first = true; |
| | | |
| | | |
| | | shmid = shmget(SHM_KEY, MAX_HEAP, IPC_CREAT | IPC_EXCL | OBJ_PERMS); |
| | | if (shmid == -1 && errno == EEXIST) { |
| | | first = false; |
| | | shmid = shmget(SHM_KEY, 0, 0); |
| | | } |
| | | if (shmid == -1) |
| | | err_exit(errno, "mm_init shmget"); |
| | | shmp = shmat(shmid, key_addr, 0); |
| | | if ((long)shmp == -1) |
| | | err_exit(errno, "mm_init shmat"); |
| | | |
| | | mem_start_brk = (void*)ALIGN((size_t)((char *)shmp + offset + ALIGNMENT)); |
| | | mem_max_addr = (void *)((char *)shmp+ MAX_HEAP); |
| | | mem_max_size = (char *)mem_max_addr - (char*)mem_start_brk; |
| | | mem_brk = mem_start_brk; |
| | | void *free_listp; |
| | | /* Create the initial empty heap */ |
| | | int initsize = ALIGN(3 * SIZE_T_SIZE + 2 * PTR_SIZE); |
| | | heap_listp = (char *)mem_start_brk + initsize - 2 * SIZE_T_SIZE - 2 * PTR_SIZE; |
| | | |
| | | if(!first) { |
| | | *addr = shmp; |
| | | SemUtil::inc(mutex); |
| | | return first; |
| | | } |
| | | |
| | | |
| | | if ((mem_sbrk(initsize)) == (void *) - 1) |
| | | err_exit(errno, "mm_init mem_sbrk"); |
| | | |
| | | PUT((char *)mem_start_brk + initsize - SIZE_T_SIZE, PACK(0, 1)); /* Epilogue header */ |
| | | /*PUT(HDRP(heap_listp), PACK(initsize - SIZE_T_SIZE, 1)); |
| | | PUT(FTRP(heap_listp), PACK(initsize - SIZE_T_SIZE, 1));*/ |
| | | |
| | | PUT(HDRP(heap_listp), PACK(initsize - SIZE_T_SIZE, 1)); |
| | | PUT(FTRP(heap_listp), PACK(initsize - SIZE_T_SIZE, 1)); |
| | | |
| | | /** |
| | | * here the heap_listp can be look as a ancher which concat the header and tail of free-list to form a ring, and the heap_list itself will never be used as a free block |
| | | */ |
| | | PUT_PTR(SUCCRP(heap_listp), heap_listp); |
| | | PUT_PTR(PREDRP(heap_listp), heap_listp); |
| | | /* Extend the empty heap with a free block of CHUNKSIZE bytes */ |
| | | if ((free_listp = extend_heap(mem_max_size - initsize - ALIGNMENT)) == NULL) |
| | | err_exit(errno, "mm_init extend_heap"); |
| | | |
| | | *addr = shmp; |
| | | SemUtil::inc(mutex); |
| | | return first; |
| | | } |
| | | |
| | | |
| | | |
| | | bool mm_destroy(void) { |
| | | struct shmid_ds shmid_ds; |
| | | //detache |
| | | |
| | | |
| | | SemUtil::dec(mutex); |
| | | if (shmdt(shmp) == -1) { |
| | | err_msg(errno, "mm_destroy shmdt"); |
| | | SemUtil::inc(mutex); |
| | | } |
| | | |
| | | |
| | | if(shmctl(shmid, IPC_STAT, &shmid_ds) == 0) { |
| | | //LoggerFactory::getLogger().debug("shm_nattch=%d\n", shmid_ds.shm_nattch); |
| | | if(shmid_ds.shm_nattch == 0) { |
| | | //remove shared memery |
| | | if (shmctl(shmid, IPC_RMID, 0) == -1) |
| | | err_exit(errno, "mm_destroy shmctl IPC_RMID"); |
| | | else |
| | | LoggerFactory::getLogger().debug("shared memory destroy\n"); |
| | | |
| | | SemUtil::inc(mutex); |
| | | SemUtil::remove(mutex); |
| | | return true; |
| | | |
| | | } else { |
| | | //LoggerFactory::getLogger()->debug("shm_nattch=%d\n", shmid_ds.shm_nattch); |
| | | // 只有当前一个进程attach到共享内存上 |
| | | if (shmid_ds.shm_nattch > 1) { |
| | | //detache |
| | | if (shmdt(shmp) == -1) { |
| | | LoggerFactory::getLogger()->error(errno, "mm_destroy shmdt"); |
| | | } |
| | | SemUtil::inc(mutex); |
| | | } |
| | | return false; |
| | | return false; |
| | | } else { |
| | | |
| | | hashtable_destroy(hashtable); |
| | | //detache |
| | | if (shmdt(shmp) == -1) { |
| | | LoggerFactory::getLogger()->error(errno, "mm_destroy shmdt"); |
| | | SemUtil::inc(mutex); |
| | | return false; |
| | | } |
| | | |
| | | //remove shared memery |
| | | if (shmctl(shmid, IPC_RMID, 0) == -1) |
| | | err_exit(errno, "mm_destroy shmctl IPC_RMID"); |
| | | else |
| | | LoggerFactory::getLogger()->debug("shared memory destroy\n"); |
| | | |
| | | LoggerFactory::getLogger()->debug(errno, "mm_destroy: real destroy."); |
| | | |
| | | SemUtil::inc(mutex); |
| | | SemUtil::remove(mutex); |
| | | return true; |
| | | |
| | | } |
| | | |
| | | } else { |
| | | err_msg(errno, "mm_destroy shmctl IPC_STAT"); |
| | | SemUtil::inc(mutex); |
| | | return false; |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | hashtable_t * mm_get_hashtable() { |
| | | return hashtable; |
| | | } |
| | | |
| | | void * mm_get_by_key(int key) { |
| | | return hashtable_get(hashtable, key); |
| | | } |
| | | |
| | | void mm_free_by_key(int key) { |
| | | void *ptr; |
| | | ptr = hashtable_get(hashtable, key); |
| | | if(ptr != NULL) { |
| | | mm_free(ptr); |
| | | hashtable_remove(hashtable, key); |
| | | } |
| | | } |
| | | |
| | | |
| | | int mm_alloc_key() { |
| | | return hashtable_alloc_key(hashtable); |
| | | } |
| | | |
| | | /* |
| | | * extend_heap - Extend heap with free block and return its block pointer |
| | | */ |
| | |
| | | /** |
| | | * remove a block form free list |
| | | */ |
| | | static void rm_fblock(void *rbp) |
| | | static inline void rm_fblock(void *rbp) |
| | | { |
| | | // the successor of the previous block of rbp point to next block of rbp |
| | | |
| | | PUT_PTR(SUCCRP(PREV_FBLKP(rbp)), NEXT_FBLKP(rbp)); |
| | | // the predecessor of then next block of rbp point to previous block of rbp |
| | | PUT_PTR(PREDRP(NEXT_FBLKP(rbp)), PREV_FBLKP(rbp)); |