1 /*
2 * jmemmgr.c
3 *
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.
7 *
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
14 * virtual arrays;
15 * * control logic for swapping virtual arrays between main memory and
16 * backing storage.
17 * The separate system-dependent file provides the actual backing-storage
18 * access code, and it contains the policy decision about how much total
19 * main memory to use.
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...)
196 fprintf(stderr, "Freeing pool %d, total space = %ld\n",
197 pool_id, mem->total_space_allocated);
198
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);
203 }
204
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);
210 }
211 }
212
213 #endif /* MEM_STATS */
214
215
216 LOCAL(void)
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 */
220 {
221 #ifdef MEM_STATS
222 cinfo->err->trace_level = 2; /* force self_destruct to report stats */
223 #endif
224 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
225 }
226
227
228 /*
229 * Allocation of "small" objects.
230 *
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.
804 }
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.
808 */
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 */
814 } else {
815 undef_row = ptr->first_undef_row;
816 }
817 if (writable)
818 ptr->first_undef_row = end_row;
819 if (ptr->pre_zero) {
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);
825 undef_row++;
826 }
827 } else {
828 if (! writable) /* reader looking at undefined data */
829 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
830 }
831 }
832 /* Flag the buffer dirty if caller will write in it */
833 if (writable)
834 ptr->dirty = TRUE;
835 /* Return address of proper part of the buffer */
836 return ptr->mem_buffer + (start_row - ptr->cur_start_row);
837 }
838
839
840 METHODDEF(JBLOCKARRAY)
841 access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
842 JDIMENSION start_row, JDIMENSION num_rows,
843 boolean writable)
844 /* Access the part of a virtual block array starting at start_row */
889 }
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.
893 */
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 */
899 } else {
900 undef_row = ptr->first_undef_row;
901 }
902 if (writable)
903 ptr->first_undef_row = end_row;
904 if (ptr->pre_zero) {
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);
910 undef_row++;
911 }
912 } else {
913 if (! writable) /* reader looking at undefined data */
914 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
915 }
916 }
917 /* Flag the buffer dirty if caller will write in it */
918 if (writable)
919 ptr->dirty = TRUE;
920 /* Return address of proper part of the buffer */
921 return ptr->mem_buffer + (start_row - ptr->cur_start_row);
922 }
923
924
925 /*
926 * Release all objects belonging to a specified pool.
927 */
928
929 METHODDEF(void)
|
1 /*
2 * jmemmgr.c
3 *
4 * Copyright (C) 1991-1997, Thomas G. Lane.
5 * Modified 2011-2012 by Guido Vollbeding.
6 * This file is part of the Independent JPEG Group's software.
7 * For conditions of distribution and use, see the accompanying README file.
8 *
9 * This file contains the JPEG system-independent memory management
10 * routines. This code is usable across a wide variety of machines; most
11 * of the system dependencies have been isolated in a separate file.
12 * The major functions provided here are:
13 * * pool-based allocation and freeing of memory;
14 * * policy decisions about how to divide available memory among the
15 * virtual arrays;
16 * * control logic for swapping virtual arrays between main memory and
17 * backing storage.
18 * The separate system-dependent file provides the actual backing-storage
19 * access code, and it contains the policy decision about how much total
20 * main memory to use.
21 * This file is system-dependent in the sense that some of its functions
22 * are unnecessary in some systems. For example, if there is enough virtual
23 * memory so that backing storage will never be used, much of the virtual
24 * array control logic could be removed. (Of course, if you have that much
25 * memory then you shouldn't care about a little bit of unused code...)
197 fprintf(stderr, "Freeing pool %d, total space = %ld\n",
198 pool_id, mem->total_space_allocated);
199
200 for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
201 lhdr_ptr = lhdr_ptr->hdr.next) {
202 fprintf(stderr, " Large chunk used %ld\n",
203 (long) lhdr_ptr->hdr.bytes_used);
204 }
205
206 for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
207 shdr_ptr = shdr_ptr->hdr.next) {
208 fprintf(stderr, " Small chunk used %ld free %ld\n",
209 (long) shdr_ptr->hdr.bytes_used,
210 (long) shdr_ptr->hdr.bytes_left);
211 }
212 }
213
214 #endif /* MEM_STATS */
215
216
217 LOCAL(noreturn_t)
218 out_of_memory (j_common_ptr cinfo, int which)
219 /* Report an out-of-memory error and stop execution */
220 /* If we compiled MEM_STATS support, report alloc requests before dying */
221 {
222 #ifdef MEM_STATS
223 cinfo->err->trace_level = 2; /* force self_destruct to report stats */
224 #endif
225 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
226 }
227
228
229 /*
230 * Allocation of "small" objects.
231 *
232 * For these, we use pooled storage. When a new pool must be created,
233 * we try to get enough space for the current request plus a "slop" factor,
234 * where the slop will be the amount of leftover space in the new pool.
235 * The speed vs. space tradeoff is largely determined by the slop values.
236 * A different slop value is provided for each pool class (lifetime),
237 * and we also distinguish the first pool of a class from later ones.
805 }
806 /* Ensure the accessed part of the array is defined; prezero if needed.
807 * To improve locality of access, we only prezero the part of the array
808 * that the caller is about to access, not the entire in-memory array.
809 */
810 if (ptr->first_undef_row < end_row) {
811 if (ptr->first_undef_row < start_row) {
812 if (writable) /* writer skipped over a section of array */
813 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
814 undef_row = start_row; /* but reader is allowed to read ahead */
815 } else {
816 undef_row = ptr->first_undef_row;
817 }
818 if (writable)
819 ptr->first_undef_row = end_row;
820 if (ptr->pre_zero) {
821 size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
822 undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
823 end_row -= ptr->cur_start_row;
824 while (undef_row < end_row) {
825 FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
826 undef_row++;
827 }
828 } else {
829 if (! writable) /* reader looking at undefined data */
830 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
831 }
832 }
833 /* Flag the buffer dirty if caller will write in it */
834 if (writable)
835 ptr->dirty = TRUE;
836 /* Return address of proper part of the buffer */
837 return ptr->mem_buffer + (start_row - ptr->cur_start_row);
838 }
839
840
841 METHODDEF(JBLOCKARRAY)
842 access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
843 JDIMENSION start_row, JDIMENSION num_rows,
844 boolean writable)
845 /* Access the part of a virtual block array starting at start_row */
890 }
891 /* Ensure the accessed part of the array is defined; prezero if needed.
892 * To improve locality of access, we only prezero the part of the array
893 * that the caller is about to access, not the entire in-memory array.
894 */
895 if (ptr->first_undef_row < end_row) {
896 if (ptr->first_undef_row < start_row) {
897 if (writable) /* writer skipped over a section of array */
898 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
899 undef_row = start_row; /* but reader is allowed to read ahead */
900 } else {
901 undef_row = ptr->first_undef_row;
902 }
903 if (writable)
904 ptr->first_undef_row = end_row;
905 if (ptr->pre_zero) {
906 size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
907 undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
908 end_row -= ptr->cur_start_row;
909 while (undef_row < end_row) {
910 FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
911 undef_row++;
912 }
913 } else {
914 if (! writable) /* reader looking at undefined data */
915 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
916 }
917 }
918 /* Flag the buffer dirty if caller will write in it */
919 if (writable)
920 ptr->dirty = TRUE;
921 /* Return address of proper part of the buffer */
922 return ptr->mem_buffer + (start_row - ptr->cur_start_row);
923 }
924
925
926 /*
927 * Release all objects belonging to a specified pool.
928 */
929
930 METHODDEF(void)
|