00001
00002
00003
00004 #include "internal.h"
00005
00006
00007
00008
00009
00010
00011
00012 size_t tm_os_alloc_total = 0;
00013
00014
00015 #if tm_USE_MMAP
00016 #include <sys/mman.h>
00017 #endif
00018
00019
00020
00021
00022
00023
00024
00025
00026 static
00027 void *_tm_os_alloc_(long size)
00028 {
00029 void *ptr;
00030
00031 tm_assert_test(size > 0);
00032
00033 #if tm_USE_MMAP
00034 #ifdef MAP_ANONYMOUS
00035 tm.mmap_fd = -1;
00036 #endif
00037
00038 ptr = mmap((void*) 0,
00039 (size_t) size,
00040 PROT_READ | PROT_WRITE,
00041 #ifdef MAP_ANONYMOUS
00042 MAP_ANONYMOUS |
00043 #endif
00044 MAP_PRIVATE,
00045 tm.mmap_fd,
00046 (off_t) 0
00047 );
00048
00049 if ( ptr == MAP_FAILED ) {
00050 perror("tm: mmap() failed");
00051 ptr = 0;
00052 tm_abort();
00053 }
00054 #endif
00055
00056 #if tm_USE_SBRK
00057 ptr = sbrk(size);
00058
00059 tm.os_alloc_last = ptr;
00060 tm.os_alloc_last_size = size;
00061
00062 if ( tm.os_alloc_expected ) {
00063 tm_warn(ptr == tm.os_alloc_expected, "ptr = %p, expected = %p", ptr, tm.os_alloc_expected);
00064 }
00065 if ( size > 0 ) {
00066 tm.os_alloc_expected = (char *)ptr + size;
00067 }
00068 #endif
00069
00070 #if 0
00071 fprintf(stderr, " _tm_os_alloc_(%lu) => %p\n", (unsigned long) size, (void*) ptr);
00072 #endif
00073
00074 return ptr;
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 static
00087 void *_tm_os_free_(void *ptr, long size)
00088 {
00089 #if 0
00090 fprintf(stderr, " _tm_os_free_(%p, %lu)\n", (void*) ptr, (unsigned long) size);
00091 #endif
00092
00093 tm_assert_test(ptr != 0);
00094 tm_assert_test(size > 0);
00095
00096 #if tm_USE_MMAP
00097 munmap(ptr, size);
00098
00099
00100 return 0;
00101 #endif
00102
00103 #if tm_USE_SBRK
00104 if ( ptr == tm.os_alloc_last &&
00105 size == tm.os_alloc_last_size &&
00106 ptr == sbrk(0) ) {
00107 ptr = sbrk(- size);
00108
00109 tm.os_alloc_expected -= size;
00110 }
00111
00112
00113 return ptr;
00114 #endif
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124 static __inline
00125 void *_tm_os_alloc(long size)
00126 {
00127 void *ptr;
00128
00129 #if tm_TIME_STAT
00130 tm_time_stat_begin(&tm.ts_os_alloc);
00131 #endif
00132
00133
00134 if ( tm_os_alloc_total + size > tm_os_alloc_max ) {
00135 ptr = 0;
00136 } else {
00137 ptr = _tm_os_alloc_(size);
00138 }
00139
00140 #if tm_TIME_STAT
00141 tm_time_stat_end(&tm.ts_os_alloc);
00142 #endif
00143
00144 if ( ptr == 0 || ptr == (void*) -1L ) {
00145 ptr = 0;
00146 tm_msg("A 0 %lu\n", (unsigned long) size);
00147 } else
00148 if ( size > 0 ) {
00149 tm_msg("A a %p[%lu] #%lu\n", ptr, (unsigned long) size, (unsigned long) tm.n[tm_B]);
00150
00151 tm_os_alloc_total += size;
00152 } else if ( size < 0 ) {
00153 tm_assert_test(size > 0);
00154 }
00155 #if 0
00156 else {
00157 tm_msg("A z\n");
00158 }
00159 #endif
00160
00161 #if 0
00162 if ( tm.n[tm_B] > 16 ) {
00163 tm_print_stats();
00164 }
00165 #endif
00166
00167
00168
00169 return ptr;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 static __inline
00179 void *_tm_os_free(void *ptr, long size)
00180 {
00181 void *result = 0;
00182
00183 #if tm_TIME_STAT
00184 tm_time_stat_begin(&tm.ts_os_free);
00185 #endif
00186
00187 result = _tm_os_free_(ptr, size);
00188
00189 #if tm_TIME_STAT
00190 tm_time_stat_end(&tm.ts_os_free);
00191 #endif
00192
00193
00194 if ( tm_ptr_is_aligned_to_page(ptr) ) {
00195 _tm_page_mark_unused_range(ptr, size);
00196 }
00197
00198 tm_msg("A d %p[%lu] #%lu\n", ptr, (unsigned long) size, (unsigned long) tm.n[tm_B]);
00199
00200 tm_os_alloc_total -= size;
00201
00202 return result;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 void *_tm_os_alloc_aligned(size_t size)
00217 {
00218 void *ptr;
00219
00220 tm_assert(tm_ptr_is_aligned_to_block(size));
00221
00222 ptr = _tm_os_alloc(size);
00223
00224
00225 if ( ! ptr )
00226 return 0;
00227
00228
00229
00230
00231
00232
00233 if ( ! tm_ptr_is_aligned_to_block(ptr) ) {
00234 size_t offset = ((unsigned long) ptr) % tm_block_SIZE;
00235 size_t left_over = tm_block_SIZE - offset;
00236 size_t new_size = size + left_over;
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 tm_msg("A al %p[%lu] %lu %ld\n", (void *) ptr, (unsigned long) size, (unsigned long) tm_block_SIZE, (long) offset);
00257
00258
00259
00260
00261 _tm_os_free(ptr, size);
00262
00263
00264 ptr = _tm_os_alloc(new_size);
00265
00266
00267
00268
00269 if ( ! ptr )
00270 return 0;
00271
00272
00273 offset = ((unsigned long) ptr) % tm_block_SIZE;
00274
00275 tm_msg("A alr %p[%lu] %ld\n", (void *) ptr, (unsigned long) new_size, (long) offset);
00276
00277 if ( offset ) {
00278 left_over = tm_block_SIZE - offset;
00279
00280 ptr += left_over;
00281 new_size -= left_over;
00282
00283
00284 tm_assert(size == new_size);
00285 tm_assert(tm_ptr_is_aligned_to_block(ptr));
00286 tm_assert(tm_ptr_is_aligned_to_block(new_size));
00287 }
00288 }
00289
00290
00291 return ptr;
00292 }
00293
00294
00295
00296
00297
00298 void _tm_os_free_aligned(void *ptr, size_t size)
00299 {
00300 tm_assert_test(tm_ptr_is_aligned_to_block(ptr));
00301 tm_assert_test(tm_ptr_is_aligned_to_block(size));
00302
00303 _tm_os_free(ptr, size);
00304 }
00305
00306