4  * Copyright (C) 1991-1997, Thomas G. Lane. 
   5  * This file is part of the Independent JPEG Group's software. 
   6  * For conditions of distribution and use, see the accompanying README file. 
   8  * This file contains the JPEG system-independent memory management 
   9  * routines.  This code is usable across a wide variety of machines; most 
  10  * of the system dependencies have been isolated in a separate file. 
  11  * The major functions provided here are: 
  12  *   * pool-based allocation and freeing of memory; 
  13  *   * policy decisions about how to divide available memory among the 
  15  *   * control logic for swapping virtual arrays between main memory and 
  17  * The separate system-dependent file provides the actual backing-storage 
  18  * access code, and it contains the policy decision about how much total 
  20  * This file is system-dependent in the sense that some of its functions 
  21  * are unnecessary in some systems.  For example, if there is enough virtual 
  22  * memory so that backing storage will never be used, much of the virtual 
  23  * array control logic could be removed.  (Of course, if you have that much 
  24  * memory then you shouldn't care about a little bit of unused code...) 
  27 #define JPEG_INTERNALS 
  28 #define AM_MEMORY_MANAGER       /* we define jvirt_Xarray_control structs */ 
  31 #include "jmemsys.h"            /* import the system-dependent declarations */ 
  34 #ifndef HAVE_STDLIB_H           /* <stdlib.h> should declare getenv() */ 
  35 extern char * getenv 
JPP((const char * name
)); 
  41  * Some important notes: 
  42  *   The allocation routines provided here must never return NULL. 
  43  *   They should exit to error_exit if unsuccessful. 
  45  *   It's not a good idea to try to merge the sarray and barray routines, 
  46  *   even though they are textually almost the same, because samples are 
  47  *   usually stored as bytes while coefficients are shorts or ints.  Thus, 
  48  *   in machines where byte pointers have a different representation from 
  49  *   word pointers, the resulting machine code could not be the same. 
  54  * Many machines require storage alignment: longs must start on 4-byte 
  55  * boundaries, doubles on 8-byte boundaries, etc.  On such machines, malloc() 
  56  * always returns pointers that are multiples of the worst-case alignment 
  57  * requirement, and we had better do so too. 
  58  * There isn't any really portable way to determine the worst-case alignment 
  59  * requirement.  This module assumes that the alignment requirement is 
  60  * multiples of sizeof(ALIGN_TYPE). 
  61  * By default, we define ALIGN_TYPE as double.  This is necessary on some 
  62  * workstations (where doubles really do need 8-byte alignment) and will work 
  63  * fine on nearly everything.  If your machine has lesser alignment needs, 
  64  * you can save a few bytes by making ALIGN_TYPE smaller. 
  65  * The only place I know of where this will NOT work is certain Macintosh 
  66  * 680x0 compilers that define double as a 10-byte IEEE extended float. 
  67  * Doing 10-byte alignment is counterproductive because longwords won't be 
  68  * aligned well.  Put "#define ALIGN_TYPE long" in jconfig.h if you have 
  72 #ifndef ALIGN_TYPE              /* so can override from jconfig.h */ 
  73 #define ALIGN_TYPE  double 
  78  * We allocate objects from "pools", where each pool is gotten with a single 
  79  * request to jpeg_get_small() or jpeg_get_large().  There is no per-object 
  80  * overhead within a pool, except for alignment padding.  Each pool has a 
  81  * header with a link to the next pool of the same class. 
  82  * Small and large pool headers are identical except that the latter's 
  83  * link pointer must be FAR on 80x86 machines. 
  84  * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE 
  85  * field.  This forces the compiler to make SIZEOF(small_pool_hdr) a multiple 
  86  * of the alignment requirement of ALIGN_TYPE. 
  89 typedef union small_pool_struct 
* small_pool_ptr
; 
  91 typedef union small_pool_struct 
{ 
  93     small_pool_ptr next
;        /* next in list of pools */ 
  94     size_t bytes_used
;          /* how many bytes already used within pool */ 
  95     size_t bytes_left
;          /* bytes still available in this pool */ 
  97   ALIGN_TYPE dummy
;             /* included in union to ensure alignment */ 
 100 typedef union large_pool_struct FAR 
* large_pool_ptr
; 
 102 typedef union large_pool_struct 
{ 
 104     large_pool_ptr next
;        /* next in list of pools */ 
 105     size_t bytes_used
;          /* how many bytes already used within pool */ 
 106     size_t bytes_left
;          /* bytes still available in this pool */ 
 108   ALIGN_TYPE dummy
;             /* included in union to ensure alignment */ 
 113  * Here is the full definition of a memory manager object. 
 117   struct jpeg_memory_mgr pub
;   /* public fields */ 
 119   /* Each pool identifier (lifetime class) names a linked list of pools. */ 
 120   small_pool_ptr small_list
[JPOOL_NUMPOOLS
]; 
 121   large_pool_ptr large_list
[JPOOL_NUMPOOLS
]; 
 123   /* Since we only have one lifetime class of virtual arrays, only one 
 124    * linked list is necessary (for each datatype).  Note that the virtual 
 125    * array control blocks being linked together are actually stored somewhere 
 126    * in the small-pool list. 
 128   jvirt_sarray_ptr virt_sarray_list
; 
 129   jvirt_barray_ptr virt_barray_list
; 
 131   /* This counts total space obtained from jpeg_get_small/large */ 
 132   long total_space_allocated
; 
 134   /* alloc_sarray and alloc_barray set this value for use by virtual 
 137   JDIMENSION last_rowsperchunk
; /* from most recent alloc_sarray/barray */ 
 140 typedef my_memory_mgr 
* my_mem_ptr
; 
 144  * The control blocks for virtual arrays. 
 145  * Note that these blocks are allocated in the "small" pool area. 
 146  * System-dependent info for the associated backing store (if any) is hidden 
 147  * inside the backing_store_info struct. 
 150 struct jvirt_sarray_control 
{ 
 151   JSAMPARRAY mem_buffer
;        /* => the in-memory buffer */ 
 152   JDIMENSION rows_in_array
;     /* total virtual array height */ 
 153   JDIMENSION samplesperrow
;     /* width of array (and of memory buffer) */ 
 154   JDIMENSION maxaccess
;         /* max rows accessed by access_virt_sarray */ 
 155   JDIMENSION rows_in_mem
;       /* height of memory buffer */ 
 156   JDIMENSION rowsperchunk
;      /* allocation chunk size in mem_buffer */ 
 157   JDIMENSION cur_start_row
;     /* first logical row # in the buffer */ 
 158   JDIMENSION first_undef_row
;   /* row # of first uninitialized row */ 
 159   boolean pre_zero
;             /* pre-zero mode requested? */ 
 160   boolean dirty
;                /* do current buffer contents need written? */ 
 161   boolean b_s_open
;             /* is backing-store data valid? */ 
 162   jvirt_sarray_ptr next
;        /* link to next virtual sarray control block */ 
 163   backing_store_info b_s_info
;  /* System-dependent control info */ 
 166 struct jvirt_barray_control 
{ 
 167   JBLOCKARRAY mem_buffer
;       /* => the in-memory buffer */ 
 168   JDIMENSION rows_in_array
;     /* total virtual array height */ 
 169   JDIMENSION blocksperrow
;      /* width of array (and of memory buffer) */ 
 170   JDIMENSION maxaccess
;         /* max rows accessed by access_virt_barray */ 
 171   JDIMENSION rows_in_mem
;       /* height of memory buffer */ 
 172   JDIMENSION rowsperchunk
;      /* allocation chunk size in mem_buffer */ 
 173   JDIMENSION cur_start_row
;     /* first logical row # in the buffer */ 
 174   JDIMENSION first_undef_row
;   /* row # of first uninitialized row */ 
 175   boolean pre_zero
;             /* pre-zero mode requested? */ 
 176   boolean dirty
;                /* do current buffer contents need written? */ 
 177   boolean b_s_open
;             /* is backing-store data valid? */ 
 178   jvirt_barray_ptr next
;        /* link to next virtual barray control block */ 
 179   backing_store_info b_s_info
;  /* System-dependent control info */ 
 183 #ifdef MEM_STATS                /* optional extra stuff for statistics */ 
 186 print_mem_stats (j_common_ptr cinfo
, int pool_id
) 
 188   my_mem_ptr mem 
= (my_mem_ptr
) cinfo
->mem
; 
 189   small_pool_ptr shdr_ptr
; 
 190   large_pool_ptr lhdr_ptr
; 
 192   /* Since this is only a debugging stub, we can cheat a little by using 
 193    * fprintf directly rather than going through the trace message code. 
 194    * This is helpful because message parm array can't handle longs. 
 196   fprintf(stderr
, "Freeing pool %d, total space = %ld\n", 
 197           pool_id
, mem
->total_space_allocated
); 
 199   for (lhdr_ptr 
= mem
->large_list
[pool_id
]; lhdr_ptr 
!= NULL
; 
 200        lhdr_ptr 
= lhdr_ptr
->hdr
.next
) { 
 201     fprintf(stderr
, "  Large chunk used %ld\n", 
 202             (long) lhdr_ptr
->hdr
.bytes_used
); 
 205   for (shdr_ptr 
= mem
->small_list
[pool_id
]; shdr_ptr 
!= NULL
; 
 206        shdr_ptr 
= shdr_ptr
->hdr
.next
) { 
 207     fprintf(stderr
, "  Small chunk used %ld free %ld\n", 
 208             (long) shdr_ptr
->hdr
.bytes_used
, 
 209             (long) shdr_ptr
->hdr
.bytes_left
); 
 213 #endif /* MEM_STATS */ 
 217 out_of_memory (j_common_ptr cinfo
, int which
) 
 218 /* Report an out-of-memory error and stop execution */ 
 219 /* If we compiled MEM_STATS support, report alloc requests before dying */ 
 222   cinfo
->err
->trace_level 
= 2;  /* force self_destruct to report stats */ 
 224   ERREXIT1(cinfo
, JERR_OUT_OF_MEMORY
, which
); 
 229  * Allocation of "small" objects. 
 231  * For these, we use pooled storage.  When a new pool must be created, 
 232  * we try to get enough space for the current request plus a "slop" factor, 
 233  * where the slop will be the amount of leftover space in the new pool. 
 234  * The speed vs. space tradeoff is largely determined by the slop values. 
 235  * A different slop value is provided for each pool class (lifetime), 
 236  * and we also distinguish the first pool of a class from later ones. 
 237  * NOTE: the values given work fairly well on both 16- and 32-bit-int 
 238  * machines, but may be too small if longs are 64 bits or more. 
 241 static const size_t first_pool_slop
[JPOOL_NUMPOOLS
] =  
 243         1600,                   /* first PERMANENT pool */ 
 244         16000                   /* first IMAGE pool */ 
 247 static const size_t extra_pool_slop
[JPOOL_NUMPOOLS
] =  
 249         0,                      /* additional PERMANENT pools */ 
 250         5000                    /* additional IMAGE pools */ 
 253 #define MIN_SLOP  50            /* greater than 0 to avoid futile looping */ 
 257 alloc_small (j_common_ptr cinfo
, int pool_id
, size_t sizeofobject
) 
 258 /* Allocate a "small" object */ 
 260   my_mem_ptr mem 
= (my_mem_ptr
) cinfo
->mem
; 
 261   small_pool_ptr hdr_ptr
, prev_hdr_ptr
; 
 263   size_t odd_bytes
, min_request
, slop
; 
 265   /* Check for unsatisfiable request (do now to ensure no overflow below) */ 
 266   if (sizeofobject 
> (size_t) (MAX_ALLOC_CHUNK
-SIZEOF(small_pool_hdr
))) 
 267     out_of_memory(cinfo
, 1);    /* request exceeds malloc's ability */ 
 269   /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ 
 270   odd_bytes 
= sizeofobject 
% SIZEOF(ALIGN_TYPE
); 
 272     sizeofobject 
+= SIZEOF(ALIGN_TYPE
) - odd_bytes
; 
 274   /* See if space is available in any existing pool */ 
 275   if (pool_id 
< 0 || pool_id 
>= JPOOL_NUMPOOLS
) 
 276     ERREXIT1(cinfo
, JERR_BAD_POOL_ID
, pool_id
); /* safety check */ 
 278   hdr_ptr 
= mem
->small_list
[pool_id
]; 
 279   while (hdr_ptr 
!= NULL
) { 
 280     if (hdr_ptr
->hdr
.bytes_left 
>= sizeofobject
) 
 281       break;                    /* found pool with enough space */ 
 282     prev_hdr_ptr 
= hdr_ptr
; 
 283     hdr_ptr 
= hdr_ptr
->hdr
.next
; 
 286   /* Time to make a new pool? */ 
 287   if (hdr_ptr 
== NULL
) { 
 288     /* min_request is what we need now, slop is what will be leftover */ 
 289     min_request 
= sizeofobject 
+ SIZEOF(small_pool_hdr
); 
 290     if (prev_hdr_ptr 
== NULL
)   /* first pool in class? */ 
 291       slop 
= first_pool_slop
[pool_id
]; 
 293       slop 
= extra_pool_slop
[pool_id
]; 
 294     /* Don't ask for more than MAX_ALLOC_CHUNK */ 
 295     if (slop 
> (size_t) (MAX_ALLOC_CHUNK
-min_request
)) 
 296       slop 
= (size_t) (MAX_ALLOC_CHUNK
-min_request
); 
 297     /* Try to get space, if fail reduce slop and try again */ 
 299       hdr_ptr 
= (small_pool_ptr
) jpeg_get_small(cinfo
, min_request 
+ slop
); 
 303       if (slop 
< MIN_SLOP
)      /* give up when it gets real small */ 
 304         out_of_memory(cinfo
, 2); /* jpeg_get_small failed */ 
 306     mem
->total_space_allocated 
+= min_request 
+ slop
; 
 307     /* Success, initialize the new pool header and add to end of list */ 
 308     hdr_ptr
->hdr
.next 
= NULL
; 
 309     hdr_ptr
->hdr
.bytes_used 
= 0; 
 310     hdr_ptr
->hdr
.bytes_left 
= sizeofobject 
+ slop
; 
 311     if (prev_hdr_ptr 
== NULL
)   /* first pool in class? */ 
 312       mem
->small_list
[pool_id
] = hdr_ptr
; 
 314       prev_hdr_ptr
->hdr
.next 
= hdr_ptr
; 
 317   /* OK, allocate the object from the current pool */ 
 318   data_ptr 
= (char *) (hdr_ptr 
+ 1); /* point to first data byte in pool */ 
 319   data_ptr 
+= hdr_ptr
->hdr
.bytes_used
; /* point to place for object */ 
 320   hdr_ptr
->hdr
.bytes_used 
+= sizeofobject
; 
 321   hdr_ptr
->hdr
.bytes_left 
-= sizeofobject
; 
 323   return (void *) data_ptr
; 
 328  * Allocation of "large" objects. 
 330  * The external semantics of these are the same as "small" objects, 
 331  * except that FAR pointers are used on 80x86.  However the pool 
 332  * management heuristics are quite different.  We assume that each 
 333  * request is large enough that it may as well be passed directly to 
 334  * jpeg_get_large; the pool management just links everything together 
 335  * so that we can free it all on demand. 
 336  * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY 
 337  * structures.  The routines that create these structures (see below) 
 338  * deliberately bunch rows together to ensure a large request size. 
 341 METHODDEF(void FAR 
*) 
 342 alloc_large (j_common_ptr cinfo
, int pool_id
, size_t sizeofobject
) 
 343 /* Allocate a "large" object */ 
 345   my_mem_ptr mem 
= (my_mem_ptr
) cinfo
->mem
; 
 346   large_pool_ptr hdr_ptr
; 
 349   /* Check for unsatisfiable request (do now to ensure no overflow below) */ 
 350   if (sizeofobject 
> (size_t) (MAX_ALLOC_CHUNK
-SIZEOF(large_pool_hdr
))) 
 351     out_of_memory(cinfo
, 3);    /* request exceeds malloc's ability */ 
 353   /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */ 
 354   odd_bytes 
= sizeofobject 
% SIZEOF(ALIGN_TYPE
); 
 356     sizeofobject 
+= SIZEOF(ALIGN_TYPE
) - odd_bytes
; 
 358   /* Always make a new pool */ 
 359   if (pool_id 
< 0 || pool_id 
>= JPOOL_NUMPOOLS
) 
 360     ERREXIT1(cinfo
, JERR_BAD_POOL_ID
, pool_id
); /* safety check */ 
 362   hdr_ptr 
= (large_pool_ptr
) jpeg_get_large(cinfo
, sizeofobject 
+ 
 363                                             SIZEOF(large_pool_hdr
)); 
 365     out_of_memory(cinfo
, 4);    /* jpeg_get_large failed */ 
 366   mem
->total_space_allocated 
+= sizeofobject 
+ SIZEOF(large_pool_hdr
); 
 368   /* Success, initialize the new pool header and add to list */ 
 369   hdr_ptr
->hdr
.next 
= mem
->large_list
[pool_id
]; 
 370   /* We maintain space counts in each pool header for statistical purposes, 
 371    * even though they are not needed for allocation. 
 373   hdr_ptr
->hdr
.bytes_used 
= sizeofobject
; 
 374   hdr_ptr
->hdr
.bytes_left 
= 0; 
 375   mem
->large_list
[pool_id
] = hdr_ptr
; 
 377   return (void FAR 
*) (hdr_ptr 
+ 1); /* point to first data byte in pool */ 
 382  * Creation of 2-D sample arrays. 
 383  * The pointers are in near heap, the samples themselves in FAR heap. 
 385  * To minimize allocation overhead and to allow I/O of large contiguous 
 386  * blocks, we allocate the sample rows in groups of as many rows as possible 
 387  * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. 
 388  * NB: the virtual array control routines, later in this file, know about 
 389  * this chunking of rows.  The rowsperchunk value is left in the mem manager 
 390  * object so that it can be saved away if this sarray is the workspace for 
 394 METHODDEF(JSAMPARRAY
) 
 395 alloc_sarray (j_common_ptr cinfo
, int pool_id
, 
 396               JDIMENSION samplesperrow
, JDIMENSION numrows
) 
 397 /* Allocate a 2-D sample array */ 
 399   my_mem_ptr mem 
= (my_mem_ptr
) cinfo
->mem
; 
 402   JDIMENSION rowsperchunk
, currow
, i
; 
 405   /* Calculate max # of rows allowed in one allocation chunk */ 
 406   ltemp 
= (MAX_ALLOC_CHUNK
-SIZEOF(large_pool_hdr
)) / 
 407           ((long) samplesperrow 
* SIZEOF(JSAMPLE
)); 
 409     ERREXIT(cinfo
, JERR_WIDTH_OVERFLOW
); 
 410   if (ltemp 
< (long) numrows
) 
 411     rowsperchunk 
= (JDIMENSION
) ltemp
; 
 413     rowsperchunk 
= numrows
; 
 414   mem
->last_rowsperchunk 
= rowsperchunk
; 
 416   /* Get space for row pointers (small object) */ 
 417   result 
= (JSAMPARRAY
) alloc_small(cinfo
, pool_id
, 
 418                                     (size_t) (numrows 
* SIZEOF(JSAMPROW
))); 
 420   /* Get the rows themselves (large objects) */ 
 422   while (currow 
< numrows
) { 
 423     rowsperchunk 
= MIN(rowsperchunk
, numrows 
- currow
); 
 424     workspace 
= (JSAMPROW
) alloc_large(cinfo
, pool_id
, 
 425         (size_t) ((size_t) rowsperchunk 
* (size_t) samplesperrow
 
 427     for (i 
= rowsperchunk
; i 
> 0; i
--) { 
 428       result
[currow
++] = workspace
; 
 429       workspace 
+= samplesperrow
; 
 438  * Creation of 2-D coefficient-block arrays. 
 439  * This is essentially the same as the code for sample arrays, above. 
 442 METHODDEF(JBLOCKARRAY
) 
 443 alloc_barray (j_common_ptr cinfo
, int pool_id
, 
 444               JDIMENSION blocksperrow
, JDIMENSION numrows
) 
 445 /* Allocate a 2-D coefficient-block array */ 
 447   my_mem_ptr mem 
= (my_mem_ptr
) cinfo
->mem
; 
 450   JDIMENSION rowsperchunk
, currow
, i
; 
 453   /* Calculate max # of rows allowed in one allocation chunk */ 
 454   ltemp 
= (MAX_ALLOC_CHUNK
-SIZEOF(large_pool_hdr
)) / 
 455           ((long) blocksperrow 
* SIZEOF(JBLOCK
)); 
 457     ERREXIT(cinfo
, JERR_WIDTH_OVERFLOW
); 
 458   if (ltemp 
< (long) numrows
) 
 459     rowsperchunk 
= (JDIMENSION
) ltemp
; 
 461     rowsperchunk 
= numrows
; 
 462   mem
->last_rowsperchunk 
= rowsperchunk
; 
 464   /* Get space for row pointers (small object) */ 
 465   result 
= (JBLOCKARRAY
) alloc_small(cinfo
, pool_id
, 
 466                                      (size_t) (numrows 
* SIZEOF(JBLOCKROW
))); 
 468   /* Get the rows themselves (large objects) */ 
 470   while (currow 
< numrows
) { 
 471     rowsperchunk 
= MIN(rowsperchunk
, numrows 
- currow
); 
 472     workspace 
= (JBLOCKROW
) alloc_large(cinfo
, pool_id
, 
 473         (size_t) ((size_t) rowsperchunk 
* (size_t) blocksperrow
 
 475     for (i 
= rowsperchunk
; i 
> 0; i
--) { 
 476       result
[currow
++] = workspace
; 
 477       workspace 
+= blocksperrow
; 
 486  * About virtual array management: 
 488  * The above "normal" array routines are only used to allocate strip buffers 
 489  * (as wide as the image, but just a few rows high).  Full-image-sized buffers 
 490  * are handled as "virtual" arrays.  The array is still accessed a strip at a 
 491  * time, but the memory manager must save the whole array for repeated 
 492  * accesses.  The intended implementation is that there is a strip buffer in 
 493  * memory (as high as is possible given the desired memory limit), plus a 
 494  * backing file that holds the rest of the array. 
 496  * The request_virt_array routines are told the total size of the image and 
 497  * the maximum number of rows that will be accessed at once.  The in-memory 
 498  * buffer must be at least as large as the maxaccess value. 
 500  * The request routines create control blocks but not the in-memory buffers. 
 501  * That is postponed until realize_virt_arrays is called.  At that time the 
 502  * total amount of space needed is known (approximately, anyway), so free 
 503  * memory can be divided up fairly. 
 505  * The access_virt_array routines are responsible for making a specific strip 
 506  * area accessible (after reading or writing the backing file, if necessary). 
 507  * Note that the access routines are told whether the caller intends to modify 
 508  * the accessed strip; during a read-only pass this saves having to rewrite 
 509  * data to disk.  The access routines are also responsible for pre-zeroing 
 510  * any newly accessed rows, if pre-zeroing was requested. 
 512  * In current usage, the access requests are usually for nonoverlapping 
 513  * strips; that is, successive access start_row numbers differ by exactly 
 514  * num_rows = maxaccess.  This means we can get good performance with simple 
 515  * buffer dump/reload logic, by making the in-memory buffer be a multiple 
 516  * of the access height; then there will never be accesses across bufferload 
 517  * boundaries.  The code will still work with overlapping access requests, 
 518  * but it doesn't handle bufferload overlaps very efficiently. 
 522 METHODDEF(jvirt_sarray_ptr
) 
 523 request_virt_sarray (j_common_ptr cinfo
, int pool_id
, boolean pre_zero
, 
 524                      JDIMENSION samplesperrow
, JDIMENSION numrows
, 
 525                      JDIMENSION maxaccess
) 
 526 /* Request a virtual 2-D sample array */ 
 528   my_mem_ptr mem 
= (my_mem_ptr
) cinfo
->mem
; 
 529   jvirt_sarray_ptr result
; 
 531   /* Only IMAGE-lifetime virtual arrays are currently supported */ 
 532   if (pool_id 
!= JPOOL_IMAGE
) 
 533     ERREXIT1(cinfo
, JERR_BAD_POOL_ID
, pool_id
); /* safety check */ 
 535   /* get control block */ 
 536   result 
= (jvirt_sarray_ptr
) alloc_small(cinfo
, pool_id
, 
 537                                           SIZEOF(struct jvirt_sarray_control
)); 
 539   result
->mem_buffer 
= NULL
;    /* marks array not yet realized */ 
 540   result
->rows_in_array 
= numrows
; 
 541   result
->samplesperrow 
= samplesperrow
; 
 542   result
->maxaccess 
= maxaccess
; 
 543   result
->pre_zero 
= pre_zero
; 
 544   result
->b_s_open 
= FALSE
;     /* no associated backing-store object */ 
 545   result
->next 
= mem
->virt_sarray_list
; /* add to list of virtual arrays */ 
 546   mem
->virt_sarray_list 
= result
; 
 552 METHODDEF(jvirt_barray_ptr
) 
 553 request_virt_barray (j_common_ptr cinfo
, int pool_id
, boolean pre_zero
, 
 554                      JDIMENSION blocksperrow
, JDIMENSION numrows
, 
 555                      JDIMENSION maxaccess
) 
 556 /* Request a virtual 2-D coefficient-block array */ 
 558   my_mem_ptr mem 
= (my_mem_ptr
) cinfo
->mem
; 
 559   jvirt_barray_ptr result
; 
 561   /* Only IMAGE-lifetime virtual arrays are currently supported */ 
 562   if (pool_id 
!= JPOOL_IMAGE
) 
 563     ERREXIT1(cinfo
, JERR_BAD_POOL_ID
, pool_id
); /* safety check */ 
 565   /* get control block */ 
 566   result 
= (jvirt_barray_ptr
) alloc_small(cinfo
, pool_id
, 
 567                                           SIZEOF(struct jvirt_barray_control
)); 
 569   result
->mem_buffer 
= NULL
;    /* marks array not yet realized */ 
 570   result
->rows_in_array 
= numrows
; 
 571   result
->blocksperrow 
= blocksperrow
; 
 572   result
->maxaccess 
= maxaccess
; 
 573   result
->pre_zero 
= pre_zero
; 
 574   result
->b_s_open 
= FALSE
;     /* no associated backing-store object */ 
 575   result
->next 
= mem
->virt_barray_list
; /* add to list of virtual arrays */ 
 576   mem
->virt_barray_list 
= result
; 
 583 realize_virt_arrays (j_common_ptr cinfo
) 
 584 /* Allocate the in-memory buffers for any unrealized virtual arrays */ 
 586   my_mem_ptr mem 
= (my_mem_ptr
) cinfo
->mem
; 
 587   long space_per_minheight
, maximum_space
, avail_mem
; 
 588   long minheights
, max_minheights
; 
 589   jvirt_sarray_ptr sptr
; 
 590   jvirt_barray_ptr bptr
; 
 592   /* Compute the minimum space needed (maxaccess rows in each buffer) 
 593    * and the maximum space needed (full image height in each buffer). 
 594    * These may be of use to the system-dependent jpeg_mem_available routine. 
 596   space_per_minheight 
= 0; 
 598   for (sptr 
= mem
->virt_sarray_list
; sptr 
!= NULL
; sptr 
= sptr
->next
) { 
 599     if (sptr
->mem_buffer 
== NULL
) { /* if not realized yet */ 
 600       space_per_minheight 
+= (long) sptr
->maxaccess 
* 
 601                              (long) sptr
->samplesperrow 
* SIZEOF(JSAMPLE
); 
 602       maximum_space 
+= (long) sptr
->rows_in_array 
* 
 603                        (long) sptr
->samplesperrow 
* SIZEOF(JSAMPLE
); 
 606   for (bptr 
= mem
->virt_barray_list
; bptr 
!= NULL
; bptr 
= bptr
->next
) { 
 607     if (bptr
->mem_buffer 
== NULL
) { /* if not realized yet */ 
 608       space_per_minheight 
+= (long) bptr
->maxaccess 
* 
 609                              (long) bptr
->blocksperrow 
* SIZEOF(JBLOCK
); 
 610       maximum_space 
+= (long) bptr
->rows_in_array 
* 
 611                        (long) bptr
->blocksperrow 
* SIZEOF(JBLOCK
); 
 615   if (space_per_minheight 
<= 0) 
 616     return;                     /* no unrealized arrays, no work */ 
 618   /* Determine amount of memory to actually use; this is system-dependent. */ 
 619   avail_mem 
= jpeg_mem_available(cinfo
, space_per_minheight
, maximum_space
, 
 620                                  mem
->total_space_allocated
); 
 622   /* If the maximum space needed is available, make all the buffers full 
 623    * height; otherwise parcel it out with the same number of minheights 
 626   if (avail_mem 
>= maximum_space
) 
 627     max_minheights 
= 1000000000L; 
 629     max_minheights 
= avail_mem 
/ space_per_minheight
; 
 630     /* If there doesn't seem to be enough space, try to get the minimum 
 631      * anyway.  This allows a "stub" implementation of jpeg_mem_available(). 
 633     if (max_minheights 
<= 0) 
 637   /* Allocate the in-memory buffers and initialize backing store as needed. */ 
 639   for (sptr 
= mem
->virt_sarray_list
; sptr 
!= NULL
; sptr 
= sptr
->next
) { 
 640     if (sptr
->mem_buffer 
== NULL
) { /* if not realized yet */ 
 641       minheights 
= ((long) sptr
->rows_in_array 
- 1L) / sptr
->maxaccess 
+ 1L; 
 642       if (minheights 
<= max_minheights
) { 
 643         /* This buffer fits in memory */ 
 644         sptr
->rows_in_mem 
= sptr
->rows_in_array
; 
 646         /* It doesn't fit in memory, create backing store. */ 
 647         sptr
->rows_in_mem 
= (JDIMENSION
) (max_minheights 
* sptr
->maxaccess
); 
 648         jpeg_open_backing_store(cinfo
, & sptr
->b_s_info
, 
 649                                 (long) sptr
->rows_in_array 
* 
 650                                 (long) sptr
->samplesperrow 
* 
 651                                 (long) SIZEOF(JSAMPLE
)); 
 652         sptr
->b_s_open 
= TRUE
; 
 654       sptr
->mem_buffer 
= alloc_sarray(cinfo
, JPOOL_IMAGE
, 
 655                                       sptr
->samplesperrow
, sptr
->rows_in_mem
); 
 656       sptr
->rowsperchunk 
= mem
->last_rowsperchunk
; 
 657       sptr
->cur_start_row 
= 0; 
 658       sptr
->first_undef_row 
= 0; 
 663   for (bptr 
= mem
->virt_barray_list
; bptr 
!= NULL
; bptr 
= bptr
->next
) { 
 664     if (bptr
->mem_buffer 
== NULL
) { /* if not realized yet */ 
 665       minheights 
= ((long) bptr
->rows_in_array 
- 1L) / bptr
->maxaccess 
+ 1L; 
 666       if (minheights 
<= max_minheights
) { 
 667         /* This buffer fits in memory */ 
 668         bptr
->rows_in_mem 
= bptr
->rows_in_array
; 
 670         /* It doesn't fit in memory, create backing store. */ 
 671         bptr
->rows_in_mem 
= (JDIMENSION
) (max_minheights 
* bptr
->maxaccess
); 
 672         jpeg_open_backing_store(cinfo
, & bptr
->b_s_info
, 
 673                                 (long) bptr
->rows_in_array 
* 
 674                                 (long) bptr
->blocksperrow 
* 
 675                                 (long) SIZEOF(JBLOCK
)); 
 676         bptr
->b_s_open 
= TRUE
; 
 678       bptr
->mem_buffer 
= alloc_barray(cinfo
, JPOOL_IMAGE
, 
 679                                       bptr
->blocksperrow
, bptr
->rows_in_mem
); 
 680       bptr
->rowsperchunk 
= mem
->last_rowsperchunk
; 
 681       bptr
->cur_start_row 
= 0; 
 682       bptr
->first_undef_row 
= 0; 
 690 do_sarray_io (j_common_ptr cinfo
, jvirt_sarray_ptr ptr
, boolean writing
) 
 691 /* Do backing store read or write of a virtual sample array */ 
 693   long bytesperrow
, file_offset
, byte_count
, rows
, thisrow
, i
; 
 695   bytesperrow 
= (long) ptr
->samplesperrow 
* SIZEOF(JSAMPLE
); 
 696   file_offset 
= ptr
->cur_start_row 
* bytesperrow
; 
 697   /* Loop to read or write each allocation chunk in mem_buffer */ 
 698   for (i 
= 0; i 
< (long) ptr
->rows_in_mem
; i 
+= ptr
->rowsperchunk
) { 
 699     /* One chunk, but check for short chunk at end of buffer */ 
 700     rows 
= MIN((long) ptr
->rowsperchunk
, (long) ptr
->rows_in_mem 
- i
); 
 701     /* Transfer no more than is currently defined */ 
 702     thisrow 
= (long) ptr
->cur_start_row 
+ i
; 
 703     rows 
= MIN(rows
, (long) ptr
->first_undef_row 
- thisrow
); 
 704     /* Transfer no more than fits in file */ 
 705     rows 
= MIN(rows
, (long) ptr
->rows_in_array 
- thisrow
); 
 706     if (rows 
<= 0)              /* this chunk might be past end of file! */ 
 708     byte_count 
= rows 
* bytesperrow
; 
 710       (*ptr
->b_s_info
.write_backing_store
) (cinfo
, & ptr
->b_s_info
, 
 711                                             (void FAR 
*) ptr
->mem_buffer
[i
], 
 712                                             file_offset
, byte_count
); 
 714       (*ptr
->b_s_info
.read_backing_store
) (cinfo
, & ptr
->b_s_info
, 
 715                                            (void FAR 
*) ptr
->mem_buffer
[i
], 
 716                                            file_offset
, byte_count
); 
 717     file_offset 
+= byte_count
; 
 723 do_barray_io (j_common_ptr cinfo
, jvirt_barray_ptr ptr
, boolean writing
) 
 724 /* Do backing store read or write of a virtual coefficient-block array */ 
 726   long bytesperrow
, file_offset
, byte_count
, rows
, thisrow
, i
; 
 728   bytesperrow 
= (long) ptr
->blocksperrow 
* SIZEOF(JBLOCK
); 
 729   file_offset 
= ptr
->cur_start_row 
* bytesperrow
; 
 730   /* Loop to read or write each allocation chunk in mem_buffer */ 
 731   for (i 
= 0; i 
< (long) ptr
->rows_in_mem
; i 
+= ptr
->rowsperchunk
) { 
 732     /* One chunk, but check for short chunk at end of buffer */ 
 733     rows 
= MIN((long) ptr
->rowsperchunk
, (long) ptr
->rows_in_mem 
- i
); 
 734     /* Transfer no more than is currently defined */ 
 735     thisrow 
= (long) ptr
->cur_start_row 
+ i
; 
 736     rows 
= MIN(rows
, (long) ptr
->first_undef_row 
- thisrow
); 
 737     /* Transfer no more than fits in file */ 
 738     rows 
= MIN(rows
, (long) ptr
->rows_in_array 
- thisrow
); 
 739     if (rows 
<= 0)              /* this chunk might be past end of file! */ 
 741     byte_count 
= rows 
* bytesperrow
; 
 743       (*ptr
->b_s_info
.write_backing_store
) (cinfo
, & ptr
->b_s_info
, 
 744                                             (void FAR 
*) ptr
->mem_buffer
[i
], 
 745                                             file_offset
, byte_count
); 
 747       (*ptr
->b_s_info
.read_backing_store
) (cinfo
, & ptr
->b_s_info
, 
 748                                            (void FAR 
*) ptr
->mem_buffer
[i
], 
 749                                            file_offset
, byte_count
); 
 750     file_offset 
+= byte_count
; 
 755 METHODDEF(JSAMPARRAY
) 
 756 access_virt_sarray (j_common_ptr cinfo
, jvirt_sarray_ptr ptr
, 
 757                     JDIMENSION start_row
, JDIMENSION num_rows
, 
 759 /* Access the part of a virtual sample array starting at start_row */ 
 760 /* and extending for num_rows rows.  writable is true if  */ 
 761 /* caller intends to modify the accessed area. */ 
 763   JDIMENSION end_row 
= start_row 
+ num_rows
; 
 764   JDIMENSION undef_row
; 
 766   /* debugging check */ 
 767   if (end_row 
> ptr
->rows_in_array 
|| num_rows 
> ptr
->maxaccess 
|| 
 768       ptr
->mem_buffer 
== NULL
) 
 769     ERREXIT(cinfo
, JERR_BAD_VIRTUAL_ACCESS
); 
 771   /* Make the desired part of the virtual array accessible */ 
 772   if (start_row 
< ptr
->cur_start_row 
|| 
 773       end_row 
> ptr
->cur_start_row
+ptr
->rows_in_mem
) { 
 775       ERREXIT(cinfo
, JERR_VIRTUAL_BUG
); 
 776     /* Flush old buffer contents if necessary */ 
 778       do_sarray_io(cinfo
, ptr
, TRUE
); 
 781     /* Decide what part of virtual array to access. 
 782      * Algorithm: if target address > current window, assume forward scan, 
 783      * load starting at target address.  If target address < current window, 
 784      * assume backward scan, load so that target area is top of window. 
 785      * Note that when switching from forward write to forward read, will have 
 786      * start_row = 0, so the limiting case applies and we load from 0 anyway. 
 788     if (start_row 
> ptr
->cur_start_row
) { 
 789       ptr
->cur_start_row 
= start_row
; 
 791       /* use long arithmetic here to avoid overflow & unsigned problems */ 
 794       ltemp 
= (long) end_row 
- (long) ptr
->rows_in_mem
; 
 796         ltemp 
= 0;              /* don't fall off front end of file */ 
 797       ptr
->cur_start_row 
= (JDIMENSION
) ltemp
; 
 799     /* Read in the selected part of the array. 
 800      * During the initial write pass, we will do no actual read 
 801      * because the selected part is all undefined. 
 803     do_sarray_io(cinfo
, ptr
, FALSE
); 
 805   /* Ensure the accessed part of the array is defined; prezero if needed. 
 806    * To improve locality of access, we only prezero the part of the array 
 807    * that the caller is about to access, not the entire in-memory array. 
 809   if (ptr
->first_undef_row 
< end_row
) { 
 810     if (ptr
->first_undef_row 
< start_row
) { 
 811       if (writable
)             /* writer skipped over a section of array */ 
 812         ERREXIT(cinfo
, JERR_BAD_VIRTUAL_ACCESS
); 
 813       undef_row 
= start_row
;    /* but reader is allowed to read ahead */ 
 815       undef_row 
= ptr
->first_undef_row
; 
 818       ptr
->first_undef_row 
= end_row
; 
 820       size_t bytesperrow 
= (size_t) ptr
->samplesperrow 
* SIZEOF(JSAMPLE
); 
 821       undef_row 
-= ptr
->cur_start_row
; /* make indexes relative to buffer */ 
 822       end_row 
-= ptr
->cur_start_row
; 
 823       while (undef_row 
< end_row
) { 
 824         jzero_far((void FAR 
*) ptr
->mem_buffer
[undef_row
], bytesperrow
); 
 828       if (! writable
)           /* reader looking at undefined data */ 
 829         ERREXIT(cinfo
, JERR_BAD_VIRTUAL_ACCESS
); 
 832   /* Flag the buffer dirty if caller will write in it */ 
 835   /* Return address of proper part of the buffer */ 
 836   return ptr
->mem_buffer 
+ (start_row 
- ptr
->cur_start_row
); 
 840 METHODDEF(JBLOCKARRAY
) 
 841 access_virt_barray (j_common_ptr cinfo
, jvirt_barray_ptr ptr
, 
 842                     JDIMENSION start_row
, JDIMENSION num_rows
, 
 844 /* Access the part of a virtual block array starting at start_row */ 
 845 /* and extending for num_rows rows.  writable is true if  */ 
 846 /* caller intends to modify the accessed area. */ 
 848   JDIMENSION end_row 
= start_row 
+ num_rows
; 
 849   JDIMENSION undef_row
; 
 851   /* debugging check */ 
 852   if (end_row 
> ptr
->rows_in_array 
|| num_rows 
> ptr
->maxaccess 
|| 
 853       ptr
->mem_buffer 
== NULL
) 
 854     ERREXIT(cinfo
, JERR_BAD_VIRTUAL_ACCESS
); 
 856   /* Make the desired part of the virtual array accessible */ 
 857   if (start_row 
< ptr
->cur_start_row 
|| 
 858       end_row 
> ptr
->cur_start_row
+ptr
->rows_in_mem
) { 
 860       ERREXIT(cinfo
, JERR_VIRTUAL_BUG
); 
 861     /* Flush old buffer contents if necessary */ 
 863       do_barray_io(cinfo
, ptr
, TRUE
); 
 866     /* Decide what part of virtual array to access. 
 867      * Algorithm: if target address > current window, assume forward scan, 
 868      * load starting at target address.  If target address < current window, 
 869      * assume backward scan, load so that target area is top of window. 
 870      * Note that when switching from forward write to forward read, will have 
 871      * start_row = 0, so the limiting case applies and we load from 0 anyway. 
 873     if (start_row 
> ptr
->cur_start_row
) { 
 874       ptr
->cur_start_row 
= start_row
; 
 876       /* use long arithmetic here to avoid overflow & unsigned problems */ 
 879       ltemp 
= (long) end_row 
- (long) ptr
->rows_in_mem
; 
 881         ltemp 
= 0;              /* don't fall off front end of file */ 
 882       ptr
->cur_start_row 
= (JDIMENSION
) ltemp
; 
 884     /* Read in the selected part of the array. 
 885      * During the initial write pass, we will do no actual read 
 886      * because the selected part is all undefined. 
 888     do_barray_io(cinfo
, ptr
, FALSE
); 
 890   /* Ensure the accessed part of the array is defined; prezero if needed. 
 891    * To improve locality of access, we only prezero the part of the array 
 892    * that the caller is about to access, not the entire in-memory array. 
 894   if (ptr
->first_undef_row 
< end_row
) { 
 895     if (ptr
->first_undef_row 
< start_row
) { 
 896       if (writable
)             /* writer skipped over a section of array */ 
 897         ERREXIT(cinfo
, JERR_BAD_VIRTUAL_ACCESS
); 
 898       undef_row 
= start_row
;    /* but reader is allowed to read ahead */ 
 900       undef_row 
= ptr
->first_undef_row
; 
 903       ptr
->first_undef_row 
= end_row
; 
 905       size_t bytesperrow 
= (size_t) ptr
->blocksperrow 
* SIZEOF(JBLOCK
); 
 906       undef_row 
-= ptr
->cur_start_row
; /* make indexes relative to buffer */ 
 907       end_row 
-= ptr
->cur_start_row
; 
 908       while (undef_row 
< end_row
) { 
 909         jzero_far((void FAR 
*) ptr
->mem_buffer
[undef_row
], bytesperrow
); 
 913       if (! writable
)           /* reader looking at undefined data */ 
 914         ERREXIT(cinfo
, JERR_BAD_VIRTUAL_ACCESS
); 
 917   /* Flag the buffer dirty if caller will write in it */ 
 920   /* Return address of proper part of the buffer */ 
 921   return ptr
->mem_buffer 
+ (start_row 
- ptr
->cur_start_row
); 
 926  * Release all objects belonging to a specified pool. 
 930 free_pool (j_common_ptr cinfo
, int pool_id
) 
 932   my_mem_ptr mem 
= (my_mem_ptr
) cinfo
->mem
; 
 933   small_pool_ptr shdr_ptr
; 
 934   large_pool_ptr lhdr_ptr
; 
 937   if (pool_id 
< 0 || pool_id 
>= JPOOL_NUMPOOLS
) 
 938     ERREXIT1(cinfo
, JERR_BAD_POOL_ID
, pool_id
); /* safety check */ 
 941   if (cinfo
->err
->trace_level 
> 1) 
 942     print_mem_stats(cinfo
, pool_id
); /* print pool's memory usage statistics */ 
 945   /* If freeing IMAGE pool, close any virtual arrays first */ 
 946   if (pool_id 
== JPOOL_IMAGE
) { 
 947     jvirt_sarray_ptr sptr
; 
 948     jvirt_barray_ptr bptr
; 
 950     for (sptr 
= mem
->virt_sarray_list
; sptr 
!= NULL
; sptr 
= sptr
->next
) { 
 951       if (sptr
->b_s_open
) {     /* there may be no backing store */ 
 952         sptr
->b_s_open 
= FALSE
; /* prevent recursive close if error */ 
 953         (*sptr
->b_s_info
.close_backing_store
) (cinfo
, & sptr
->b_s_info
); 
 956     mem
->virt_sarray_list 
= NULL
; 
 957     for (bptr 
= mem
->virt_barray_list
; bptr 
!= NULL
; bptr 
= bptr
->next
) { 
 958       if (bptr
->b_s_open
) {     /* there may be no backing store */ 
 959         bptr
->b_s_open 
= FALSE
; /* prevent recursive close if error */ 
 960         (*bptr
->b_s_info
.close_backing_store
) (cinfo
, & bptr
->b_s_info
); 
 963     mem
->virt_barray_list 
= NULL
; 
 966   /* Release large objects */ 
 967   lhdr_ptr 
= mem
->large_list
[pool_id
]; 
 968   mem
->large_list
[pool_id
] = NULL
; 
 970   while (lhdr_ptr 
!= NULL
) { 
 971     large_pool_ptr next_lhdr_ptr 
= lhdr_ptr
->hdr
.next
; 
 972     space_freed 
= lhdr_ptr
->hdr
.bytes_used 
+ 
 973                   lhdr_ptr
->hdr
.bytes_left 
+ 
 974                   SIZEOF(large_pool_hdr
); 
 975     jpeg_free_large(cinfo
, (void FAR 
*) lhdr_ptr
, space_freed
); 
 976     mem
->total_space_allocated 
-= space_freed
; 
 977     lhdr_ptr 
= next_lhdr_ptr
; 
 980   /* Release small objects */ 
 981   shdr_ptr 
= mem
->small_list
[pool_id
]; 
 982   mem
->small_list
[pool_id
] = NULL
; 
 984   while (shdr_ptr 
!= NULL
) { 
 985     small_pool_ptr next_shdr_ptr 
= shdr_ptr
->hdr
.next
; 
 986     space_freed 
= shdr_ptr
->hdr
.bytes_used 
+ 
 987                   shdr_ptr
->hdr
.bytes_left 
+ 
 988                   SIZEOF(small_pool_hdr
); 
 989     jpeg_free_small(cinfo
, (void *) shdr_ptr
, space_freed
); 
 990     mem
->total_space_allocated 
-= space_freed
; 
 991     shdr_ptr 
= next_shdr_ptr
; 
 997  * Close up shop entirely. 
 998  * Note that this cannot be called unless cinfo->mem is non-NULL. 
1002 self_destruct (j_common_ptr cinfo
) 
1006   /* Close all backing store, release all memory. 
1007    * Releasing pools in reverse order might help avoid fragmentation 
1008    * with some (brain-damaged) malloc libraries. 
1010   for (pool 
= JPOOL_NUMPOOLS
-1; pool 
>= JPOOL_PERMANENT
; pool
--) { 
1011     free_pool(cinfo
, pool
); 
1014   /* Release the memory manager control block too. */ 
1015   jpeg_free_small(cinfo
, (void *) cinfo
->mem
, SIZEOF(my_memory_mgr
)); 
1016   cinfo
->mem 
= NULL
;            /* ensures I will be called only once */ 
1018   jpeg_mem_term(cinfo
);         /* system-dependent cleanup */ 
1023  * Memory manager initialization. 
1024  * When this is called, only the error manager pointer is valid in cinfo! 
1028 jinit_memory_mgr (j_common_ptr cinfo
) 
1035   cinfo
->mem 
= NULL
;            /* for safety if init fails */ 
1037   /* Check for configuration errors. 
1038    * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably 
1039    * doesn't reflect any real hardware alignment requirement. 
1040    * The test is a little tricky: for X>0, X and X-1 have no one-bits 
1041    * in common if and only if X is a power of 2, ie has only one one-bit. 
1042    * Some compilers may give an "unreachable code" warning here; ignore it. 
1044   if ((SIZEOF(ALIGN_TYPE
) & (SIZEOF(ALIGN_TYPE
)-1)) != 0) 
1045     ERREXIT(cinfo
, JERR_BAD_ALIGN_TYPE
); 
1046   /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be 
1047    * a multiple of SIZEOF(ALIGN_TYPE). 
1048    * Again, an "unreachable code" warning may be ignored here. 
1049    * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. 
1051   test_mac 
= (size_t) MAX_ALLOC_CHUNK
; 
1052   if ((long) test_mac 
!= MAX_ALLOC_CHUNK 
|| 
1053       (MAX_ALLOC_CHUNK 
% SIZEOF(ALIGN_TYPE
)) != 0) 
1054     ERREXIT(cinfo
, JERR_BAD_ALLOC_CHUNK
); 
1056   max_to_use 
= jpeg_mem_init(cinfo
); /* system-dependent initialization */ 
1058   /* Attempt to allocate memory manager's control block */ 
1059   mem 
= (my_mem_ptr
) jpeg_get_small(cinfo
, SIZEOF(my_memory_mgr
)); 
1062     jpeg_mem_term(cinfo
);       /* system-dependent cleanup */ 
1063     ERREXIT1(cinfo
, JERR_OUT_OF_MEMORY
, 0); 
1066   /* OK, fill in the method pointers */ 
1067   mem
->pub
.alloc_small 
= alloc_small
; 
1068   mem
->pub
.alloc_large 
= alloc_large
; 
1069   mem
->pub
.alloc_sarray 
= alloc_sarray
; 
1070   mem
->pub
.alloc_barray 
= alloc_barray
; 
1071   mem
->pub
.request_virt_sarray 
= request_virt_sarray
; 
1072   mem
->pub
.request_virt_barray 
= request_virt_barray
; 
1073   mem
->pub
.realize_virt_arrays 
= realize_virt_arrays
; 
1074   mem
->pub
.access_virt_sarray 
= access_virt_sarray
; 
1075   mem
->pub
.access_virt_barray 
= access_virt_barray
; 
1076   mem
->pub
.free_pool 
= free_pool
; 
1077   mem
->pub
.self_destruct 
= self_destruct
; 
1079   /* Make MAX_ALLOC_CHUNK accessible to other modules */ 
1080   mem
->pub
.max_alloc_chunk 
= MAX_ALLOC_CHUNK
; 
1082   /* Initialize working state */ 
1083   mem
->pub
.max_memory_to_use 
= max_to_use
; 
1085   for (pool 
= JPOOL_NUMPOOLS
-1; pool 
>= JPOOL_PERMANENT
; pool
--) { 
1086     mem
->small_list
[pool
] = NULL
; 
1087     mem
->large_list
[pool
] = NULL
; 
1089   mem
->virt_sarray_list 
= NULL
; 
1090   mem
->virt_barray_list 
= NULL
; 
1092   mem
->total_space_allocated 
= SIZEOF(my_memory_mgr
); 
1094   /* Declare ourselves open for business */ 
1095   cinfo
->mem 
= & mem
->pub
; 
1097   /* Check for an environment variable JPEGMEM; if found, override the 
1098    * default max_memory setting from jpeg_mem_init.  Note that the 
1099    * surrounding application may again override this value. 
1100    * If your system doesn't support getenv(), define NO_GETENV to disable 
1106     if ((memenv 
= getenv("JPEGMEM")) != NULL
) { 
1109       if (sscanf(memenv
, "%ld%c", &max_to_use
, &ch
) > 0) { 
1110         if (ch 
== 'm' || ch 
== 'M') 
1111           max_to_use 
*= 1000L; 
1112         mem
->pub
.max_memory_to_use 
= max_to_use 
* 1000L;