示例#1
0
文件: mm.c 项目: msr23trini/malloclab
static void *find_fit(size_t asize)

{
   /* First fit search */
  void* bp;
  //  print_list();
  int offset = get_offset(asize);
  //printf("in first fit search  \n");
  for (int i = offset; i < 9; i++)
    {
      //printf ("In bucket %d \n",i);
      for (bp =((void*) (*(long*)GET_BUCKET(root, i)));
           bp != NULL ; bp = get_succ(bp) )
        {
          // printf("bp %p \n",bp);
          REQUIRES ((void*)bp != NULL);
          REQUIRES (((size_t)(bp))%8 == 0);
          size_t size =  GET_SIZE(HDRP((bp)));
          if (!GET_ALLOC( HDRP(((bp) ) )) &&
              (asize <= size))
            {
              ENSURES ( (size_t)(bp)%8 == 0);
              size_t diff = size - asize;
              return first_best_fit((void*)bp,asize, diff) ;
            }
        }
    }
  return NULL; /* No fit */
}
示例#2
0
void
hash_destroy (HTAB	*hashp)
{
    /* cannot destroy a shared memory hash table */
    Assert(! hashp->segbase);
    
    if (hashp != NULL) {
	register SEG_OFFSET 	segNum;
	SEGMENT		segp;
	int			nsegs = hashp->hctl->nsegs;
	int 		j;
	BUCKET_INDEX	*elp,p,q;
	ELEMENT		*curr;
	
	for (segNum =  0;  nsegs > 0; nsegs--, segNum++) {
	    
	    segp = GET_SEG(hashp,segNum);
	    for (j = 0, elp = segp; j < hashp->hctl->ssize; j++, elp++) {
		for ( p = *elp; p != INVALID_INDEX; p = q ){
		    curr = GET_BUCKET(hashp,p);
		    q = curr->next;
		    MEM_FREE((char *) curr);
		}
	    }
	    free((char *)segp);
	}
	(void) MEM_FREE( (char *) hashp->dir);
	(void) MEM_FREE( (char *) hashp->hctl);
	hash_stats("destroy",hashp);
	(void) MEM_FREE( (char *) hashp);
    }
}
示例#3
0
文件: mm.c 项目: msr23trini/malloclab
static void remove_block(void *bp, size_t size)
{
  //printf ("remove block\n");
  REQUIRES ( bp != NULL );
  REQUIRES ( (size_t)(bp) % 8 == 0);

  int offset = get_offset(size);
  void *pred = get_pred(bp);
  void *succ = get_succ(bp);

  if ( pred == NULL && succ != NULL)
    //block to be removed is the first block in the list
    {
      SET_SUCC(bp) = 0;
      SET_PRED(succ) = 0;
      SET_ROOT(GET_BUCKET(root, offset)) = (long)succ;

    }
  else if (pred != NULL && succ == NULL)
    //block to be removed is the last block in the list
    {
      SET_SUCC(pred) = 0;
      SET_PRED(bp) = 0;

    }

  else if (pred != NULL && succ != NULL)
    //block to be removed is located somewhere within the list.
    {
      SET_SUCC(pred) = (int)( (long)succ - BASE);
      SET_PRED(succ) = (int)((long)pred - BASE);
      SET_PRED(bp) = 0;
      SET_SUCC(bp) = 0;

    }

  else if ( pred == NULL && succ == NULL)
    {
      //printf("resetting root\n");
      SET_ROOT(GET_BUCKET(root, offset)) = 0;
    }
  print_list();
  return;
}
示例#4
0
文件: mm.c 项目: msr23trini/malloclab
// Returns 0 if no errors were found, otherwise returns the error
int mm_checkheap(int verbose) {
  // char *bp = heap_listp;

  if (verbose)
    printf("Heap (%p):\n", heap_listp);

  if ((GET_SIZE(HDRP(heap_listp)) != DSIZE) || !GET_ALLOC(HDRP(heap_listp)))
    printf("Bad prologue header\n");
  checkblock(heap_listp);

  void* list;
  int count_free_in_list = 0;
  int count_free_in_heap = 0;
  for (int i =0; i < 9; i++)
    {
      for (list = (void*)(*(long*)GET_BUCKET(root,i)); list != NULL;
           list =  get_succ(list)  ) {
        if (verbose)
          printblock(list);
        checkblock(list);
        if ( get_succ(list) != NULL && get_pred(list) !=NULL)
          check_succ_pred(list);
        check_address(list);
        count_free_in_list++;
        check_in_correct_bucket(list, i);
      }
    }

  char *bp;

  for (bp = heap_listp; GET_SIZE(HDRP(bp)) > 0; bp = NEXT_BLKP(bp)) {
    if (verbose)
      {
        if (GET_ALLOC(HDRP(bp)) == 0)
          count_free_in_heap ++;
        printblock(bp);
        checkblock(bp);
        check_coalescing( (void*)bp);
      }
  }

  if (count_free_in_heap != count_free_in_list)
    printf ("Number of free block not consistent in heap and list list \n");

  if (verbose)
    printblock(bp);
    if ((GET_SIZE(HDRP(bp)) != 0) || !(GET_ALLOC(HDRP(bp))))
      {
        printf("Bad epilogue header\n");
        if (GET_SIZE(HDRP(bp)) != 0)
          printf ("size is not 0\n");
        if (!(GET_ALLOC(HDRP(bp))) )
           printf ("not allocated properly\n");
     }
    return 0;
}
示例#5
0
bool
hashmap_has_key(hashmap_t* map, hash_t key) {
	/*lint --e{613} */
	size_t ibucket = GET_BUCKET(map, key);
	hashmap_node_t* bucket = map->bucket[ibucket];
	size_t inode, nsize;
	for (inode = 0, nsize = array_size(bucket); inode < nsize; ++inode) {
		if (bucket[inode].key == key)
			return true;
	}
	return false;
}
示例#6
0
void*
hashmap_lookup(hashmap_t* map, hash_t key) {
	/*lint --e{613} */
	size_t ibucket = GET_BUCKET(map, key);
	hashmap_node_t* bucket = map->bucket[ibucket];
	size_t inode, nsize;
	for (inode = 0, nsize = array_size(bucket); inode < nsize; ++inode) {
		if (bucket[inode].key == key)
			return bucket[inode].value;
	}
	return 0;
}
示例#7
0
文件: mm.c 项目: msr23trini/malloclab
static void add_block(void *bp, size_t size)
{
  // printf ("in add block\n");

  REQUIRES ( bp != NULL ) ;
  REQUIRES ((size_t)(bp) % 8 == 0);

  int offset = get_offset(size);
  if ( (*(long*)GET_BUCKET(root, offset) != 0))
    {
      //printf ("replacing root\n");
      SET_PRED((void*)(*(long*)GET_BUCKET(root, offset))) =
        (int)( (long)bp -BASE );
    }
  int val = (int)(*(long*)GET_BUCKET(root,offset) - BASE);
  //printf ("val = 0x%x \n",val);
  SET_SUCC(bp) = val;
  SET_PRED(bp) = 0;
  SET_ROOT(GET_BUCKET(root, offset)) = (long)bp;

  //print_list();
  //printf("returned from adding block\n");
  return;
}
示例#8
0
void*
hashmap_erase(hashmap_t* map, hash_t key) {
	/*lint --e{613} */
	size_t ibucket = GET_BUCKET(map, key);
	hashmap_node_t* bucket = map->bucket[ibucket];
	size_t inode, nsize;
	for (inode = 0, nsize = array_size(bucket); inode < nsize; ++inode) {
		if (bucket[inode].key == key) {
			void* prev = bucket[inode].value;
			array_erase(map->bucket[ibucket], inode);
			--map->num_nodes;
			return prev;
		}
	}
	return 0;
}
示例#9
0
/*
 * allocate some new buckets and link them into the free list
 */
static int
bucket_alloc(HTAB *hashp)
{
    int i;
    ELEMENT *tmpBucket;
    long bucketSize;
    BUCKET_INDEX tmpIndex,lastIndex;
    
    bucketSize = 
	sizeof(BUCKET_INDEX) + hashp->hctl->keysize + hashp->hctl->datasize;
    
    /* make sure its aligned correctly */
    bucketSize += sizeof(long *) - (bucketSize % sizeof(long *));
    
    /* tmpIndex is the shmem offset into the first bucket of
     * the array.
     */
    tmpBucket = (ELEMENT *)
	hashp->alloc((unsigned long) BUCKET_ALLOC_INCR*bucketSize);
    
    if (! tmpBucket) {
	return(0);
    }
    
    tmpIndex = MAKE_HASHOFFSET(hashp,tmpBucket);
    
    /* set the freebucket list to point to the first bucket */
    lastIndex = hashp->hctl->freeBucketIndex;
    hashp->hctl->freeBucketIndex = tmpIndex;
    
    /* initialize each bucket to point to the one behind it */
    for (i=0;i<(BUCKET_ALLOC_INCR-1);i++) {
	tmpBucket = GET_BUCKET(hashp,tmpIndex);
	tmpIndex += bucketSize;
	tmpBucket->next = tmpIndex;
    }
    
    /* the last bucket points to the old freelist head (which is
     * probably invalid or we wouldnt be here) 
     */
    tmpBucket->next = lastIndex;
    
    return(1);
}
示例#10
0
void*
hashmap_insert(hashmap_t* map, hash_t key, void* value) {
	/*lint --e{613} */
	size_t ibucket = GET_BUCKET(map, key);
	hashmap_node_t* bucket = map->bucket[ibucket];
	size_t inode, nsize;
	for (inode = 0, nsize = array_size(bucket); inode < nsize; ++inode) {
		if (bucket[inode].key == key) {
			void* prev = bucket[inode].value;
			bucket[inode].value = value;
			return prev;
		}
	}
	{
		hashmap_node_t node = { key, value };
		array_push(map->bucket[ibucket], node);
		++map->num_nodes;
	}
	return 0;
}
示例#11
0
/********************************* UTILITIES ************************/
static int
expand_table(HTAB *hashp)
{
    HHDR	*hctl;
    SEGMENT	old_seg,new_seg;
    long	old_bucket, new_bucket;
    long	new_segnum, new_segndx;
    long	old_segnum, old_segndx;
    ELEMENT	*chain;
    BUCKET_INDEX *old,*newbi;
    register BUCKET_INDEX chainIndex,nextIndex;
    
#ifdef HASH_STATISTICS
    hash_expansions++;
#endif
    
    hctl = hashp->hctl;
    new_bucket = ++hctl->max_bucket;
    old_bucket = (hctl->max_bucket & hctl->low_mask);
    
    new_segnum = new_bucket >> hctl->sshift;
    new_segndx = MOD ( new_bucket, hctl->ssize );
    
    if ( new_segnum >= hctl->nsegs ) {
	
	/* Allocate new segment if necessary */
	if (new_segnum >= hctl->dsize) {
	    dir_realloc(hashp);
	}
	if (! (hashp->dir[new_segnum] = seg_alloc(hashp))) {
	    return (0);
	}
	hctl->nsegs++;
    }
    
    
    if ( new_bucket > hctl->high_mask ) {
	/* Starting a new doubling */
	hctl->low_mask = hctl->high_mask;
	hctl->high_mask = new_bucket | hctl->low_mask;
    }
    
    /*
     * Relocate records to the new bucket
     */
    old_segnum = old_bucket >> hctl->sshift;
    old_segndx = MOD(old_bucket, hctl->ssize);
    
    old_seg = GET_SEG(hashp,old_segnum);
    new_seg = GET_SEG(hashp,new_segnum);
    
    old = &old_seg[old_segndx];
    newbi = &new_seg[new_segndx];
    for (chainIndex = *old; 
	 chainIndex != INVALID_INDEX;
	 chainIndex = nextIndex){
	
	chain = GET_BUCKET(hashp,chainIndex);
	nextIndex = chain->next;
	if ( call_hash(hashp,
		       (char *)&(chain->key),
		       hctl->keysize) == old_bucket ) {
	    *old = chainIndex;
	    old = &chain->next;
	} else {
	    *newbi = chainIndex;
	    newbi = &chain->next;
	}
	chain->next = INVALID_INDEX;
    }
    return (1);
}
示例#12
0
/*
 * hash_seq -- sequentially search through hash table and return
 *             all the elements one by one, return NULL on error and
 *	       return TRUE in the end.
 *
 */
long *
hash_seq(HTAB *hashp)
{
    static uint32 curBucket = 0;
    static BUCKET_INDEX curIndex;
    ELEMENT *curElem;
    long segment_num;
    long segment_ndx;
    SEGMENT segp;
    HHDR *hctl;
    
    if (hashp == NULL)
	{
	    /*
	     * reset static state
	     */
	    curBucket = 0;
	    curIndex = INVALID_INDEX;
	    return((long *) NULL);
	}
    
    hctl = hashp->hctl;
    while (curBucket <= hctl->max_bucket) {
	if (curIndex != INVALID_INDEX) {
	    curElem = GET_BUCKET(hashp, curIndex);
	    curIndex = curElem->next;
	    if (curIndex == INVALID_INDEX)	/* end of this bucket */
		++curBucket;
	    return(&(curElem->key));
	}
	
	/*
	 * initialize the search within this bucket.
	 */
	segment_num = curBucket >> hctl->sshift;
	segment_ndx = curBucket & ( hctl->ssize - 1 );
	
	/*
	 * first find the right segment in the table directory.
	 */
	segp = GET_SEG(hashp, segment_num);
	if (segp == NULL)
	    /* this is probably an error */
	    return((long *) NULL);
	
	/*
	 * now find the right index into the segment for the first
	 * item in this bucket's chain.  if the bucket is not empty
	 * (its entry in the dir is valid), we know this must
	 * correspond to a valid element and not a freed element
	 * because it came out of the directory of valid stuff.  if
	 * there are elements in the bucket chains that point to the
	 * freelist we're in big trouble.
	 */
	curIndex = segp[segment_ndx];
	
	if (curIndex == INVALID_INDEX)		/* empty bucket */
	    ++curBucket;
    }
    
    return((long *) TRUE);			/* out of buckets */
}
示例#13
0
/*
 * hash_search -- look up key in table and perform action
 *
 * action is one of HASH_FIND/HASH_ENTER/HASH_REMOVE
 *
 * RETURNS: NULL if table is corrupted, a pointer to the element
 * 	found/removed/entered if applicable, TRUE otherwise.
 *	foundPtr is TRUE if we found an element in the table 
 *	(FALSE if we entered one).
 */
long *
hash_search(HTAB *hashp,
	    char *keyPtr, 
	    HASHACTION action,	/*
				 * HASH_FIND / HASH_ENTER / HASH_REMOVE
				 * HASH_FIND_SAVE / HASH_REMOVE_SAVED
				 */
	    bool *foundPtr)
{
    uint32 bucket;
    long segment_num;
    long segment_ndx;
    SEGMENT segp;
    register ELEMENT *curr;
    HHDR	*hctl;
    BUCKET_INDEX	currIndex;
    BUCKET_INDEX	*prevIndexPtr;
    char *		destAddr;
    static struct State {
	ELEMENT      *currElem;
	BUCKET_INDEX currIndex;
	BUCKET_INDEX *prevIndex;
    } saveState;
    
    Assert((hashp && keyPtr));
    Assert((action == HASH_FIND) || (action == HASH_REMOVE) || (action == HASH_ENTER) || (action == HASH_FIND_SAVE) || (action == HASH_REMOVE_SAVED));
    
    hctl = hashp->hctl;
    
# if HASH_STATISTICS
    hash_accesses++;
    hashp->hctl->accesses++;
# endif
    if (action == HASH_REMOVE_SAVED)
	{
	    curr = saveState.currElem;
	    currIndex = saveState.currIndex;
	    prevIndexPtr = saveState.prevIndex;
	    /*
	     * Try to catch subsequent errors
	     */
	    Assert(saveState.currElem && !(saveState.currElem = 0));
	}
    else
	{
	    bucket = call_hash(hashp, keyPtr, hctl->keysize);
	    segment_num = bucket >> hctl->sshift;
	    segment_ndx = bucket & ( hctl->ssize - 1 );
	    
	    segp = GET_SEG(hashp,segment_num);
	    
	    Assert(segp);
	    
	    prevIndexPtr = &segp[segment_ndx];
	    currIndex = *prevIndexPtr;
	    /*
	     * Follow collision chain
	     */
	    for (curr = NULL;currIndex != INVALID_INDEX;) {
		/* coerce bucket index into a pointer */
		curr = GET_BUCKET(hashp,currIndex);
		
		if (! memcmp((char *)&(curr->key), keyPtr, hctl->keysize)) {
		    break;
		} 
		prevIndexPtr = &(curr->next);
		currIndex = *prevIndexPtr;
# if HASH_STATISTICS
		hash_collisions++;
		hashp->hctl->collisions++;
# endif
	    }
	}
    
    /*
     *  if we found an entry or if we weren't trying
     * to insert, we're done now.
     */
    *foundPtr = (bool) (currIndex != INVALID_INDEX);
    switch (action) {
    case HASH_ENTER:
	if (currIndex != INVALID_INDEX)
	    return(&(curr->key));
	break;
    case HASH_REMOVE:
    case HASH_REMOVE_SAVED:
	if (currIndex != INVALID_INDEX) {
	    Assert(hctl->nkeys > 0);
	    hctl->nkeys--;
	    
	    /* add the bucket to the freelist for this table.  */
	    *prevIndexPtr = curr->next;
	    curr->next = hctl->freeBucketIndex;
	    hctl->freeBucketIndex = currIndex;
	    
	    /* better hope the caller is synchronizing access to
	     * this element, because someone else is going to reuse
	     * it the next time something is added to the table
	     */
	    return (&(curr->key));
	}
	return((long *) TRUE);
    case HASH_FIND:
	if (currIndex != INVALID_INDEX)
	    return(&(curr->key));
	return((long *)TRUE);
    case HASH_FIND_SAVE:
	if (currIndex != INVALID_INDEX)
	    {
		saveState.currElem = curr;
		saveState.prevIndex = prevIndexPtr;
		saveState.currIndex = currIndex;
		return(&(curr->key));
	    }
	return((long *)TRUE);
    default:
	/* can't get here */
	return (NULL);
    }
    
    /* 
      If we got here, then we didn't find the element and
      we have to insert it into the hash table
      */
    Assert(currIndex == INVALID_INDEX);
    
    /* get the next free bucket */
    currIndex = hctl->freeBucketIndex;
    if (currIndex == INVALID_INDEX) {
	
	/* no free elements.  allocate another chunk of buckets */
	if (! bucket_alloc(hashp)) {
	    return(NULL);
	}
	currIndex = hctl->freeBucketIndex;
    }
    Assert(currIndex != INVALID_INDEX);
    
    curr = GET_BUCKET(hashp,currIndex);
    hctl->freeBucketIndex = curr->next;
    
    /* link into chain */
    *prevIndexPtr = currIndex;	
    
    /* copy key and data */
    destAddr = (char *) &(curr->key);
    memmove(destAddr,keyPtr,hctl->keysize);
    curr->next = INVALID_INDEX;
    
    /* let the caller initialize the data field after 
     * hash_search returns.
     */
    /*	memmove(destAddr,keyPtr,hctl->keysize+hctl->datasize);*/
    
    /*
     * Check if it is time to split the segment
     */
    if (++hctl->nkeys / (hctl->max_bucket+1) > hctl->ffactor) {
	/*
	  fprintf(stderr,"expanding on '%s'\n",keyPtr);
	  hash_stats("expanded table",hashp);
	  */
	if (! expand_table(hashp))
	    return(NULL);
    }
    return (&(curr->key));
}