Home | History | Annotate | Download | only in libjpeg-turbo
      1 /*
      2  * jmemmgr.c
      3  *
      4  * This file was part of the Independent JPEG Group's software:
      5  * Copyright (C) 1991-1997, Thomas G. Lane.
      6  * It was modified by The libjpeg-turbo Project to include only code and
      7  * information relevant to libjpeg-turbo.
      8  * For conditions of distribution and use, see the accompanying README file.
      9  *
     10  * This file contains the JPEG system-independent memory management
     11  * routines.  This code is usable across a wide variety of machines; most
     12  * of the system dependencies have been isolated in a separate file.
     13  * The major functions provided here are:
     14  *   * pool-based allocation and freeing of memory;
     15  *   * policy decisions about how to divide available memory among the
     16  *     virtual arrays;
     17  *   * control logic for swapping virtual arrays between main memory and
     18  *     backing storage.
     19  * The separate system-dependent file provides the actual backing-storage
     20  * access code, and it contains the policy decision about how much total
     21  * main memory to use.
     22  * This file is system-dependent in the sense that some of its functions
     23  * are unnecessary in some systems.  For example, if there is enough virtual
     24  * memory so that backing storage will never be used, much of the virtual
     25  * array control logic could be removed.  (Of course, if you have that much
     26  * memory then you shouldn't care about a little bit of unused code...)
     27  */
     28 
     29 #define JPEG_INTERNALS
     30 #define AM_MEMORY_MANAGER       /* we define jvirt_Xarray_control structs */
     31 #include "jinclude.h"
     32 #include "jpeglib.h"
     33 #include "jmemsys.h"            /* import the system-dependent declarations */
     34 
     35 #ifndef NO_GETENV
     36 #ifndef HAVE_STDLIB_H           /* <stdlib.h> should declare getenv() */
     37 extern char * getenv (const char * name);
     38 #endif
     39 #endif
     40 
     41 
     42 LOCAL(size_t)
     43 round_up_pow2 (size_t a, size_t b)
     44 /* a rounded up to the next multiple of b, i.e. ceil(a/b)*b */
     45 /* Assumes a >= 0, b > 0, and b is a power of 2 */
     46 {
     47   return ((a + b - 1) & (~(b - 1)));
     48 }
     49 
     50 
     51 /*
     52  * Some important notes:
     53  *   The allocation routines provided here must never return NULL.
     54  *   They should exit to error_exit if unsuccessful.
     55  *
     56  *   It's not a good idea to try to merge the sarray and barray routines,
     57  *   even though they are textually almost the same, because samples are
     58  *   usually stored as bytes while coefficients are shorts or ints.  Thus,
     59  *   in machines where byte pointers have a different representation from
     60  *   word pointers, the resulting machine code could not be the same.
     61  */
     62 
     63 
     64 /*
     65  * Many machines require storage alignment: longs must start on 4-byte
     66  * boundaries, doubles on 8-byte boundaries, etc.  On such machines, malloc()
     67  * always returns pointers that are multiples of the worst-case alignment
     68  * requirement, and we had better do so too.
     69  * There isn't any really portable way to determine the worst-case alignment
     70  * requirement.  This module assumes that the alignment requirement is
     71  * multiples of ALIGN_SIZE.
     72  * By default, we define ALIGN_SIZE as sizeof(double).  This is necessary on some
     73  * workstations (where doubles really do need 8-byte alignment) and will work
     74  * fine on nearly everything.  If your machine has lesser alignment needs,
     75  * you can save a few bytes by making ALIGN_SIZE smaller.
     76  * The only place I know of where this will NOT work is certain Macintosh
     77  * 680x0 compilers that define double as a 10-byte IEEE extended float.
     78  * Doing 10-byte alignment is counterproductive because longwords won't be
     79  * aligned well.  Put "#define ALIGN_SIZE 4" in jconfig.h if you have
     80  * such a compiler.
     81  */
     82 
     83 #ifndef ALIGN_SIZE              /* so can override from jconfig.h */
     84 #ifndef WITH_SIMD
     85 #define ALIGN_SIZE  sizeof(double)
     86 #else
     87 #define ALIGN_SIZE  16 /* Most SIMD implementations require this */
     88 #endif
     89 #endif
     90 
     91 /*
     92  * We allocate objects from "pools", where each pool is gotten with a single
     93  * request to jpeg_get_small() or jpeg_get_large().  There is no per-object
     94  * overhead within a pool, except for alignment padding.  Each pool has a
     95  * header with a link to the next pool of the same class.
     96  * Small and large pool headers are identical.
     97  */
     98 
     99 typedef struct small_pool_struct * small_pool_ptr;
    100 
    101 typedef struct small_pool_struct {
    102   small_pool_ptr next;  /* next in list of pools */
    103   size_t bytes_used;            /* how many bytes already used within pool */
    104   size_t bytes_left;            /* bytes still available in this pool */
    105 } small_pool_hdr;
    106 
    107 typedef struct large_pool_struct * large_pool_ptr;
    108 
    109 typedef struct large_pool_struct {
    110   large_pool_ptr next;  /* next in list of pools */
    111   size_t bytes_used;            /* how many bytes already used within pool */
    112   size_t bytes_left;            /* bytes still available in this pool */
    113 } large_pool_hdr;
    114 
    115 /*
    116  * Here is the full definition of a memory manager object.
    117  */
    118 
    119 typedef struct {
    120   struct jpeg_memory_mgr pub;   /* public fields */
    121 
    122   /* Each pool identifier (lifetime class) names a linked list of pools. */
    123   small_pool_ptr small_list[JPOOL_NUMPOOLS];
    124   large_pool_ptr large_list[JPOOL_NUMPOOLS];
    125 
    126   /* Since we only have one lifetime class of virtual arrays, only one
    127    * linked list is necessary (for each datatype).  Note that the virtual
    128    * array control blocks being linked together are actually stored somewhere
    129    * in the small-pool list.
    130    */
    131   jvirt_sarray_ptr virt_sarray_list;
    132   jvirt_barray_ptr virt_barray_list;
    133 
    134   /* This counts total space obtained from jpeg_get_small/large */
    135   size_t total_space_allocated;
    136 
    137   /* alloc_sarray and alloc_barray set this value for use by virtual
    138    * array routines.
    139    */
    140   JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */
    141 } my_memory_mgr;
    142 
    143 typedef my_memory_mgr * my_mem_ptr;
    144 
    145 
    146 /*
    147  * The control blocks for virtual arrays.
    148  * Note that these blocks are allocated in the "small" pool area.
    149  * System-dependent info for the associated backing store (if any) is hidden
    150  * inside the backing_store_info struct.
    151  */
    152 
    153 struct jvirt_sarray_control {
    154   JSAMPARRAY mem_buffer;        /* => the in-memory buffer */
    155   JDIMENSION rows_in_array;     /* total virtual array height */
    156   JDIMENSION samplesperrow;     /* width of array (and of memory buffer) */
    157   JDIMENSION maxaccess;         /* max rows accessed by access_virt_sarray */
    158   JDIMENSION rows_in_mem;       /* height of memory buffer */
    159   JDIMENSION rowsperchunk;      /* allocation chunk size in mem_buffer */
    160   JDIMENSION cur_start_row;     /* first logical row # in the buffer */
    161   JDIMENSION first_undef_row;   /* row # of first uninitialized row */
    162   boolean pre_zero;             /* pre-zero mode requested? */
    163   boolean dirty;                /* do current buffer contents need written? */
    164   boolean b_s_open;             /* is backing-store data valid? */
    165   jvirt_sarray_ptr next;        /* link to next virtual sarray control block */
    166   backing_store_info b_s_info;  /* System-dependent control info */
    167 };
    168 
    169 struct jvirt_barray_control {
    170   JBLOCKARRAY mem_buffer;       /* => the in-memory buffer */
    171   JDIMENSION rows_in_array;     /* total virtual array height */
    172   JDIMENSION blocksperrow;      /* width of array (and of memory buffer) */
    173   JDIMENSION maxaccess;         /* max rows accessed by access_virt_barray */
    174   JDIMENSION rows_in_mem;       /* height of memory buffer */
    175   JDIMENSION rowsperchunk;      /* allocation chunk size in mem_buffer */
    176   JDIMENSION cur_start_row;     /* first logical row # in the buffer */
    177   JDIMENSION first_undef_row;   /* row # of first uninitialized row */
    178   boolean pre_zero;             /* pre-zero mode requested? */
    179   boolean dirty;                /* do current buffer contents need written? */
    180   boolean b_s_open;             /* is backing-store data valid? */
    181   jvirt_barray_ptr next;        /* link to next virtual barray control block */
    182   backing_store_info b_s_info;  /* System-dependent control info */
    183 };
    184 
    185 
    186 #ifdef MEM_STATS                /* optional extra stuff for statistics */
    187 
    188 LOCAL(void)
    189 print_mem_stats (j_common_ptr cinfo, int pool_id)
    190 {
    191   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
    192   small_pool_ptr shdr_ptr;
    193   large_pool_ptr lhdr_ptr;
    194 
    195   /* Since this is only a debugging stub, we can cheat a little by using
    196    * fprintf directly rather than going through the trace message code.
    197    * This is helpful because message parm array can't handle longs.
    198    */
    199   fprintf(stderr, "Freeing pool %d, total space = %ld\n",
    200           pool_id, mem->total_space_allocated);
    201 
    202   for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
    203        lhdr_ptr = lhdr_ptr->next) {
    204     fprintf(stderr, "  Large chunk used %ld\n",
    205             (long) lhdr_ptr->bytes_used);
    206   }
    207 
    208   for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
    209        shdr_ptr = shdr_ptr->next) {
    210     fprintf(stderr, "  Small chunk used %ld free %ld\n",
    211             (long) shdr_ptr->bytes_used,
    212             (long) shdr_ptr->bytes_left);
    213   }
    214 }
    215 
    216 #endif /* MEM_STATS */
    217 
    218 
    219 LOCAL(void)
    220 out_of_memory (j_common_ptr cinfo, int which)
    221 /* Report an out-of-memory error and stop execution */
    222 /* If we compiled MEM_STATS support, report alloc requests before dying */
    223 {
    224 #ifdef MEM_STATS
    225   cinfo->err->trace_level = 2;  /* force self_destruct to report stats */
    226 #endif
    227   ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
    228 }
    229 
    230 
    231 /*
    232  * Allocation of "small" objects.
    233  *
    234  * For these, we use pooled storage.  When a new pool must be created,
    235  * we try to get enough space for the current request plus a "slop" factor,
    236  * where the slop will be the amount of leftover space in the new pool.
    237  * The speed vs. space tradeoff is largely determined by the slop values.
    238  * A different slop value is provided for each pool class (lifetime),
    239  * and we also distinguish the first pool of a class from later ones.
    240  * NOTE: the values given work fairly well on both 16- and 32-bit-int
    241  * machines, but may be too small if longs are 64 bits or more.
    242  *
    243  * Since we do not know what alignment malloc() gives us, we have to
    244  * allocate ALIGN_SIZE-1 extra space per pool to have room for alignment
    245  * adjustment.
    246  */
    247 
    248 static const size_t first_pool_slop[JPOOL_NUMPOOLS] =
    249 {
    250         1600,                   /* first PERMANENT pool */
    251         16000                   /* first IMAGE pool */
    252 };
    253 
    254 static const size_t extra_pool_slop[JPOOL_NUMPOOLS] =
    255 {
    256         0,                      /* additional PERMANENT pools */
    257         5000                    /* additional IMAGE pools */
    258 };
    259 
    260 #define MIN_SLOP  50            /* greater than 0 to avoid futile looping */
    261 
    262 
    263 METHODDEF(void *)
    264 alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
    265 /* Allocate a "small" object */
    266 {
    267   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
    268   small_pool_ptr hdr_ptr, prev_hdr_ptr;
    269   char * data_ptr;
    270   size_t min_request, slop;
    271 
    272   /*
    273    * Round up the requested size to a multiple of ALIGN_SIZE in order
    274    * to assure alignment for the next object allocated in the same pool
    275    * and so that algorithms can straddle outside the proper area up
    276    * to the next alignment.
    277    */
    278   sizeofobject = round_up_pow2(sizeofobject, ALIGN_SIZE);
    279 
    280   /* Check for unsatisfiable request (do now to ensure no overflow below) */
    281   if ((sizeof(small_pool_hdr) + sizeofobject + ALIGN_SIZE - 1) > MAX_ALLOC_CHUNK)
    282     out_of_memory(cinfo, 1);    /* request exceeds malloc's ability */
    283 
    284   /* See if space is available in any existing pool */
    285   if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
    286     ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
    287   prev_hdr_ptr = NULL;
    288   hdr_ptr = mem->small_list[pool_id];
    289   while (hdr_ptr != NULL) {
    290     if (hdr_ptr->bytes_left >= sizeofobject)
    291       break;                    /* found pool with enough space */
    292     prev_hdr_ptr = hdr_ptr;
    293     hdr_ptr = hdr_ptr->next;
    294   }
    295 
    296   /* Time to make a new pool? */
    297   if (hdr_ptr == NULL) {
    298     /* min_request is what we need now, slop is what will be leftover */
    299     min_request = sizeof(small_pool_hdr) + sizeofobject + ALIGN_SIZE - 1;
    300     if (prev_hdr_ptr == NULL)   /* first pool in class? */
    301       slop = first_pool_slop[pool_id];
    302     else
    303       slop = extra_pool_slop[pool_id];
    304     /* Don't ask for more than MAX_ALLOC_CHUNK */
    305     if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
    306       slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
    307     /* Try to get space, if fail reduce slop and try again */
    308     for (;;) {
    309       hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
    310       if (hdr_ptr != NULL)
    311         break;
    312       slop /= 2;
    313       if (slop < MIN_SLOP)      /* give up when it gets real small */
    314         out_of_memory(cinfo, 2); /* jpeg_get_small failed */
    315     }
    316     mem->total_space_allocated += min_request + slop;
    317     /* Success, initialize the new pool header and add to end of list */
    318     hdr_ptr->next = NULL;
    319     hdr_ptr->bytes_used = 0;
    320     hdr_ptr->bytes_left = sizeofobject + slop;
    321     if (prev_hdr_ptr == NULL)   /* first pool in class? */
    322       mem->small_list[pool_id] = hdr_ptr;
    323     else
    324       prev_hdr_ptr->next = hdr_ptr;
    325   }
    326 
    327   /* OK, allocate the object from the current pool */
    328   data_ptr = (char *) hdr_ptr; /* point to first data byte in pool... */
    329   data_ptr += sizeof(small_pool_hdr); /* ...by skipping the header... */
    330   if ((size_t)data_ptr % ALIGN_SIZE) /* ...and adjust for alignment */
    331     data_ptr += ALIGN_SIZE - (size_t)data_ptr % ALIGN_SIZE;
    332   data_ptr += hdr_ptr->bytes_used; /* point to place for object */
    333   hdr_ptr->bytes_used += sizeofobject;
    334   hdr_ptr->bytes_left -= sizeofobject;
    335 
    336   return (void *) data_ptr;
    337 }
    338 
    339 
    340 /*
    341  * Allocation of "large" objects.
    342  *
    343  * The external semantics of these are the same as "small" objects.  However,
    344  * the pool management heuristics are quite different.  We assume that each
    345  * request is large enough that it may as well be passed directly to
    346  * jpeg_get_large; the pool management just links everything together
    347  * so that we can free it all on demand.
    348  * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY
    349  * structures.  The routines that create these structures (see below)
    350  * deliberately bunch rows together to ensure a large request size.
    351  */
    352 
    353 METHODDEF(void *)
    354 alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
    355 /* Allocate a "large" object */
    356 {
    357   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
    358   large_pool_ptr hdr_ptr;
    359   char * data_ptr;
    360 
    361   /*
    362    * Round up the requested size to a multiple of ALIGN_SIZE so that
    363    * algorithms can straddle outside the proper area up to the next
    364    * alignment.
    365    */
    366   sizeofobject = round_up_pow2(sizeofobject, ALIGN_SIZE);
    367 
    368   /* Check for unsatisfiable request (do now to ensure no overflow below) */
    369   if ((sizeof(large_pool_hdr) + sizeofobject + ALIGN_SIZE - 1) > MAX_ALLOC_CHUNK)
    370     out_of_memory(cinfo, 3);    /* request exceeds malloc's ability */
    371 
    372   /* Always make a new pool */
    373   if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
    374     ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
    375 
    376   hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
    377                                             sizeof(large_pool_hdr) +
    378                                             ALIGN_SIZE - 1);
    379   if (hdr_ptr == NULL)
    380     out_of_memory(cinfo, 4);    /* jpeg_get_large failed */
    381   mem->total_space_allocated += sizeofobject + sizeof(large_pool_hdr) + ALIGN_SIZE - 1;
    382 
    383   /* Success, initialize the new pool header and add to list */
    384   hdr_ptr->next = mem->large_list[pool_id];
    385   /* We maintain space counts in each pool header for statistical purposes,
    386    * even though they are not needed for allocation.
    387    */
    388   hdr_ptr->bytes_used = sizeofobject;
    389   hdr_ptr->bytes_left = 0;
    390   mem->large_list[pool_id] = hdr_ptr;
    391 
    392   data_ptr = (char *) hdr_ptr; /* point to first data byte in pool... */
    393   data_ptr += sizeof(small_pool_hdr); /* ...by skipping the header... */
    394   if ((size_t)data_ptr % ALIGN_SIZE) /* ...and adjust for alignment */
    395     data_ptr += ALIGN_SIZE - (size_t)data_ptr % ALIGN_SIZE;
    396 
    397   return (void *) data_ptr;
    398 }
    399 
    400 
    401 /*
    402  * Creation of 2-D sample arrays.
    403  *
    404  * To minimize allocation overhead and to allow I/O of large contiguous
    405  * blocks, we allocate the sample rows in groups of as many rows as possible
    406  * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request.
    407  * NB: the virtual array control routines, later in this file, know about
    408  * this chunking of rows.  The rowsperchunk value is left in the mem manager
    409  * object so that it can be saved away if this sarray is the workspace for
    410  * a virtual array.
    411  *
    412  * Since we are often upsampling with a factor 2, we align the size (not
    413  * the start) to 2 * ALIGN_SIZE so that the upsampling routines don't have
    414  * to be as careful about size.
    415  */
    416 
    417 METHODDEF(JSAMPARRAY)
    418 alloc_sarray (j_common_ptr cinfo, int pool_id,
    419               JDIMENSION samplesperrow, JDIMENSION numrows)
    420 /* Allocate a 2-D sample array */
    421 {
    422   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
    423   JSAMPARRAY result;
    424   JSAMPROW workspace;
    425   JDIMENSION rowsperchunk, currow, i;
    426   long ltemp;
    427 
    428   /* Make sure each row is properly aligned */
    429   if ((ALIGN_SIZE % sizeof(JSAMPLE)) != 0)
    430     out_of_memory(cinfo, 5);    /* safety check */
    431   samplesperrow = (JDIMENSION)round_up_pow2(samplesperrow, (2 * ALIGN_SIZE) / sizeof(JSAMPLE));
    432 
    433   /* Calculate max # of rows allowed in one allocation chunk */
    434   ltemp = (MAX_ALLOC_CHUNK-sizeof(large_pool_hdr)) /
    435           ((long) samplesperrow * sizeof(JSAMPLE));
    436   if (ltemp <= 0)
    437     ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
    438   if (ltemp < (long) numrows)
    439     rowsperchunk = (JDIMENSION) ltemp;
    440   else
    441     rowsperchunk = numrows;
    442   mem->last_rowsperchunk = rowsperchunk;
    443 
    444   /* Get space for row pointers (small object) */
    445   result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
    446                                     (size_t) (numrows * sizeof(JSAMPROW)));
    447 
    448   /* Get the rows themselves (large objects) */
    449   currow = 0;
    450   while (currow < numrows) {
    451     rowsperchunk = MIN(rowsperchunk, numrows - currow);
    452     workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
    453         (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
    454                   * sizeof(JSAMPLE)));
    455     for (i = rowsperchunk; i > 0; i--) {
    456       result[currow++] = workspace;
    457       workspace += samplesperrow;
    458     }
    459   }
    460 
    461   return result;
    462 }
    463 
    464 
    465 /*
    466  * Creation of 2-D coefficient-block arrays.
    467  * This is essentially the same as the code for sample arrays, above.
    468  */
    469 
    470 METHODDEF(JBLOCKARRAY)
    471 alloc_barray (j_common_ptr cinfo, int pool_id,
    472               JDIMENSION blocksperrow, JDIMENSION numrows)
    473 /* Allocate a 2-D coefficient-block array */
    474 {
    475   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
    476   JBLOCKARRAY result;
    477   JBLOCKROW workspace;
    478   JDIMENSION rowsperchunk, currow, i;
    479   long ltemp;
    480 
    481   /* Make sure each row is properly aligned */
    482   if ((sizeof(JBLOCK) % ALIGN_SIZE) != 0)
    483     out_of_memory(cinfo, 6);    /* safety check */
    484 
    485   /* Calculate max # of rows allowed in one allocation chunk */
    486   ltemp = (MAX_ALLOC_CHUNK-sizeof(large_pool_hdr)) /
    487           ((long) blocksperrow * sizeof(JBLOCK));
    488   if (ltemp <= 0)
    489     ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
    490   if (ltemp < (long) numrows)
    491     rowsperchunk = (JDIMENSION) ltemp;
    492   else
    493     rowsperchunk = numrows;
    494   mem->last_rowsperchunk = rowsperchunk;
    495 
    496   /* Get space for row pointers (small object) */
    497   result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
    498                                      (size_t) (numrows * sizeof(JBLOCKROW)));
    499 
    500   /* Get the rows themselves (large objects) */
    501   currow = 0;
    502   while (currow < numrows) {
    503     rowsperchunk = MIN(rowsperchunk, numrows - currow);
    504     workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
    505         (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
    506                   * sizeof(JBLOCK)));
    507     for (i = rowsperchunk; i > 0; i--) {
    508       result[currow++] = workspace;
    509       workspace += blocksperrow;
    510     }
    511   }
    512 
    513   return result;
    514 }
    515 
    516 
    517 /*
    518  * About virtual array management:
    519  *
    520  * The above "normal" array routines are only used to allocate strip buffers
    521  * (as wide as the image, but just a few rows high).  Full-image-sized buffers
    522  * are handled as "virtual" arrays.  The array is still accessed a strip at a
    523  * time, but the memory manager must save the whole array for repeated
    524  * accesses.  The intended implementation is that there is a strip buffer in
    525  * memory (as high as is possible given the desired memory limit), plus a
    526  * backing file that holds the rest of the array.
    527  *
    528  * The request_virt_array routines are told the total size of the image and
    529  * the maximum number of rows that will be accessed at once.  The in-memory
    530  * buffer must be at least as large as the maxaccess value.
    531  *
    532  * The request routines create control blocks but not the in-memory buffers.
    533  * That is postponed until realize_virt_arrays is called.  At that time the
    534  * total amount of space needed is known (approximately, anyway), so free
    535  * memory can be divided up fairly.
    536  *
    537  * The access_virt_array routines are responsible for making a specific strip
    538  * area accessible (after reading or writing the backing file, if necessary).
    539  * Note that the access routines are told whether the caller intends to modify
    540  * the accessed strip; during a read-only pass this saves having to rewrite
    541  * data to disk.  The access routines are also responsible for pre-zeroing
    542  * any newly accessed rows, if pre-zeroing was requested.
    543  *
    544  * In current usage, the access requests are usually for nonoverlapping
    545  * strips; that is, successive access start_row numbers differ by exactly
    546  * num_rows = maxaccess.  This means we can get good performance with simple
    547  * buffer dump/reload logic, by making the in-memory buffer be a multiple
    548  * of the access height; then there will never be accesses across bufferload
    549  * boundaries.  The code will still work with overlapping access requests,
    550  * but it doesn't handle bufferload overlaps very efficiently.
    551  */
    552 
    553 
    554 METHODDEF(jvirt_sarray_ptr)
    555 request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
    556                      JDIMENSION samplesperrow, JDIMENSION numrows,
    557                      JDIMENSION maxaccess)
    558 /* Request a virtual 2-D sample array */
    559 {
    560   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
    561   jvirt_sarray_ptr result;
    562 
    563   /* Only IMAGE-lifetime virtual arrays are currently supported */
    564   if (pool_id != JPOOL_IMAGE)
    565     ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
    566 
    567   /* get control block */
    568   result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
    569                                           sizeof(struct jvirt_sarray_control));
    570 
    571   result->mem_buffer = NULL;    /* marks array not yet realized */
    572   result->rows_in_array = numrows;
    573   result->samplesperrow = samplesperrow;
    574   result->maxaccess = maxaccess;
    575   result->pre_zero = pre_zero;
    576   result->b_s_open = FALSE;     /* no associated backing-store object */
    577   result->next = mem->virt_sarray_list; /* add to list of virtual arrays */
    578   mem->virt_sarray_list = result;
    579 
    580   return result;
    581 }
    582 
    583 
    584 METHODDEF(jvirt_barray_ptr)
    585 request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
    586                      JDIMENSION blocksperrow, JDIMENSION numrows,
    587                      JDIMENSION maxaccess)
    588 /* Request a virtual 2-D coefficient-block array */
    589 {
    590   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
    591   jvirt_barray_ptr result;
    592 
    593   /* Only IMAGE-lifetime virtual arrays are currently supported */
    594   if (pool_id != JPOOL_IMAGE)
    595     ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
    596 
    597   /* get control block */
    598   result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
    599                                           sizeof(struct jvirt_barray_control));
    600 
    601   result->mem_buffer = NULL;    /* marks array not yet realized */
    602   result->rows_in_array = numrows;
    603   result->blocksperrow = blocksperrow;
    604   result->maxaccess = maxaccess;
    605   result->pre_zero = pre_zero;
    606   result->b_s_open = FALSE;     /* no associated backing-store object */
    607   result->next = mem->virt_barray_list; /* add to list of virtual arrays */
    608   mem->virt_barray_list = result;
    609 
    610   return result;
    611 }
    612 
    613 
    614 METHODDEF(void)
    615 realize_virt_arrays (j_common_ptr cinfo)
    616 /* Allocate the in-memory buffers for any unrealized virtual arrays */
    617 {
    618   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
    619   size_t space_per_minheight, maximum_space, avail_mem;
    620   size_t minheights, max_minheights;
    621   jvirt_sarray_ptr sptr;
    622   jvirt_barray_ptr bptr;
    623 
    624   /* Compute the minimum space needed (maxaccess rows in each buffer)
    625    * and the maximum space needed (full image height in each buffer).
    626    * These may be of use to the system-dependent jpeg_mem_available routine.
    627    */
    628   space_per_minheight = 0;
    629   maximum_space = 0;
    630   for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
    631     if (sptr->mem_buffer == NULL) { /* if not realized yet */
    632       space_per_minheight += (long) sptr->maxaccess *
    633                              (long) sptr->samplesperrow * sizeof(JSAMPLE);
    634       maximum_space += (long) sptr->rows_in_array *
    635                        (long) sptr->samplesperrow * sizeof(JSAMPLE);
    636     }
    637   }
    638   for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
    639     if (bptr->mem_buffer == NULL) { /* if not realized yet */
    640       space_per_minheight += (long) bptr->maxaccess *
    641                              (long) bptr->blocksperrow * sizeof(JBLOCK);
    642       maximum_space += (long) bptr->rows_in_array *
    643                        (long) bptr->blocksperrow * sizeof(JBLOCK);
    644     }
    645   }
    646 
    647   if (space_per_minheight <= 0)
    648     return;                     /* no unrealized arrays, no work */
    649 
    650   /* Determine amount of memory to actually use; this is system-dependent. */
    651   avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space,
    652                                  mem->total_space_allocated);
    653 
    654   /* If the maximum space needed is available, make all the buffers full
    655    * height; otherwise parcel it out with the same number of minheights
    656    * in each buffer.
    657    */
    658   if (avail_mem >= maximum_space)
    659     max_minheights = 1000000000L;
    660   else {
    661     max_minheights = avail_mem / space_per_minheight;
    662     /* If there doesn't seem to be enough space, try to get the minimum
    663      * anyway.  This allows a "stub" implementation of jpeg_mem_available().
    664      */
    665     if (max_minheights <= 0)
    666       max_minheights = 1;
    667   }
    668 
    669   /* Allocate the in-memory buffers and initialize backing store as needed. */
    670 
    671   for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
    672     if (sptr->mem_buffer == NULL) { /* if not realized yet */
    673       minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
    674       if (minheights <= max_minheights) {
    675         /* This buffer fits in memory */
    676         sptr->rows_in_mem = sptr->rows_in_array;
    677       } else {
    678         /* It doesn't fit in memory, create backing store. */
    679         sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
    680         jpeg_open_backing_store(cinfo, & sptr->b_s_info,
    681                                 (long) sptr->rows_in_array *
    682                                 (long) sptr->samplesperrow *
    683                                 (long) sizeof(JSAMPLE));
    684         sptr->b_s_open = TRUE;
    685       }
    686       sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
    687                                       sptr->samplesperrow, sptr->rows_in_mem);
    688       sptr->rowsperchunk = mem->last_rowsperchunk;
    689       sptr->cur_start_row = 0;
    690       sptr->first_undef_row = 0;
    691       sptr->dirty = FALSE;
    692     }
    693   }
    694 
    695   for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
    696     if (bptr->mem_buffer == NULL) { /* if not realized yet */
    697       minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
    698       if (minheights <= max_minheights) {
    699         /* This buffer fits in memory */
    700         bptr->rows_in_mem = bptr->rows_in_array;
    701       } else {
    702         /* It doesn't fit in memory, create backing store. */
    703         bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
    704         jpeg_open_backing_store(cinfo, & bptr->b_s_info,
    705                                 (long) bptr->rows_in_array *
    706                                 (long) bptr->blocksperrow *
    707                                 (long) sizeof(JBLOCK));
    708         bptr->b_s_open = TRUE;
    709       }
    710       bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
    711                                       bptr->blocksperrow, bptr->rows_in_mem);
    712       bptr->rowsperchunk = mem->last_rowsperchunk;
    713       bptr->cur_start_row = 0;
    714       bptr->first_undef_row = 0;
    715       bptr->dirty = FALSE;
    716     }
    717   }
    718 }
    719 
    720 
    721 LOCAL(void)
    722 do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
    723 /* Do backing store read or write of a virtual sample array */
    724 {
    725   long bytesperrow, file_offset, byte_count, rows, thisrow, i;
    726 
    727   bytesperrow = (long) ptr->samplesperrow * sizeof(JSAMPLE);
    728   file_offset = ptr->cur_start_row * bytesperrow;
    729   /* Loop to read or write each allocation chunk in mem_buffer */
    730   for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
    731     /* One chunk, but check for short chunk at end of buffer */
    732     rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
    733     /* Transfer no more than is currently defined */
    734     thisrow = (long) ptr->cur_start_row + i;
    735     rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
    736     /* Transfer no more than fits in file */
    737     rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
    738     if (rows <= 0)              /* this chunk might be past end of file! */
    739       break;
    740     byte_count = rows * bytesperrow;
    741     if (writing)
    742       (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
    743                                             (void *) ptr->mem_buffer[i],
    744                                             file_offset, byte_count);
    745     else
    746       (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
    747                                            (void *) ptr->mem_buffer[i],
    748                                            file_offset, byte_count);
    749     file_offset += byte_count;
    750   }
    751 }
    752 
    753 
    754 LOCAL(void)
    755 do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
    756 /* Do backing store read or write of a virtual coefficient-block array */
    757 {
    758   long bytesperrow, file_offset, byte_count, rows, thisrow, i;
    759 
    760   bytesperrow = (long) ptr->blocksperrow * sizeof(JBLOCK);
    761   file_offset = ptr->cur_start_row * bytesperrow;
    762   /* Loop to read or write each allocation chunk in mem_buffer */
    763   for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
    764     /* One chunk, but check for short chunk at end of buffer */
    765     rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
    766     /* Transfer no more than is currently defined */
    767     thisrow = (long) ptr->cur_start_row + i;
    768     rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
    769     /* Transfer no more than fits in file */
    770     rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
    771     if (rows <= 0)              /* this chunk might be past end of file! */
    772       break;
    773     byte_count = rows * bytesperrow;
    774     if (writing)
    775       (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
    776                                             (void *) ptr->mem_buffer[i],
    777                                             file_offset, byte_count);
    778     else
    779       (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
    780                                            (void *) ptr->mem_buffer[i],
    781                                            file_offset, byte_count);
    782     file_offset += byte_count;
    783   }
    784 }
    785 
    786 
    787 METHODDEF(JSAMPARRAY)
    788 access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
    789                     JDIMENSION start_row, JDIMENSION num_rows,
    790                     boolean writable)
    791 /* Access the part of a virtual sample array starting at start_row */
    792 /* and extending for num_rows rows.  writable is true if  */
    793 /* caller intends to modify the accessed area. */
    794 {
    795   JDIMENSION end_row = start_row + num_rows;
    796   JDIMENSION undef_row;
    797 
    798   /* debugging check */
    799   if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
    800       ptr->mem_buffer == NULL)
    801     ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
    802 
    803   /* Make the desired part of the virtual array accessible */
    804   if (start_row < ptr->cur_start_row ||
    805       end_row > ptr->cur_start_row+ptr->rows_in_mem) {
    806     if (! ptr->b_s_open)
    807       ERREXIT(cinfo, JERR_VIRTUAL_BUG);
    808     /* Flush old buffer contents if necessary */
    809     if (ptr->dirty) {
    810       do_sarray_io(cinfo, ptr, TRUE);
    811       ptr->dirty = FALSE;
    812     }
    813     /* Decide what part of virtual array to access.
    814      * Algorithm: if target address > current window, assume forward scan,
    815      * load starting at target address.  If target address < current window,
    816      * assume backward scan, load so that target area is top of window.
    817      * Note that when switching from forward write to forward read, will have
    818      * start_row = 0, so the limiting case applies and we load from 0 anyway.
    819      */
    820     if (start_row > ptr->cur_start_row) {
    821       ptr->cur_start_row = start_row;
    822     } else {
    823       /* use long arithmetic here to avoid overflow & unsigned problems */
    824       long ltemp;
    825 
    826       ltemp = (long) end_row - (long) ptr->rows_in_mem;
    827       if (ltemp < 0)
    828         ltemp = 0;              /* don't fall off front end of file */
    829       ptr->cur_start_row = (JDIMENSION) ltemp;
    830     }
    831     /* Read in the selected part of the array.
    832      * During the initial write pass, we will do no actual read
    833      * because the selected part is all undefined.
    834      */
    835     do_sarray_io(cinfo, ptr, FALSE);
    836   }
    837   /* Ensure the accessed part of the array is defined; prezero if needed.
    838    * To improve locality of access, we only prezero the part of the array
    839    * that the caller is about to access, not the entire in-memory array.
    840    */
    841   if (ptr->first_undef_row < end_row) {
    842     if (ptr->first_undef_row < start_row) {
    843       if (writable)             /* writer skipped over a section of array */
    844         ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
    845       undef_row = start_row;    /* but reader is allowed to read ahead */
    846     } else {
    847       undef_row = ptr->first_undef_row;
    848     }
    849     if (writable)
    850       ptr->first_undef_row = end_row;
    851     if (ptr->pre_zero) {
    852       size_t bytesperrow = (size_t) ptr->samplesperrow * sizeof(JSAMPLE);
    853       undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
    854       end_row -= ptr->cur_start_row;
    855       while (undef_row < end_row) {
    856         jzero_far((void *) ptr->mem_buffer[undef_row], bytesperrow);
    857         undef_row++;
    858       }
    859     } else {
    860       if (! writable)           /* reader looking at undefined data */
    861         ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
    862     }
    863   }
    864   /* Flag the buffer dirty if caller will write in it */
    865   if (writable)
    866     ptr->dirty = TRUE;
    867   /* Return address of proper part of the buffer */
    868   return ptr->mem_buffer + (start_row - ptr->cur_start_row);
    869 }
    870 
    871 
    872 METHODDEF(JBLOCKARRAY)
    873 access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
    874                     JDIMENSION start_row, JDIMENSION num_rows,
    875                     boolean writable)
    876 /* Access the part of a virtual block array starting at start_row */
    877 /* and extending for num_rows rows.  writable is true if  */
    878 /* caller intends to modify the accessed area. */
    879 {
    880   JDIMENSION end_row = start_row + num_rows;
    881   JDIMENSION undef_row;
    882 
    883   /* debugging check */
    884   if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
    885       ptr->mem_buffer == NULL)
    886     ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
    887 
    888   /* Make the desired part of the virtual array accessible */
    889   if (start_row < ptr->cur_start_row ||
    890       end_row > ptr->cur_start_row+ptr->rows_in_mem) {
    891     if (! ptr->b_s_open)
    892       ERREXIT(cinfo, JERR_VIRTUAL_BUG);
    893     /* Flush old buffer contents if necessary */
    894     if (ptr->dirty) {
    895       do_barray_io(cinfo, ptr, TRUE);
    896       ptr->dirty = FALSE;
    897     }
    898     /* Decide what part of virtual array to access.
    899      * Algorithm: if target address > current window, assume forward scan,
    900      * load starting at target address.  If target address < current window,
    901      * assume backward scan, load so that target area is top of window.
    902      * Note that when switching from forward write to forward read, will have
    903      * start_row = 0, so the limiting case applies and we load from 0 anyway.
    904      */
    905     if (start_row > ptr->cur_start_row) {
    906       ptr->cur_start_row = start_row;
    907     } else {
    908       /* use long arithmetic here to avoid overflow & unsigned problems */
    909       long ltemp;
    910 
    911       ltemp = (long) end_row - (long) ptr->rows_in_mem;
    912       if (ltemp < 0)
    913         ltemp = 0;              /* don't fall off front end of file */
    914       ptr->cur_start_row = (JDIMENSION) ltemp;
    915     }
    916     /* Read in the selected part of the array.
    917      * During the initial write pass, we will do no actual read
    918      * because the selected part is all undefined.
    919      */
    920     do_barray_io(cinfo, ptr, FALSE);
    921   }
    922   /* Ensure the accessed part of the array is defined; prezero if needed.
    923    * To improve locality of access, we only prezero the part of the array
    924    * that the caller is about to access, not the entire in-memory array.
    925    */
    926   if (ptr->first_undef_row < end_row) {
    927     if (ptr->first_undef_row < start_row) {
    928       if (writable)             /* writer skipped over a section of array */
    929         ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
    930       undef_row = start_row;    /* but reader is allowed to read ahead */
    931     } else {
    932       undef_row = ptr->first_undef_row;
    933     }
    934     if (writable)
    935       ptr->first_undef_row = end_row;
    936     if (ptr->pre_zero) {
    937       size_t bytesperrow = (size_t) ptr->blocksperrow * sizeof(JBLOCK);
    938       undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
    939       end_row -= ptr->cur_start_row;
    940       while (undef_row < end_row) {
    941         jzero_far((void *) ptr->mem_buffer[undef_row], bytesperrow);
    942         undef_row++;
    943       }
    944     } else {
    945       if (! writable)           /* reader looking at undefined data */
    946         ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
    947     }
    948   }
    949   /* Flag the buffer dirty if caller will write in it */
    950   if (writable)
    951     ptr->dirty = TRUE;
    952   /* Return address of proper part of the buffer */
    953   return ptr->mem_buffer + (start_row - ptr->cur_start_row);
    954 }
    955 
    956 
    957 /*
    958  * Release all objects belonging to a specified pool.
    959  */
    960 
    961 METHODDEF(void)
    962 free_pool (j_common_ptr cinfo, int pool_id)
    963 {
    964   my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
    965   small_pool_ptr shdr_ptr;
    966   large_pool_ptr lhdr_ptr;
    967   size_t space_freed;
    968 
    969   if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
    970     ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
    971 
    972 #ifdef MEM_STATS
    973   if (cinfo->err->trace_level > 1)
    974     print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */
    975 #endif
    976 
    977   /* If freeing IMAGE pool, close any virtual arrays first */
    978   if (pool_id == JPOOL_IMAGE) {
    979     jvirt_sarray_ptr sptr;
    980     jvirt_barray_ptr bptr;
    981 
    982     for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
    983       if (sptr->b_s_open) {     /* there may be no backing store */
    984         sptr->b_s_open = FALSE; /* prevent recursive close if error */
    985         (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
    986       }
    987     }
    988     mem->virt_sarray_list = NULL;
    989     for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
    990       if (bptr->b_s_open) {     /* there may be no backing store */
    991         bptr->b_s_open = FALSE; /* prevent recursive close if error */
    992         (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
    993       }
    994     }
    995     mem->virt_barray_list = NULL;
    996   }
    997 
    998   /* Release large objects */
    999   lhdr_ptr = mem->large_list[pool_id];
   1000   mem->large_list[pool_id] = NULL;
   1001 
   1002   while (lhdr_ptr != NULL) {
   1003     large_pool_ptr next_lhdr_ptr = lhdr_ptr->next;
   1004     space_freed = lhdr_ptr->bytes_used +
   1005                   lhdr_ptr->bytes_left +
   1006                   sizeof(large_pool_hdr);
   1007     jpeg_free_large(cinfo, (void *) lhdr_ptr, space_freed);
   1008     mem->total_space_allocated -= space_freed;
   1009     lhdr_ptr = next_lhdr_ptr;
   1010   }
   1011 
   1012   /* Release small objects */
   1013   shdr_ptr = mem->small_list[pool_id];
   1014   mem->small_list[pool_id] = NULL;
   1015 
   1016   while (shdr_ptr != NULL) {
   1017     small_pool_ptr next_shdr_ptr = shdr_ptr->next;
   1018     space_freed = shdr_ptr->bytes_used +
   1019                   shdr_ptr->bytes_left +
   1020                   sizeof(small_pool_hdr);
   1021     jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
   1022     mem->total_space_allocated -= space_freed;
   1023     shdr_ptr = next_shdr_ptr;
   1024   }
   1025 }
   1026 
   1027 
   1028 /*
   1029  * Close up shop entirely.
   1030  * Note that this cannot be called unless cinfo->mem is non-NULL.
   1031  */
   1032 
   1033 METHODDEF(void)
   1034 self_destruct (j_common_ptr cinfo)
   1035 {
   1036   int pool;
   1037 
   1038   /* Close all backing store, release all memory.
   1039    * Releasing pools in reverse order might help avoid fragmentation
   1040    * with some (brain-damaged) malloc libraries.
   1041    */
   1042   for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
   1043     free_pool(cinfo, pool);
   1044   }
   1045 
   1046   /* Release the memory manager control block too. */
   1047   jpeg_free_small(cinfo, (void *) cinfo->mem, sizeof(my_memory_mgr));
   1048   cinfo->mem = NULL;            /* ensures I will be called only once */
   1049 
   1050   jpeg_mem_term(cinfo);         /* system-dependent cleanup */
   1051 }
   1052 
   1053 
   1054 /*
   1055  * Memory manager initialization.
   1056  * When this is called, only the error manager pointer is valid in cinfo!
   1057  */
   1058 
   1059 GLOBAL(void)
   1060 jinit_memory_mgr (j_common_ptr cinfo)
   1061 {
   1062   my_mem_ptr mem;
   1063   long max_to_use;
   1064   int pool;
   1065   size_t test_mac;
   1066 
   1067   cinfo->mem = NULL;            /* for safety if init fails */
   1068 
   1069   /* Check for configuration errors.
   1070    * sizeof(ALIGN_TYPE) should be a power of 2; otherwise, it probably
   1071    * doesn't reflect any real hardware alignment requirement.
   1072    * The test is a little tricky: for X>0, X and X-1 have no one-bits
   1073    * in common if and only if X is a power of 2, ie has only one one-bit.
   1074    * Some compilers may give an "unreachable code" warning here; ignore it.
   1075    */
   1076   if ((ALIGN_SIZE & (ALIGN_SIZE-1)) != 0)
   1077     ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
   1078   /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be
   1079    * a multiple of ALIGN_SIZE.
   1080    * Again, an "unreachable code" warning may be ignored here.
   1081    * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK.
   1082    */
   1083   test_mac = (size_t) MAX_ALLOC_CHUNK;
   1084   if ((long) test_mac != MAX_ALLOC_CHUNK ||
   1085       (MAX_ALLOC_CHUNK % ALIGN_SIZE) != 0)
   1086     ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
   1087 
   1088   max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */
   1089 
   1090   /* Attempt to allocate memory manager's control block */
   1091   mem = (my_mem_ptr) jpeg_get_small(cinfo, sizeof(my_memory_mgr));
   1092 
   1093   if (mem == NULL) {
   1094     jpeg_mem_term(cinfo);       /* system-dependent cleanup */
   1095     ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
   1096   }
   1097 
   1098   /* OK, fill in the method pointers */
   1099   mem->pub.alloc_small = alloc_small;
   1100   mem->pub.alloc_large = alloc_large;
   1101   mem->pub.alloc_sarray = alloc_sarray;
   1102   mem->pub.alloc_barray = alloc_barray;
   1103   mem->pub.request_virt_sarray = request_virt_sarray;
   1104   mem->pub.request_virt_barray = request_virt_barray;
   1105   mem->pub.realize_virt_arrays = realize_virt_arrays;
   1106   mem->pub.access_virt_sarray = access_virt_sarray;
   1107   mem->pub.access_virt_barray = access_virt_barray;
   1108   mem->pub.free_pool = free_pool;
   1109   mem->pub.self_destruct = self_destruct;
   1110 
   1111   /* Make MAX_ALLOC_CHUNK accessible to other modules */
   1112   mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK;
   1113 
   1114   /* Initialize working state */
   1115   mem->pub.max_memory_to_use = max_to_use;
   1116 
   1117   for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
   1118     mem->small_list[pool] = NULL;
   1119     mem->large_list[pool] = NULL;
   1120   }
   1121   mem->virt_sarray_list = NULL;
   1122   mem->virt_barray_list = NULL;
   1123 
   1124   mem->total_space_allocated = sizeof(my_memory_mgr);
   1125 
   1126   /* Declare ourselves open for business */
   1127   cinfo->mem = & mem->pub;
   1128 
   1129   /* Check for an environment variable JPEGMEM; if found, override the
   1130    * default max_memory setting from jpeg_mem_init.  Note that the
   1131    * surrounding application may again override this value.
   1132    * If your system doesn't support getenv(), define NO_GETENV to disable
   1133    * this feature.
   1134    */
   1135 #ifndef NO_GETENV
   1136   { char * memenv;
   1137 
   1138     if ((memenv = getenv("JPEGMEM")) != NULL) {
   1139       char ch = 'x';
   1140 
   1141       if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
   1142         if (ch == 'm' || ch == 'M')
   1143           max_to_use *= 1000L;
   1144         mem->pub.max_memory_to_use = max_to_use * 1000L;
   1145       }
   1146     }
   1147   }
   1148 #endif
   1149 
   1150 }
   1151