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