wangzhengquan
2020-12-22 b90ba316b54db321d3e8aaac7df93b46d80b9d9c
src/queue/mm.c
@@ -81,7 +81,7 @@
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);
@@ -122,6 +122,7 @@
    SemUtil::inc(mutex);
    return aptr;
  } else {
    SemUtil::inc(mutex);
    err_msg(0, "mm_malloc : out of memery\n");
    return NULL;
  }
@@ -143,9 +144,8 @@
   *}
   */
  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);
@@ -300,115 +300,76 @@
  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
 */
@@ -444,9 +405,10 @@
/**
 * 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));