⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpool_t.c

📁 一个关于memory pool 的实例
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Memory pool test program.
 *
 * Copyright 1996 by Gray Watson.
 *
 * This file is part of the mpool package.
 *
 * Permission to use, copy, modify, and distribute this software for
 * any purpose and without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all
 * copies, and that the name of Gray Watson not be used in advertising
 * or publicity pertaining to distribution of the document or software
 * without specific, written prior permission.
 *
 * Gray Watson makes no representations about the suitability of the
 * software described herein for any purpose.  It is provided "as is"
 * without express or implied warranty.
 *
 * The author may be reached via http://256.com/gray/
 *
 * $Id: mpool_t.c,v 1.2 2005/05/20 20:08:55 gray Exp $
 */

/*
 * Test program for the malloc library.  Current it is interactive although
 * should be script based.
 */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include "mpool.h"

#ifdef __GNUC__
#ident "$Id: mpool_t.c,v 1.2 2005/05/20 20:08:55 gray Exp $"
#else
static char *rcs_id = "$Id: mpool_t.c,v 1.2 2005/05/20 20:08:55 gray Exp $";
#endif

#define DEFAULT_ITERATIONS	10000
#define MAX_POINTERS		1024
#define MAX_ALLOC		(1024 * 1024)
#define MIN_AVAIL		10

#define RANDOM_VALUE(x)		((random() % ((x) * 10)) / 10)

/* pointer tracking structure */
struct pnt_info_st {
  long			pi_crc;			/* crc of storage */
  long			pi_size;		/* size of storage */
  void			*pi_pnt;		/* pnt to storage */
  struct pnt_info_st	*pi_next;		/* pnt to next */
};

typedef struct pnt_info_st pnt_info_t;

static	pnt_info_t	*pointer_grid;

/* argument variables */
static	int		best_fit_b = 0;			/* set best fit flag */
static	int		heavy_pack_b = 0;		/* set heavy pack flg*/
static	int		interactive_b = 0;		/* interactive flag */
static	int		log_trxn_b = 0; 		/* log mem trxns */
static	long		max_alloc = MAX_ALLOC;		/* amt of mem to use */
static	int		max_pages_n = 0;		/* max # pages */
static	int		use_malloc_b = 0; 		/* use system alloc */
static	int		max_pointers = MAX_POINTERS;	/* # of pnts to use */
static	int		no_free_b = 0;			/* set no free flag */
static	long		page_size = 0;			/* mpool pagesize */
static	int		use_sbrk_b = 0;			/* use sbrk not mmap */
static	unsigned int	seed_random = 0;		/* random seed */
static	int		default_iter_n = DEFAULT_ITERATIONS; /* # of iters */
static	int		verbose_b = 0;			/* verbose flag */

/*
 * static long hex_to_long
 *
 * DESCRIPTION:
 *
 * Hexadecimal string to integer translation.
 *
 * RETURNS:
 *
 * Long value of converted hex string.
 *
 * ARGUMENTS:
 *
 * str -> Hex string we are converting.
 */
static	long	hex_to_long(const char *str)
{
  long		ret;
  const char	*str_p = str;
  
  /* strip off spaces */
  for (; *str_p == ' ' || *str_p == '\t'; str_p++) {
  }
  
  /* skip a leading 0[xX] */
  if (*str_p == '0' && (*(str_p + 1) == 'x' || *(str_p + 1) == 'X')) {
    str_p += 2;
  }
  
  for (ret = 0;; str_p++) {
    if (*str_p >= '0' && *str_p <= '9') {
      ret = ret * 16 + (*str_p - '0');
    }
    else if (*str_p >= 'a' && *str_p <= 'f') {
      ret = ret * 16 + (*str_p - 'a' + 10);
    }
    else if (*str_p >= 'A' && *str_p <= 'F') {
      ret = ret * 16 + (*str_p - 'A' + 10);
    }
    else {
      break;
    }
  }
  
  return ret;
}

/*
 * static void* get_address
 *
 * DESCRIPTION:
 *
 * Read an address from the user.
 *
 * RETURNS:
 *
 * Address read in from user.
 *
 * ARGUMENTS:
 *
 * None.
 */
static	void	*get_address(void)
{
  char	line[80];
  void	*pnt;
  
  do {
    (void)printf("Enter a hex address: ");
    if (fgets(line, sizeof(line), stdin) == NULL) {
      return NULL;
    }
  } while (line[0] == '\0');
  
  pnt = (void *)hex_to_long(line);
  
  return pnt;
}

/*
 * static void do_random
 *
 * DESCRIPTION:
 *
 * Try ITER_N random program iterations, returns 1 on success else 0
 *
 * RETURNS:
 *
 * None.
 *
 * ARGUMENTS:
 *
 * pool <-> Out memory pool.
 *
 * iter_n -> Number of iterations to run.
 */
static	void	do_random(mpool_t *pool, const int iter_n)
{
  int		iter_c, free_c, ret;
  long		max = max_alloc, amount;
  char		*chunk_p;
  void		*new_pnt;
  pnt_info_t	*free_p, *used_p = NULL;
  pnt_info_t	*pnt_p, *last_p;
  
  if (use_malloc_b) {
    pointer_grid = (pnt_info_t *)malloc(sizeof(pnt_info_t) * max_pointers);
  }
  else {
    pointer_grid = (pnt_info_t *)mpool_alloc(pool,
					     sizeof(pnt_info_t) * max_pointers,
					     &ret);
  }
  if (pointer_grid == NULL) {
    (void)printf("mpool_t: problems allocating %d pointer slots: %s\n",
		 max_pointers, strerror(errno));
    return;
  }
  
  /* initialize free list */
  free_p = pointer_grid;
  for (pnt_p = pointer_grid; pnt_p < pointer_grid + max_pointers; pnt_p++) {
    pnt_p->pi_size = 0;
    pnt_p->pi_pnt = NULL;
    pnt_p->pi_next = pnt_p + 1;
  }
  /* redo the last next pointer */
  (pnt_p - 1)->pi_next = NULL;
  free_c = max_pointers;
  
  for (iter_c = 0; iter_c < iter_n;) {
    int		which;
    
    /* special case when doing non-linear stuff, sbrk took all memory */
    if (max < MIN_AVAIL && free_c == max_pointers) {
      break;
    }
    
    if (free_c < max_pointers && used_p == NULL) {
      (void)fprintf(stderr, "mpool_t: problem with test program free list\n");
      exit(1);
    }
    
    /* decide whether to malloc a new pointer or free/realloc an existing */
    which = RANDOM_VALUE(4);
    
    /*
     * < MIN_AVAIL means alloc as long as we have enough memory and
     * there are free slots we do an allocation, else we free
     */
    if (free_c == max_pointers
	|| (free_c > 0 && which < 3 && max >= MIN_AVAIL)) {
      
      while (1) {
	amount = RANDOM_VALUE(max / 2);
	if (amount > 0) {
	  break;
	}
      }
      which = RANDOM_VALUE(9);
      pnt_p = NULL;
      
      switch (which) {
	
      case 0: case 1: case 2:
	pnt_p = free_p;
	if (use_malloc_b) {
	  pnt_p->pi_pnt = malloc(amount);
	}
	else {
	  pnt_p->pi_pnt = mpool_alloc(pool, amount, &ret);
	}
	
	if (verbose_b) {
	  (void)printf("%d: malloc %ld (max %ld) into slot %d.  got %#lx\n",
		       iter_c + 1, amount, max, pnt_p - pointer_grid,
		       (long)pnt_p->pi_pnt);
	}
	
	if (pnt_p->pi_pnt == NULL) {
	  (void)printf("malloc of %ld failed: %s\n",
		       amount,
		       (use_malloc_b ? strerror(errno) : mpool_strerror(ret)));
	}
	pnt_p->pi_size = amount;
	break;
	
      case 3: case 4: case 5:
	pnt_p = free_p;
	if (use_malloc_b) {
	  pnt_p->pi_pnt = calloc(amount, sizeof(char));
	}
	else {
	  pnt_p->pi_pnt = mpool_calloc(pool, amount, sizeof(char), &ret);
	}
	
	if (verbose_b) {
	  (void)printf("%d: calloc %ld (max %ld) into slot %d.  got %#lx\n",
		       iter_c + 1, amount, max, pnt_p - pointer_grid,
		       (long)pnt_p->pi_pnt);
	}
	
	/* test the returned block to make sure that is has been cleared */
	if (pnt_p->pi_pnt == NULL) {
	  (void)printf("calloc of %ld failed: %s\n",
		       amount,
		       (use_malloc_b ? strerror(errno) : mpool_strerror(ret)));
	}
	else {
	  for (chunk_p = pnt_p->pi_pnt;
	       chunk_p < (char *)pnt_p->pi_pnt + amount;
	       chunk_p++) {
	    if (*chunk_p != '\0') {
	      (void)printf("calloc of %ld not zeroed on iteration #%d\n",
			   amount, iter_c + 1);
	      break;
	    }
	  }
	  pnt_p->pi_size = amount;
	}
	break;

      case 6: case 7: case 8:
	if (free_c == max_pointers) {
	  continue;
	}
	
	which = RANDOM_VALUE(max_pointers - free_c);
	for (pnt_p = used_p; which > 0; which--) {
	  pnt_p = pnt_p->pi_next;
	}
	
	if (use_malloc_b) {
	  new_pnt = realloc(pnt_p->pi_pnt, amount);
	}
	else {
	  new_pnt = mpool_resize(pool, pnt_p->pi_pnt, pnt_p->pi_size, amount,
				 &ret);
	}
	
	if (verbose_b) {
	  (void)printf("%d: resize %#lx from %ld to %ld (max %ld) slot %d. "
		       "got %#lx\n",
		       iter_c + 1, (long)pnt_p->pi_pnt, pnt_p->pi_size, amount,
		       max, pnt_p - pointer_grid, (long)new_pnt);
	}
	
	if (new_pnt == NULL) {
	  (void)printf("resize of %#lx old size %ld new size %ld failed: %s\n",
		       (long)pnt_p->pi_pnt, pnt_p->pi_size, amount,
		       (use_malloc_b ? strerror(errno) : mpool_strerror(ret)));
	  pnt_p->pi_pnt = NULL;
	  pnt_p->pi_size = 0;
	}
	else {
	  /* we effectively freed the old memory */
	  max += pnt_p->pi_size;
	  pnt_p->pi_pnt = new_pnt;
	  pnt_p->pi_size = amount;
	}
	break;
	
      default:
	break;
      }
      
      if (pnt_p != NULL && pnt_p->pi_pnt != NULL) {
	if (pnt_p == free_p) {
	  free_p = pnt_p->pi_next;
	  pnt_p->pi_next = used_p;
	  used_p = pnt_p;
	  free_c--;
	}
	
	max -= amount;
	iter_c++;
      }
      continue;
    }
    
    /*
     * choose a rand slot to free and make sure it is not a free-slot
     */
    which = RANDOM_VALUE(max_pointers - free_c);
    /* find pnt in the used list */
    last_p = NULL;
    for (pnt_p = used_p, last_p = NULL;
	 pnt_p != NULL && which > 0;
	 last_p = pnt_p, pnt_p = pnt_p->pi_next, which--) {
    }
    if (pnt_p == NULL) {
      /* huh? error here */
      abort();
    }
    if (last_p == NULL) {
      used_p = pnt_p->pi_next;
    }
    else {
      last_p->pi_next = pnt_p->pi_next;
    }
    
    if (use_malloc_b) {
      free(pnt_p->pi_pnt);
    }
    else {
      ret = mpool_free(pool, pnt_p->pi_pnt, pnt_p->pi_size);
      if (ret != MPOOL_ERROR_NONE) {
	(void)printf("free error on pointer '%#lx' of size %ld: %s\n",
		     (long)pnt_p->pi_pnt, pnt_p->pi_size,
		     mpool_strerror(ret));
      }
    }
    
    if (verbose_b) {
      (void)printf("%d: free'd %ld bytes from slot %d (%#lx)\n",
		   iter_c + 1, pnt_p->pi_size, pnt_p - pointer_grid,
		   (long)pnt_p->pi_pnt);
    }
    
    pnt_p->pi_pnt = NULL;
    pnt_p->pi_next = free_p;
    free_p = pnt_p;
    free_c++;
    
    max += pnt_p->pi_size;
    iter_c++;
  }
  
  /* free used pointers */
  for (pnt_p = pointer_grid; pnt_p < pointer_grid + max_pointers; pnt_p++) {
    if (pnt_p->pi_pnt != NULL) {
      if (use_malloc_b) {
	free(pnt_p->pi_pnt);
      }
      else {
	ret = mpool_free(pool, pnt_p->pi_pnt, pnt_p->pi_size);
	if (ret != MPOOL_ERROR_NONE) {
	  (void)printf("free error on pointer '%#lx' of size %ld: %s\n",
		       (long)pnt_p->pi_pnt, pnt_p->pi_size,
		       mpool_strerror(ret));
	}
      }
    }
  }
  
  if (use_malloc_b) {
    free(pointer_grid);
  }
  else {
    ret = mpool_free(pool, pointer_grid, sizeof(pnt_info_t) * max_pointers);
    if (ret != MPOOL_ERROR_NONE) {
      (void)printf("free error on grid pointer: %s\n", mpool_strerror(ret));
    }
  }
}

/*
 * static void do_interactive
 *
 * DESCRIPTION:
 *
 * Run the interactive section of the program.
 *
 * RETURNS:
 *
 * None.
 *
 * ARGUMENTS:
 *
 * pool <-> Out memory pool.
 */
static	void	do_interactive(mpool_t *pool)
{
  int		len, ret;
  char		line[128], *line_p;
  void		*pnt, *new_pnt;
  
  (void)printf("Mpool test program.  Type 'help' for assistance.\n");
  
  for (;;) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -