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

📄 jmemmgr.c

📁 EVM板JPEG实现,Texas Instruments TMS320C54x EVM JPEG
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * jmemmgr.c
 *
 * Copyright (C) 1991, 1992, Thomas G. Lane.
 * This file is part of the Independent JPEG Group's software.
 * For conditions of distribution and use, see the accompanying README file.
 *
 * This file provides the standard system-independent memory management
 * routines.  This code is usable across a wide variety of machines; most
 * of the system dependencies have been isolated in a separate file.
 * The major functions provided here are:
 *   * bookkeeping to allow all allocated memory to be freed upon exit;
 *   * policy decisions about how to divide available memory among the
 *     various large arrays;
 *   * control logic for swapping virtual arrays between main memory and
 *     backing storage.
 * The separate system-dependent file provides the actual backing-storage
 * access code, and it contains the policy decision about how much total
 * main memory to use.
 * This file is system-dependent in the sense that some of its functions
 * are unnecessary in some systems.  For example, if there is enough virtual
 * memory so that backing storage will never be used, much of the big-array
 * control logic could be removed.  (Of course, if you have that much memory
 * then you shouldn't care about a little bit of unused code...)
 *
 * These routines are invoked via the methods alloc_small, free_small,
 * alloc_medium, free_medium, alloc_small_sarray, free_small_sarray,
 * alloc_small_barray, free_small_barray, request_big_sarray,
 * request_big_barray, alloc_big_arrays, access_big_sarray, access_big_barray,
 * free_big_sarray, free_big_barray, and free_all.
 */

/* This code was changed to eliminate the error messages.  Christopher Chang,
   Summer, 1993. 
*/

#define NO_GETENV
#define AM_MEMORY_MANAGER       /* we define big_Xarray_control structs */

#include "jinclude.h"
#include "jmemsys.h"            /* import the system-dependent declarations */

#ifndef NO_GETENV
#ifdef INCLUDES_ARE_ANSI
#include <stdlib.h>             /* to declare getenv() */
#else
extern char * getenv PP((const char * name));
#endif
#endif


/*
 * On many systems it is not necessary to distinguish alloc_small from
 * alloc_medium; the main case where they must be distinguished is when
 * FAR pointers are distinct from regular pointers.  However, you might
 * want to keep them separate if you have different system-dependent logic
 * for small and large memory requests (i.e., jget_small and jget_large
 * do different things).
 */

#ifdef NEED_FAR_POINTERS
#define NEED_ALLOC_MEDIUM       /* flags alloc_medium really exists */
#endif


/*
 * Many machines require storage alignment: longs must start on 4-byte
 * boundaries, doubles on 8-byte boundaries, etc.  On such machines, malloc()
 * always returns pointers that are multiples of the worst-case alignment
 * requirement, and we had better do so too.  This means the headers that
 * we tack onto allocated structures had better have length a multiple of
 * the alignment requirement.
 * There isn't any really portable way to determine the worst-case alignment
 * requirement.  In this code we assume that the alignment requirement is
 * multiples of sizeof(align_type).  Here we define align_type as double;
 * with this definition, the code will run on all machines known to me.
 * If your machine has lesser alignment needs, you can save a few bytes
 * by making align_type smaller.
 */

typedef double align_type;


/*
 * Some important notes:
 *   The allocation routines provided here must never return NULL.
 *   They should exit to error_exit if unsuccessful.
 *
 *   It's not a good idea to try to merge the sarray and barray routines,
 *   even though they are textually almost the same, because samples are
 *   usually stored as bytes while coefficients are shorts.  Thus, in machines
 *   where byte pointers have a different representation from word pointers,
 *   the resulting machine code could not be the same.
 */


static external_methods_ptr methods; /* saved for access to error_exit */


#ifdef MEM_STATS                /* optional extra stuff for statistics */

/* These macros are the assumed overhead per block for malloc().
 * They don't have to be accurate, but the printed statistics will be
 * off a little bit if they are not.
 */
#define MALLOC_OVERHEAD  (SIZEOF(void *)) /* overhead for jget_small() */
#define MALLOC_FAR_OVERHEAD  (SIZEOF(void FAR *)) /* for jget_large() */

static long total_num_small = 0;        /* total # of small objects alloced */
static long total_bytes_small = 0;      /* total bytes requested */
static long cur_num_small = 0;          /* # currently alloced */
static long max_num_small = 0;          /* max simultaneously alloced */

#ifdef NEED_ALLOC_MEDIUM
static long total_num_medium = 0;       /* total # of medium objects alloced */
static long total_bytes_medium = 0;     /* total bytes requested */
static long cur_num_medium = 0;         /* # currently alloced */
static long max_num_medium = 0;         /* max simultaneously alloced */
#endif

static long total_num_sarray = 0;       /* total # of sarray objects alloced */
static long total_bytes_sarray = 0;     /* total bytes requested */
static long cur_num_sarray = 0;         /* # currently alloced */
static long max_num_sarray = 0;         /* max simultaneously alloced */

static long total_num_barray = 0;       /* total # of barray objects alloced */
static long total_bytes_barray = 0;     /* total bytes requested */
static long cur_num_barray = 0;         /* # currently alloced */
static long max_num_barray = 0;         /* max simultaneously alloced */


LOCAL void
print_mem_stats (void)
{
  /* since this is only a debugging stub, we can cheat a little on the
   * trace message mechanism... helpful 'cuz trace_message can't handle longs.
   */
/*  fprintf(stderr, "total_num_small = %ld\n", total_num_small);
  fprintf(stderr, "total_bytes_small = %ld\n", total_bytes_small);
  if (cur_num_small)
	fprintf(stderr, "cur_num_small = %ld\n", cur_num_small);
  fprintf(stderr, "max_num_small = %ld\n", max_num_small);
  
#ifdef NEED_ALLOC_MEDIUM
  fprintf(stderr, "total_num_medium = %ld\n", total_num_medium);
  fprintf(stderr, "total_bytes_medium = %ld\n", total_bytes_medium);
  if (cur_num_medium)
	fprintf(stderr, "cur_num_medium = %ld\n", cur_num_medium);
  fprintf(stderr, "max_num_medium = %ld\n", max_num_medium);
#endif
  
  fprintf(stderr, "total_num_sarray = %ld\n", total_num_sarray);
  fprintf(stderr, "total_bytes_sarray = %ld\n", total_bytes_sarray);
  if (cur_num_sarray)
	fprintf(stderr, "cur_num_sarray = %ld\n", cur_num_sarray);
  fprintf(stderr, "max_num_sarray = %ld\n", max_num_sarray);
  
  fprintf(stderr, "total_num_barray = %ld\n", total_num_barray);
  fprintf(stderr, "total_bytes_barray = %ld\n", total_bytes_barray);
  if (cur_num_barray)
	fprintf(stderr, "cur_num_barray = %ld\n", cur_num_barray);
  fprintf(stderr, "max_num_barray = %ld\n", max_num_barray); */
}

#endif /* MEM_STATS */


LOCAL void
out_of_memory (int which)
/* Report an out-of-memory error and stop execution */
/* If we compiled MEM_STATS support, report alloc requests before dying */
{
#ifdef MEM_STATS
  if (methods->trace_level <= 0) /* don't do it if free_all() will */
	print_mem_stats();          /* print optional memory usage statistics */
#endif
	send_command(ERR3);
	receive_command();
	exit();
/* ERREXIT1(methods, "Insufficient memory (case %d)", which); */
}


/*
 * Management of "small" objects.
 * These are all-in-memory, and are in near-heap space on an 80x86.
 */

typedef union small_struct * small_ptr;

typedef union small_struct {
	small_ptr next;         /* next in list of allocated objects */
	align_type dummy;       /* ensures alignment of following storage */
	  } small_hdr;

static small_ptr small_list;    /* head of list */


METHODDEF void *
alloc_small (size_t sizeofobject)
/* Allocate a "small" object */
{
  small_ptr result;

  sizeofobject += SIZEOF(small_hdr); /* add space for header */

#ifdef MEM_STATS
  total_num_small++;
  total_bytes_small += sizeofobject + MALLOC_OVERHEAD;
  cur_num_small++;
  if (cur_num_small > max_num_small) max_num_small = cur_num_small;
#endif

  result = (small_ptr) jget_small(sizeofobject);
  if (result == NULL)
	out_of_memory(1);

  result->next = small_list;
  small_list = result;
  result++;                     /* advance past header */

  return (void *) result;
}


METHODDEF void
free_small (void *ptr)
/* Free a "small" object */
{
  small_ptr hdr;
  small_ptr * llink;

  hdr = (small_ptr) ptr;
  hdr--;                        /* point back to header */

  /* Remove item from list -- linear search is fast enough */
  llink = &small_list;
  while (*llink != hdr) {
	llink = &( (*llink)->next );
  }
  *llink = hdr->next;

  jfree_small((void *) hdr);

#ifdef MEM_STATS
  cur_num_small--;
#endif
}


/*
 * Management of "medium-size" objects.
 * These are just like small objects except they are in the FAR heap.
 */

#ifdef NEED_ALLOC_MEDIUM

typedef union medium_struct FAR * medium_ptr;

typedef union medium_struct {
	medium_ptr next;        /* next in list of allocated objects */
	align_type dummy;       /* ensures alignment of following storage */
	  } medium_hdr;

static medium_ptr medium_list;  /* head of list */


METHODDEF void FAR *
alloc_medium (size_t sizeofobject)
/* Allocate a "medium-size" object */
{
  medium_ptr result;

  sizeofobject += SIZEOF(medium_hdr); /* add space for header */

#ifdef MEM_STATS
  total_num_medium++;
  total_bytes_medium += sizeofobject + MALLOC_FAR_OVERHEAD;
  cur_num_medium++;
  if (cur_num_medium > max_num_medium) max_num_medium = cur_num_medium;
#endif

  result = (medium_ptr) jget_large(sizeofobject);
  if (result == NULL)
	out_of_memory(2);

  result->next = medium_list;
  medium_list = result;
  result++;                     /* advance past header */

  return (void FAR *) result;
}


METHODDEF void
free_medium (void FAR *ptr)
/* Free a "medium-size" object */
{
  medium_ptr hdr;
  medium_ptr FAR * llink;

  hdr = (medium_ptr) ptr;
  hdr--;                        /* point back to header */

  /* Remove item from list -- linear search is fast enough */
  llink = &medium_list;
  while (*llink != hdr) {
	llink = &( (*llink)->next );
  }
  *llink = hdr->next;

  jfree_large((void FAR *) hdr);

#ifdef MEM_STATS
  cur_num_medium--;
#endif
}

#endif /* NEED_ALLOC_MEDIUM */


/*
 * Management of "small" (all-in-memory) 2-D sample arrays.
 * The pointers are in near heap, the samples themselves in FAR heap.
 * The header structure is adjacent to the row pointers.
 * To minimize allocation overhead and to allow I/O of large contiguous
 * blocks, we allocate the sample rows in groups of as many rows as possible
 * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request.
 * Note that the big-array control routines, later in this file, know about
 * this chunking of rows ... and also how to get the rowsperchunk value!
 */

typedef struct small_sarray_struct * small_sarray_ptr;

typedef struct small_sarray_struct {
	small_sarray_ptr next;  /* next in list of allocated sarrays */
	long numrows;           /* # of rows in this array */
	long rowsperchunk;      /* max # of rows per allocation chunk */
	JSAMPROW dummy;         /* ensures alignment of following storage */
	  } small_sarray_hdr;

static small_sarray_ptr small_sarray_list; /* head of list */


METHODDEF JSAMPARRAY
alloc_small_sarray (long samplesperrow, long numrows)
/* Allocate a "small" (all-in-memory) 2-D sample array */
{
  small_sarray_ptr hdr;
  JSAMPARRAY result;
  JSAMPROW workspace;
  long rowsperchunk, currow, i;

#ifdef MEM_STATS
  total_num_sarray++;
  cur_num_sarray++;
  if (cur_num_sarray > max_num_sarray) max_num_sarray = cur_num_sarray;
#endif

  /* Calculate max # of rows allowed in one allocation chunk */
  rowsperchunk = MAX_ALLOC_CHUNK / (samplesperrow * SIZEOF(JSAMPLE));
  /* Get space for header and row pointers; this is always "near" on 80x86 */

⌨️ 快捷键说明

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