00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define JPEG_INTERNALS
00028 #define AM_MEMORY_MANAGER
00029 #include "jinclude.h"
00030 #include "jpeglib.h"
00031 #include "jmemsys.h"
00032
00033 #ifndef NO_GETENV
00034 #ifndef HAVE_STDLIB_H
00035 extern char * getenv JPP((const char * name));
00036 #endif
00037 #endif
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 #ifndef ALIGN_TYPE
00073 #define ALIGN_TYPE double
00074 #endif
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 typedef union small_pool_struct * small_pool_ptr;
00090
00091 typedef union small_pool_struct {
00092 struct {
00093 small_pool_ptr next;
00094 size_t bytes_used;
00095 size_t bytes_left;
00096 } hdr;
00097 ALIGN_TYPE dummy;
00098 } small_pool_hdr;
00099
00100 typedef union large_pool_struct FAR * large_pool_ptr;
00101
00102 typedef union large_pool_struct {
00103 struct {
00104 large_pool_ptr next;
00105 size_t bytes_used;
00106 size_t bytes_left;
00107 } hdr;
00108 ALIGN_TYPE dummy;
00109 } large_pool_hdr;
00110
00111
00112
00113
00114
00115
00116 typedef struct {
00117 struct jpeg_memory_mgr pub;
00118
00119
00120 small_pool_ptr small_list[JPOOL_NUMPOOLS];
00121 large_pool_ptr large_list[JPOOL_NUMPOOLS];
00122
00123
00124
00125
00126
00127
00128 jvirt_sarray_ptr virt_sarray_list;
00129 jvirt_barray_ptr virt_barray_list;
00130
00131
00132 long total_space_allocated;
00133
00134
00135
00136
00137 JDIMENSION last_rowsperchunk;
00138 } my_memory_mgr;
00139
00140 typedef my_memory_mgr * my_mem_ptr;
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 struct jvirt_sarray_control {
00151 JSAMPARRAY mem_buffer;
00152 JDIMENSION rows_in_array;
00153 JDIMENSION samplesperrow;
00154 JDIMENSION maxaccess;
00155 JDIMENSION rows_in_mem;
00156 JDIMENSION rowsperchunk;
00157 JDIMENSION cur_start_row;
00158 JDIMENSION first_undef_row;
00159 boolean pre_zero;
00160 boolean dirty;
00161 boolean b_s_open;
00162 jvirt_sarray_ptr next;
00163 backing_store_info b_s_info;
00164 };
00165
00166 struct jvirt_barray_control {
00167 JBLOCKARRAY mem_buffer;
00168 JDIMENSION rows_in_array;
00169 JDIMENSION blocksperrow;
00170 JDIMENSION maxaccess;
00171 JDIMENSION rows_in_mem;
00172 JDIMENSION rowsperchunk;
00173 JDIMENSION cur_start_row;
00174 JDIMENSION first_undef_row;
00175 boolean pre_zero;
00176 boolean dirty;
00177 boolean b_s_open;
00178 jvirt_barray_ptr next;
00179 backing_store_info b_s_info;
00180 };
00181
00182
00183 #ifdef MEM_STATS
00184
00185 LOCAL(void)
00186 print_mem_stats (j_common_ptr cinfo, int pool_id)
00187 {
00188 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00189 small_pool_ptr shdr_ptr;
00190 large_pool_ptr lhdr_ptr;
00191
00192
00193
00194
00195
00196 fprintf(stderr, "Freeing pool %d, total space = %ld\n",
00197 pool_id, mem->total_space_allocated);
00198
00199 for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
00200 lhdr_ptr = lhdr_ptr->hdr.next) {
00201 fprintf(stderr, " Large chunk used %ld\n",
00202 (long) lhdr_ptr->hdr.bytes_used);
00203 }
00204
00205 for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
00206 shdr_ptr = shdr_ptr->hdr.next) {
00207 fprintf(stderr, " Small chunk used %ld free %ld\n",
00208 (long) shdr_ptr->hdr.bytes_used,
00209 (long) shdr_ptr->hdr.bytes_left);
00210 }
00211 }
00212
00213 #endif
00214
00215
00216 LOCAL(void)
00217 out_of_memory (j_common_ptr cinfo, int which)
00218
00219
00220 {
00221 #ifdef MEM_STATS
00222 cinfo->err->trace_level = 2;
00223 #endif
00224 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 static const size_t first_pool_slop[JPOOL_NUMPOOLS] =
00242 {
00243 1600,
00244 16000
00245 };
00246
00247 static const size_t extra_pool_slop[JPOOL_NUMPOOLS] =
00248 {
00249 0,
00250 5000
00251 };
00252
00253 #define MIN_SLOP 50
00254
00255
00256 METHODDEF(void *)
00257 alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
00258
00259 {
00260 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00261 small_pool_ptr hdr_ptr, prev_hdr_ptr;
00262 char * data_ptr;
00263 size_t odd_bytes, min_request, slop;
00264
00265
00266 if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr)))
00267 out_of_memory(cinfo, 1);
00268
00269
00270 odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
00271 if (odd_bytes > 0)
00272 sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
00273
00274
00275 if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
00276 ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);
00277 prev_hdr_ptr = NULL;
00278 hdr_ptr = mem->small_list[pool_id];
00279 while (hdr_ptr != NULL) {
00280 if (hdr_ptr->hdr.bytes_left >= sizeofobject)
00281 break;
00282 prev_hdr_ptr = hdr_ptr;
00283 hdr_ptr = hdr_ptr->hdr.next;
00284 }
00285
00286
00287 if (hdr_ptr == NULL) {
00288
00289 min_request = sizeofobject + SIZEOF(small_pool_hdr);
00290 if (prev_hdr_ptr == NULL)
00291 slop = first_pool_slop[pool_id];
00292 else
00293 slop = extra_pool_slop[pool_id];
00294
00295 if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
00296 slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
00297
00298 for (;;) {
00299 hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
00300 if (hdr_ptr != NULL)
00301 break;
00302 slop /= 2;
00303 if (slop < MIN_SLOP)
00304 out_of_memory(cinfo, 2);
00305 }
00306 mem->total_space_allocated += min_request + slop;
00307
00308 hdr_ptr->hdr.next = NULL;
00309 hdr_ptr->hdr.bytes_used = 0;
00310 hdr_ptr->hdr.bytes_left = sizeofobject + slop;
00311 if (prev_hdr_ptr == NULL)
00312 mem->small_list[pool_id] = hdr_ptr;
00313 else
00314 prev_hdr_ptr->hdr.next = hdr_ptr;
00315 }
00316
00317
00318 data_ptr = (char *) (hdr_ptr + 1);
00319 data_ptr += hdr_ptr->hdr.bytes_used;
00320 hdr_ptr->hdr.bytes_used += sizeofobject;
00321 hdr_ptr->hdr.bytes_left -= sizeofobject;
00322
00323 return (void *) data_ptr;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 METHODDEF(void FAR *)
00342 alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
00343
00344 {
00345 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00346 large_pool_ptr hdr_ptr;
00347 size_t odd_bytes;
00348
00349
00350 if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)))
00351 out_of_memory(cinfo, 3);
00352
00353
00354 odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
00355 if (odd_bytes > 0)
00356 sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
00357
00358
00359 if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
00360 ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);
00361
00362 hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
00363 SIZEOF(large_pool_hdr));
00364 if (hdr_ptr == NULL)
00365 out_of_memory(cinfo, 4);
00366 mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr);
00367
00368
00369 hdr_ptr->hdr.next = mem->large_list[pool_id];
00370
00371
00372
00373 hdr_ptr->hdr.bytes_used = sizeofobject;
00374 hdr_ptr->hdr.bytes_left = 0;
00375 mem->large_list[pool_id] = hdr_ptr;
00376
00377 return (void FAR *) (hdr_ptr + 1);
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 METHODDEF(JSAMPARRAY)
00395 alloc_sarray (j_common_ptr cinfo, int pool_id,
00396 JDIMENSION samplesperrow, JDIMENSION numrows)
00397
00398 {
00399 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00400 JSAMPARRAY result;
00401 JSAMPROW workspace;
00402 JDIMENSION rowsperchunk, currow, i;
00403 long ltemp;
00404
00405
00406 ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
00407 ((long) samplesperrow * SIZEOF(JSAMPLE));
00408 if (ltemp <= 0)
00409 ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
00410 if (ltemp < (long) numrows)
00411 rowsperchunk = (JDIMENSION) ltemp;
00412 else
00413 rowsperchunk = numrows;
00414 mem->last_rowsperchunk = rowsperchunk;
00415
00416
00417 result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
00418 (size_t) (numrows * SIZEOF(JSAMPROW)));
00419
00420
00421 currow = 0;
00422 while (currow < numrows) {
00423 rowsperchunk = MIN(rowsperchunk, numrows - currow);
00424 workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
00425 (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
00426 * SIZEOF(JSAMPLE)));
00427 for (i = rowsperchunk; i > 0; i--) {
00428 result[currow++] = workspace;
00429 workspace += samplesperrow;
00430 }
00431 }
00432
00433 return result;
00434 }
00435
00436
00437
00438
00439
00440
00441
00442 METHODDEF(JBLOCKARRAY)
00443 alloc_barray (j_common_ptr cinfo, int pool_id,
00444 JDIMENSION blocksperrow, JDIMENSION numrows)
00445
00446 {
00447 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00448 JBLOCKARRAY result;
00449 JBLOCKROW workspace;
00450 JDIMENSION rowsperchunk, currow, i;
00451 long ltemp;
00452
00453
00454 ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
00455 ((long) blocksperrow * SIZEOF(JBLOCK));
00456 if (ltemp <= 0)
00457 ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
00458 if (ltemp < (long) numrows)
00459 rowsperchunk = (JDIMENSION) ltemp;
00460 else
00461 rowsperchunk = numrows;
00462 mem->last_rowsperchunk = rowsperchunk;
00463
00464
00465 result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
00466 (size_t) (numrows * SIZEOF(JBLOCKROW)));
00467
00468
00469 currow = 0;
00470 while (currow < numrows) {
00471 rowsperchunk = MIN(rowsperchunk, numrows - currow);
00472 workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
00473 (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
00474 * SIZEOF(JBLOCK)));
00475 for (i = rowsperchunk; i > 0; i--) {
00476 result[currow++] = workspace;
00477 workspace += blocksperrow;
00478 }
00479 }
00480
00481 return result;
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 METHODDEF(jvirt_sarray_ptr)
00523 request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
00524 JDIMENSION samplesperrow, JDIMENSION numrows,
00525 JDIMENSION maxaccess)
00526
00527 {
00528 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00529 jvirt_sarray_ptr result;
00530
00531
00532 if (pool_id != JPOOL_IMAGE)
00533 ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);
00534
00535
00536 result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
00537 SIZEOF(struct jvirt_sarray_control));
00538
00539 result->mem_buffer = NULL;
00540 result->rows_in_array = numrows;
00541 result->samplesperrow = samplesperrow;
00542 result->maxaccess = maxaccess;
00543 result->pre_zero = pre_zero;
00544 result->b_s_open = FALSE;
00545 result->next = mem->virt_sarray_list;
00546 mem->virt_sarray_list = result;
00547
00548 return result;
00549 }
00550
00551
00552 METHODDEF(jvirt_barray_ptr)
00553 request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
00554 JDIMENSION blocksperrow, JDIMENSION numrows,
00555 JDIMENSION maxaccess)
00556
00557 {
00558 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00559 jvirt_barray_ptr result;
00560
00561
00562 if (pool_id != JPOOL_IMAGE)
00563 ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);
00564
00565
00566 result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
00567 SIZEOF(struct jvirt_barray_control));
00568
00569 result->mem_buffer = NULL;
00570 result->rows_in_array = numrows;
00571 result->blocksperrow = blocksperrow;
00572 result->maxaccess = maxaccess;
00573 result->pre_zero = pre_zero;
00574 result->b_s_open = FALSE;
00575 result->next = mem->virt_barray_list;
00576 mem->virt_barray_list = result;
00577
00578 return result;
00579 }
00580
00581
00582 METHODDEF(void)
00583 realize_virt_arrays (j_common_ptr cinfo)
00584
00585 {
00586 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00587 long space_per_minheight, maximum_space, avail_mem;
00588 long minheights, max_minheights;
00589 jvirt_sarray_ptr sptr;
00590 jvirt_barray_ptr bptr;
00591
00592
00593
00594
00595
00596 space_per_minheight = 0;
00597 maximum_space = 0;
00598 for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
00599 if (sptr->mem_buffer == NULL) {
00600 space_per_minheight += (long) sptr->maxaccess *
00601 (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
00602 maximum_space += (long) sptr->rows_in_array *
00603 (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
00604 }
00605 }
00606 for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
00607 if (bptr->mem_buffer == NULL) {
00608 space_per_minheight += (long) bptr->maxaccess *
00609 (long) bptr->blocksperrow * SIZEOF(JBLOCK);
00610 maximum_space += (long) bptr->rows_in_array *
00611 (long) bptr->blocksperrow * SIZEOF(JBLOCK);
00612 }
00613 }
00614
00615 if (space_per_minheight <= 0)
00616 return;
00617
00618
00619 avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space,
00620 mem->total_space_allocated);
00621
00622
00623
00624
00625
00626 if (avail_mem >= maximum_space)
00627 max_minheights = 1000000000L;
00628 else {
00629 max_minheights = avail_mem / space_per_minheight;
00630
00631
00632
00633 if (max_minheights <= 0)
00634 max_minheights = 1;
00635 }
00636
00637
00638
00639 for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
00640 if (sptr->mem_buffer == NULL) {
00641 minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
00642 if (minheights <= max_minheights) {
00643
00644 sptr->rows_in_mem = sptr->rows_in_array;
00645 } else {
00646
00647 sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
00648 jpeg_open_backing_store(cinfo, & sptr->b_s_info,
00649 (long) sptr->rows_in_array *
00650 (long) sptr->samplesperrow *
00651 (long) SIZEOF(JSAMPLE));
00652 sptr->b_s_open = TRUE;
00653 }
00654 sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
00655 sptr->samplesperrow, sptr->rows_in_mem);
00656 sptr->rowsperchunk = mem->last_rowsperchunk;
00657 sptr->cur_start_row = 0;
00658 sptr->first_undef_row = 0;
00659 sptr->dirty = FALSE;
00660 }
00661 }
00662
00663 for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
00664 if (bptr->mem_buffer == NULL) {
00665 minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
00666 if (minheights <= max_minheights) {
00667
00668 bptr->rows_in_mem = bptr->rows_in_array;
00669 } else {
00670
00671 bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
00672 jpeg_open_backing_store(cinfo, & bptr->b_s_info,
00673 (long) bptr->rows_in_array *
00674 (long) bptr->blocksperrow *
00675 (long) SIZEOF(JBLOCK));
00676 bptr->b_s_open = TRUE;
00677 }
00678 bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
00679 bptr->blocksperrow, bptr->rows_in_mem);
00680 bptr->rowsperchunk = mem->last_rowsperchunk;
00681 bptr->cur_start_row = 0;
00682 bptr->first_undef_row = 0;
00683 bptr->dirty = FALSE;
00684 }
00685 }
00686 }
00687
00688
00689 LOCAL(void)
00690 do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
00691
00692 {
00693 long bytesperrow, file_offset, byte_count, rows, thisrow, i;
00694
00695 bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE);
00696 file_offset = ptr->cur_start_row * bytesperrow;
00697
00698 for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
00699
00700 rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
00701
00702 thisrow = (long) ptr->cur_start_row + i;
00703 rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
00704
00705 rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
00706 if (rows <= 0)
00707 break;
00708 byte_count = rows * bytesperrow;
00709 if (writing)
00710 (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
00711 (void FAR *) ptr->mem_buffer[i],
00712 file_offset, byte_count);
00713 else
00714 (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
00715 (void FAR *) ptr->mem_buffer[i],
00716 file_offset, byte_count);
00717 file_offset += byte_count;
00718 }
00719 }
00720
00721
00722 LOCAL(void)
00723 do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
00724
00725 {
00726 long bytesperrow, file_offset, byte_count, rows, thisrow, i;
00727
00728 bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK);
00729 file_offset = ptr->cur_start_row * bytesperrow;
00730
00731 for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
00732
00733 rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
00734
00735 thisrow = (long) ptr->cur_start_row + i;
00736 rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
00737
00738 rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
00739 if (rows <= 0)
00740 break;
00741 byte_count = rows * bytesperrow;
00742 if (writing)
00743 (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
00744 (void FAR *) ptr->mem_buffer[i],
00745 file_offset, byte_count);
00746 else
00747 (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
00748 (void FAR *) ptr->mem_buffer[i],
00749 file_offset, byte_count);
00750 file_offset += byte_count;
00751 }
00752 }
00753
00754
00755 METHODDEF(JSAMPARRAY)
00756 access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
00757 JDIMENSION start_row, JDIMENSION num_rows,
00758 boolean writable)
00759
00760
00761
00762 {
00763 JDIMENSION end_row = start_row + num_rows;
00764 JDIMENSION undef_row;
00765
00766
00767 if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
00768 ptr->mem_buffer == NULL)
00769 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00770
00771
00772 if (start_row < ptr->cur_start_row ||
00773 end_row > ptr->cur_start_row+ptr->rows_in_mem) {
00774 if (! ptr->b_s_open)
00775 ERREXIT(cinfo, JERR_VIRTUAL_BUG);
00776
00777 if (ptr->dirty) {
00778 do_sarray_io(cinfo, ptr, TRUE);
00779 ptr->dirty = FALSE;
00780 }
00781
00782
00783
00784
00785
00786
00787
00788 if (start_row > ptr->cur_start_row) {
00789 ptr->cur_start_row = start_row;
00790 } else {
00791
00792 long ltemp;
00793
00794 ltemp = (long) end_row - (long) ptr->rows_in_mem;
00795 if (ltemp < 0)
00796 ltemp = 0;
00797 ptr->cur_start_row = (JDIMENSION) ltemp;
00798 }
00799
00800
00801
00802
00803 do_sarray_io(cinfo, ptr, FALSE);
00804 }
00805
00806
00807
00808
00809 if (ptr->first_undef_row < end_row) {
00810 if (ptr->first_undef_row < start_row) {
00811 if (writable)
00812 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00813 undef_row = start_row;
00814 } else {
00815 undef_row = ptr->first_undef_row;
00816 }
00817 if (writable)
00818 ptr->first_undef_row = end_row;
00819 if (ptr->pre_zero) {
00820 size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
00821 undef_row -= ptr->cur_start_row;
00822 end_row -= ptr->cur_start_row;
00823 while (undef_row < end_row) {
00824 jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
00825 undef_row++;
00826 }
00827 } else {
00828 if (! writable)
00829 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00830 }
00831 }
00832
00833 if (writable)
00834 ptr->dirty = TRUE;
00835
00836 return ptr->mem_buffer + (start_row - ptr->cur_start_row);
00837 }
00838
00839
00840 METHODDEF(JBLOCKARRAY)
00841 access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
00842 JDIMENSION start_row, JDIMENSION num_rows,
00843 boolean writable)
00844
00845
00846
00847 {
00848 JDIMENSION end_row = start_row + num_rows;
00849 JDIMENSION undef_row;
00850
00851
00852 if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
00853 ptr->mem_buffer == NULL)
00854 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00855
00856
00857 if (start_row < ptr->cur_start_row ||
00858 end_row > ptr->cur_start_row+ptr->rows_in_mem) {
00859 if (! ptr->b_s_open)
00860 ERREXIT(cinfo, JERR_VIRTUAL_BUG);
00861
00862 if (ptr->dirty) {
00863 do_barray_io(cinfo, ptr, TRUE);
00864 ptr->dirty = FALSE;
00865 }
00866
00867
00868
00869
00870
00871
00872
00873 if (start_row > ptr->cur_start_row) {
00874 ptr->cur_start_row = start_row;
00875 } else {
00876
00877 long ltemp;
00878
00879 ltemp = (long) end_row - (long) ptr->rows_in_mem;
00880 if (ltemp < 0)
00881 ltemp = 0;
00882 ptr->cur_start_row = (JDIMENSION) ltemp;
00883 }
00884
00885
00886
00887
00888 do_barray_io(cinfo, ptr, FALSE);
00889 }
00890
00891
00892
00893
00894 if (ptr->first_undef_row < end_row) {
00895 if (ptr->first_undef_row < start_row) {
00896 if (writable)
00897 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00898 undef_row = start_row;
00899 } else {
00900 undef_row = ptr->first_undef_row;
00901 }
00902 if (writable)
00903 ptr->first_undef_row = end_row;
00904 if (ptr->pre_zero) {
00905 size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
00906 undef_row -= ptr->cur_start_row;
00907 end_row -= ptr->cur_start_row;
00908 while (undef_row < end_row) {
00909 jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
00910 undef_row++;
00911 }
00912 } else {
00913 if (! writable)
00914 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00915 }
00916 }
00917
00918 if (writable)
00919 ptr->dirty = TRUE;
00920
00921 return ptr->mem_buffer + (start_row - ptr->cur_start_row);
00922 }
00923
00924
00925
00926
00927
00928
00929 METHODDEF(void)
00930 free_pool (j_common_ptr cinfo, int pool_id)
00931 {
00932 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00933 small_pool_ptr shdr_ptr;
00934 large_pool_ptr lhdr_ptr;
00935 size_t space_freed;
00936
00937 if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
00938 ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);
00939
00940 #ifdef MEM_STATS
00941 if (cinfo->err->trace_level > 1)
00942 print_mem_stats(cinfo, pool_id);
00943 #endif
00944
00945
00946 if (pool_id == JPOOL_IMAGE) {
00947 jvirt_sarray_ptr sptr;
00948 jvirt_barray_ptr bptr;
00949
00950 for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
00951 if (sptr->b_s_open) {
00952 sptr->b_s_open = FALSE;
00953 (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
00954 }
00955 }
00956 mem->virt_sarray_list = NULL;
00957 for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
00958 if (bptr->b_s_open) {
00959 bptr->b_s_open = FALSE;
00960 (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
00961 }
00962 }
00963 mem->virt_barray_list = NULL;
00964 }
00965
00966
00967 lhdr_ptr = mem->large_list[pool_id];
00968 mem->large_list[pool_id] = NULL;
00969
00970 while (lhdr_ptr != NULL) {
00971 large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next;
00972 space_freed = lhdr_ptr->hdr.bytes_used +
00973 lhdr_ptr->hdr.bytes_left +
00974 SIZEOF(large_pool_hdr);
00975 jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed);
00976 mem->total_space_allocated -= space_freed;
00977 lhdr_ptr = next_lhdr_ptr;
00978 }
00979
00980
00981 shdr_ptr = mem->small_list[pool_id];
00982 mem->small_list[pool_id] = NULL;
00983
00984 while (shdr_ptr != NULL) {
00985 small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next;
00986 space_freed = shdr_ptr->hdr.bytes_used +
00987 shdr_ptr->hdr.bytes_left +
00988 SIZEOF(small_pool_hdr);
00989 jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
00990 mem->total_space_allocated -= space_freed;
00991 shdr_ptr = next_shdr_ptr;
00992 }
00993 }
00994
00995
00996
00997
00998
00999
01000
01001 METHODDEF(void)
01002 self_destruct (j_common_ptr cinfo)
01003 {
01004 int pool;
01005
01006
01007
01008
01009
01010 for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
01011 free_pool(cinfo, pool);
01012 }
01013
01014
01015 jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr));
01016 cinfo->mem = NULL;
01017
01018 jpeg_mem_term(cinfo);
01019 }
01020
01021
01022
01023
01024
01025
01026
01027 GLOBAL(void)
01028 jinit_memory_mgr (j_common_ptr cinfo)
01029 {
01030 my_mem_ptr mem;
01031 long max_to_use;
01032 int pool;
01033 size_t test_mac;
01034
01035 cinfo->mem = NULL;
01036
01037
01038
01039
01040
01041
01042
01043
01044 if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
01045 ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
01046
01047
01048
01049
01050
01051 test_mac = (size_t) MAX_ALLOC_CHUNK;
01052 if ((long) test_mac != MAX_ALLOC_CHUNK ||
01053 (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)
01054 ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
01055
01056 max_to_use = jpeg_mem_init(cinfo);
01057
01058
01059 mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));
01060
01061 if (mem == NULL) {
01062 jpeg_mem_term(cinfo);
01063 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
01064 }
01065
01066
01067 mem->pub.alloc_small = alloc_small;
01068 mem->pub.alloc_large = alloc_large;
01069 mem->pub.alloc_sarray = alloc_sarray;
01070 mem->pub.alloc_barray = alloc_barray;
01071 mem->pub.request_virt_sarray = request_virt_sarray;
01072 mem->pub.request_virt_barray = request_virt_barray;
01073 mem->pub.realize_virt_arrays = realize_virt_arrays;
01074 mem->pub.access_virt_sarray = access_virt_sarray;
01075 mem->pub.access_virt_barray = access_virt_barray;
01076 mem->pub.free_pool = free_pool;
01077 mem->pub.self_destruct = self_destruct;
01078
01079
01080 mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK;
01081
01082
01083 mem->pub.max_memory_to_use = max_to_use;
01084
01085 for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
01086 mem->small_list[pool] = NULL;
01087 mem->large_list[pool] = NULL;
01088 }
01089 mem->virt_sarray_list = NULL;
01090 mem->virt_barray_list = NULL;
01091
01092 mem->total_space_allocated = SIZEOF(my_memory_mgr);
01093
01094
01095 cinfo->mem = & mem->pub;
01096
01097
01098
01099
01100
01101
01102
01103 #ifndef NO_GETENV
01104 { char * memenv;
01105
01106 if ((memenv = getenv("JPEGMEM")) != NULL) {
01107 char ch = 'x';
01108
01109 if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
01110 if (ch == 'm' || ch == 'M')
01111 max_to_use *= 1000L;
01112 mem->pub.max_memory_to_use = max_to_use * 1000L;
01113 }
01114 }
01115 }
01116 #endif
01117
01118 }