- Timestamp:
- Sep 4, 2020, 2:14:10 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 14d8a9b
- Parents:
- 56c44dc (diff), 2801829 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- libcfa
- Files:
-
- 1 added
- 10 edited
-
Makefile.dist.am (added)
-
prelude/Makefile.am (modified) (1 diff)
-
src/Makefile.am (modified) (4 diffs)
-
src/bits/defs.hfa (modified) (3 diffs)
-
src/bits/locks.hfa (modified) (4 diffs)
-
src/concurrency/CtxSwitch-arm64.S (modified) (3 diffs)
-
src/concurrency/kernel.cfa (modified) (3 diffs)
-
src/concurrency/preemption.cfa (modified) (2 diffs)
-
src/exception.c (modified) (5 diffs)
-
src/heap.cfa (modified) (9 diffs)
-
src/stdlib.hfa (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/prelude/Makefile.am
r56c44dc rce55a81 22 22 cfalibdir = ${CFA_LIBDIR} 23 23 cfalib_DATA = gcc-builtins.cf builtins.cf extras.cf prelude.cfa bootloader.c defines.hfa 24 25 EXTRA_DIST = bootloader.cf builtins.c builtins.def extras.c extras.regx extras.regx2 prelude-gen.cc prototypes.awk prototypes.c prototypes.sed sync-builtins.cf 24 26 25 27 CC = @LOCAL_CFACC@ -
libcfa/src/Makefile.am
r56c44dc rce55a81 31 31 # AM_CFAFLAGS for only cfa source 32 32 # use -no-include-stdhdr to prevent rebuild cycles 33 # The built sources must not depend on the installed headers34 AM_CFAFLAGS = -quiet -cfalib -I$(srcdir)/stdhdr $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@33 # The built sources must not depend on the installed inst_headers_src 34 AM_CFAFLAGS = -quiet -cfalib -I$(srcdir)/stdhdr -I$(srcdir)/concurrency $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@ 35 35 AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC -fexceptions -pthread @ARCH_FLAGS@ @CONFIG_CFLAGS@ 36 36 AM_CCASFLAGS = -g -Wall -Wno-unused-function @ARCH_FLAGS@ @CONFIG_CFLAGS@ … … 39 39 #---------------------------------------------------------------------------------------------------------------- 40 40 if BUILDLIB 41 headers_nosrc = bitmanip.hfa exception.hfa math.hfa gmp.hfa time_t.hfa clock.hfa \ 42 bits/align.hfa bits/containers.hfa bits/defs.hfa bits/debug.hfa bits/locks.hfa \ 43 containers/list.hfa containers/stackLockFree.hfa concurrency/iofwd.hfa 41 inst_headers_nosrc = \ 42 bitmanip.hfa \ 43 clock.hfa \ 44 exception.hfa \ 45 gmp.hfa \ 46 math.hfa \ 47 time_t.hfa \ 48 bits/align.hfa \ 49 bits/containers.hfa \ 50 bits/debug.hfa \ 51 bits/defs.hfa \ 52 bits/locks.hfa \ 53 concurrency/iofwd.hfa \ 54 containers/list.hfa \ 55 containers/stackLockFree.hfa 44 56 45 headers = common.hfa fstream.hfa heap.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa \ 46 time.hfa stdlib.hfa parseargs.hfa \ 47 containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa 57 inst_headers_src = \ 58 common.hfa \ 59 fstream.hfa \ 60 heap.hfa \ 61 iostream.hfa \ 62 iterator.hfa \ 63 limits.hfa \ 64 parseargs.hfa \ 65 rational.hfa \ 66 stdlib.hfa \ 67 time.hfa \ 68 containers/maybe.hfa \ 69 containers/pair.hfa \ 70 containers/result.hfa \ 71 containers/vector.hfa 48 72 49 libsrc = startup.cfa interpose.cfa bits/debug.cfa assert.cfa exception.c virtual.c ${headers:.hfa=.cfa} 73 libsrc = ${inst_headers_src} ${inst_headers_src:.hfa=.cfa} \ 74 assert.cfa \ 75 bits/algorithm.hfa \ 76 bits/debug.cfa \ 77 exception.c \ 78 exception.h \ 79 interpose.cfa \ 80 lsda.h \ 81 startup.cfa \ 82 startup.hfa \ 83 virtual.c \ 84 virtual.h 50 85 51 86 # not all platforms support concurrency, add option do disable it 52 thread_headers_nosrc = bits/random.hfa concurrency/invoke.h concurrency/kernel/fwd.hfa 87 inst_thread_headers_nosrc = \ 88 bits/random.hfa \ 89 concurrency/invoke.h \ 90 concurrency/kernel/fwd.hfa 53 91 54 thread_headers = concurrency/coroutine.hfa concurrency/thread.hfa concurrency/kernel.hfa \ 55 concurrency/monitor.hfa concurrency/mutex.hfa concurrency/exception.hfa 92 inst_thread_headers_src = \ 93 concurrency/coroutine.hfa \ 94 concurrency/exception.hfa \ 95 concurrency/kernel.hfa \ 96 concurrency/monitor.hfa \ 97 concurrency/mutex.hfa \ 98 concurrency/thread.hfa 56 99 57 thread_libsrc = concurrency/CtxSwitch-@ARCHITECTURE@.S concurrency/alarm.cfa \ 58 concurrency/invoke.c concurrency/io.cfa concurrency/iocall.cfa \ 59 concurrency/io/setup.cfa \ 60 concurrency/kernel/startup.cfa concurrency/preemption.cfa \ 61 concurrency/ready_queue.cfa concurrency/stats.cfa \ 62 ${thread_headers:.hfa=.cfa} 100 thread_libsrc = ${inst_thread_headers_src} ${inst_thread_headers_src:.hfa=.cfa} \ 101 bits/signal.hfa \ 102 concurrency/alarm.cfa \ 103 concurrency/alarm.hfa \ 104 concurrency/CtxSwitch-@ARCHITECTURE@.S \ 105 concurrency/invoke.c \ 106 concurrency/io.cfa \ 107 concurrency/io/setup.cfa \ 108 concurrency/io/types.hfa \ 109 concurrency/iocall.cfa \ 110 concurrency/iofwd.hfa \ 111 concurrency/kernel_private.hfa \ 112 concurrency/kernel/startup.cfa \ 113 concurrency/preemption.cfa \ 114 concurrency/preemption.hfa \ 115 concurrency/ready_queue.cfa \ 116 concurrency/ready_subqueue.hfa \ 117 concurrency/snzi.hfa \ 118 concurrency/stats.cfa \ 119 concurrency/stats.hfa \ 120 concurrency/stats.hfa 121 63 122 else 64 headers=65 thread_headers=66 headers_nosrc =67 thread_headers_nosrc =123 inst_headers_src = 124 inst_thread_headers_src = 125 inst_headers_nosrc = 126 inst_thread_headers_nosrc = 68 127 libsrc = 69 128 endif … … 115 174 116 175 #---------------------------------------------------------------------------------------------------------------- 117 libcfa_la_SOURCES = prelude.cfa ${libsrc} 176 libcfa_la_SOURCES = ${libsrc} 177 nodist_libcfa_la_SOURCES = prelude.cfa 118 178 libcfa_la_LDFLAGS = -version-info @CFA_VERSION@ 119 179 … … 124 184 125 185 cfa_includedir = $(CFA_INCDIR) 126 nobase_cfa_include_HEADERS = ${stdhdr} ${headers} ${headers_nosrc} ${thread_headers} ${thread_headers_nosrc} 186 nobase_cfa_include_HEADERS = ${stdhdr} ${inst_headers_src} ${inst_headers_nosrc} ${inst_thread_headers_src} ${inst_thread_headers_nosrc} 187 EXTRA_DIST = stdhdr 127 188 128 189 #---------------------------------------------------------------------------------------------------------------- -
libcfa/src/bits/defs.hfa
r56c44dc rce55a81 10 10 // Created On : Thu Nov 9 13:24:10 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Aug 13 22:00:23202013 // Update Count : 1912 // Last Modified On : Wed Aug 26 16:22:32 2020 13 // Update Count : 20 14 14 // 15 15 … … 49 49 50 50 static inline long long int rdtscl(void) { 51 #if defined( __aarch64__ ) 51 #if defined( __i386 ) || defined( __x86_64 ) 52 unsigned int lo, hi; 53 __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); 54 return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); 55 #elif defined( __aarch64__ ) || defined( __arm__ ) 52 56 // https://github.com/google/benchmark/blob/v1.1.0/src/cycleclock.h#L116 53 57 long long int virtual_timer_value; … … 55 59 return virtual_timer_value; 56 60 #else 57 unsigned int lo, hi; 58 __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); 59 return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); 61 #error unsupported hardware architecture 60 62 #endif // __ARM_ARCH 61 63 } -
libcfa/src/bits/locks.hfa
r56c44dc rce55a81 218 218 } 219 219 220 // Semaphore which only supports a single thread and one post 221 // Semaphore which only supports a single thread 220 // Synchronozation primitive which only supports a single thread and one post 221 // Similar to a binary semaphore with a 'one shot' semantic 222 // is expected to be discarded after each party call their side 222 223 struct oneshot { 224 // Internal state : 225 // 0p : is initial state (wait will block) 226 // 1p : fulfilled (wait won't block) 227 // any thread : a thread is currently waiting 223 228 struct $thread * volatile ptr; 224 229 }; … … 231 236 void ^?{}(oneshot & this) {} 232 237 238 // Wait for the post, return immidiately if it already happened. 239 // return true if the thread was parked 233 240 bool wait(oneshot & this) { 234 241 for() { … … 244 251 } 245 252 253 // Mark as fulfilled, wake thread if needed 254 // return true if a thread was unparked 246 255 bool post(oneshot & this) { 247 256 struct $thread * got = __atomic_exchange_n( &this.ptr, 1p, __ATOMIC_SEQ_CST); … … 251 260 } 252 261 } 262 263 // base types for future to build upon 264 // It is based on the 'oneshot' type to allow multiple futures 265 // to block on the same instance, permitting users to block a single 266 // thread on "any of" [a given set of] futures. 267 // does not support multiple threads waiting on the same future 268 struct future_t { 269 // Internal state : 270 // 0p : is initial state (wait will block) 271 // 1p : fulfilled (wait won't block) 272 // 2p : in progress () 273 // 3p : abandoned, server should delete 274 // any oneshot : a context has been setup to wait, a thread could wait on it 275 struct oneshot * volatile ptr; 276 }; 277 278 static inline { 279 void ?{}(future_t & this) { 280 this.ptr = 0p; 281 } 282 283 void ^?{}(future_t & this) {} 284 285 // check if the future is available 286 bool available( future_t & this ) { 287 return this.ptr == 1p; 288 } 289 290 // Prepare the future to be waited on 291 // intented to be use by wait, wait_any, waitfor, etc. rather than used directly 292 bool setup( future_t & this, oneshot & wait_ctx ) { 293 /* paranoid */ verify( wait_ctx.ptr == 0p ); 294 // The future needs to set the wait context 295 for() { 296 struct oneshot * expected = this.ptr; 297 // Is the future already fulfilled? 298 if(expected == 1p) return false; // Yes, just return false (didn't block) 299 300 // The future is not fulfilled, try to setup the wait context 301 /* paranoid */ verify( expected == 0p ); 302 if(__atomic_compare_exchange_n(&this.ptr, &expected, &wait_ctx, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 303 return true; 304 } 305 } 306 } 307 308 // Stop waiting on a future 309 // When multiple futures are waited for together in "any of" pattern 310 // futures that weren't fulfilled before the thread woke up 311 // should retract the wait ctx 312 // intented to be use by wait, wait_any, waitfor, etc. rather than used directly 313 void retract( future_t & this, oneshot & wait_ctx ) { 314 // Remove the wait context 315 struct oneshot * got = __atomic_exchange_n( &this.ptr, 0p, __ATOMIC_SEQ_CST); 316 317 // got == 0p: future was never actually setup, just return 318 if( got == 0p ) return; 319 320 // got == wait_ctx: since fulfil does an atomic_swap, 321 // if we got back the original then no one else saw context 322 // It is safe to delete (which could happen after the return) 323 if( got == &wait_ctx ) return; 324 325 // got == 1p: the future is ready and the context was fully consumed 326 // the server won't use the pointer again 327 // It is safe to delete (which could happen after the return) 328 if( got == 1p ) return; 329 330 // got == 2p: the future is ready but the context hasn't fully been consumed 331 // spin until it is safe to move on 332 if( got == 2p ) { 333 while( this.ptr != 1p ) Pause(); 334 return; 335 } 336 337 // got == any thing else, something wen't wrong here, abort 338 abort("Future in unexpected state"); 339 } 340 341 // Mark the future as abandoned, meaning it will be deleted by the server 342 void abandon( future_t & this ) { 343 struct oneshot * got = __atomic_exchange_n( &this.ptr, 3p, __ATOMIC_SEQ_CST); 344 345 // got == 2p: the future is ready but the context hasn't fully been consumed 346 // spin until it is safe to move on 347 if( got == 2p ) { 348 while( this.ptr != 1p ) Pause(); 349 } 350 return; 351 } 352 353 // from the server side, mark the future as fulfilled 354 // delete it if needed 355 bool fulfil( future_t & this ) { 356 for() { 357 struct oneshot * expected = this.ptr; 358 // was this abandoned? 359 if( expected == 3p ) { free( &this ); return false; } 360 361 /* paranoid */ verify( expected != 1p ); // Future is already fulfilled, should not happen 362 /* paranoid */ verify( expected != 2p ); // Future is bein fulfilled by someone else, this is even less supported then the previous case. 363 364 // If there is a wait context, we need to consume it and mark it as consumed after 365 // If there is no context then we can skip the in progress phase 366 struct oneshot * want = expected == 0p ? 1p : 2p; 367 if(__atomic_compare_exchange_n(&this.ptr, &expected, want, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { 368 if( expected == 0p ) { /* paranoid */ verify( this.ptr == 1p); return false; } 369 bool ret = post( *expected ); 370 __atomic_store_n( &this.ptr, 1p, __ATOMIC_SEQ_CST); 371 return ret; 372 } 373 } 374 375 } 376 377 // Wait for the future to be fulfilled 378 bool wait( future_t & this ) { 379 oneshot temp; 380 if( !setup(this, temp) ) return false; 381 382 // Wait context is setup, just wait on it 383 bool ret = wait( temp ); 384 385 // Wait for the future to tru 386 while( this.ptr == 2p ) Pause(); 387 // Make sure the state makes sense 388 // Should be fulfilled, could be in progress but it's out of date if so 389 // since if that is the case, the oneshot was fulfilled (unparking this thread) 390 // and the oneshot should not be needed any more 391 __attribute__((unused)) struct oneshot * was = this.ptr; 392 /* paranoid */ verifyf( was == 1p, "Expected this.ptr to be 1p, was %p\n", was ); 393 394 // Mark the future as fulfilled, to be consistent 395 // with potential calls to avail 396 // this.ptr = 1p; 397 return ret; 398 } 399 } 253 400 #endif -
libcfa/src/concurrency/CtxSwitch-arm64.S
r56c44dc rce55a81 2 2 // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo 3 3 // 4 // CtxSwitch-arm .S --4 // CtxSwitch-arm64.S -- 5 5 // 6 6 // Author : Peter A. Buhr 7 7 // Created On : Sun Aug 16 07:50:13 2020 8 8 // Last Modified By : Peter A. Buhr 9 // Last Modified On : Thu Aug 20 18:43:51202010 // Update Count : 2 49 // Last Modified On : Wed Aug 26 16:24:59 2020 10 // Update Count : 25 11 11 // 12 12 … … 26 26 #define SAVE 20 * 8 27 27 28 .file "CtxSwitch-arm .S"28 .file "CtxSwitch-arm64.S" 29 29 .text 30 30 .align 2 31 31 .global __cfactx_switch 32 .type __cfactx_switch, @function32 .type __cfactx_switch, %function 33 33 __cfactx_switch: 34 34 … … 91 91 .align 2 92 92 .global __cfactx_invoke_stub 93 .type __cfactx_invoke_stub, @function93 .type __cfactx_invoke_stub, %function 94 94 __cfactx_invoke_stub: 95 95 mov x0, x19 // load main as parameter 0 -
libcfa/src/concurrency/kernel.cfa
r56c44dc rce55a81 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Aug 14 15:23:00 202013 // Update Count : 6912 // Last Modified On : Mon Aug 31 07:08:20 2020 13 // Update Count : 71 14 14 // 15 15 … … 74 74 ) 75 75 76 #elif defined( __ARM_ARCH ) 76 #elif defined( __arm__ ) 77 #define __x87_store 78 #define __x87_load 79 80 #elif defined( __aarch64__ ) 77 81 #define __x87_store \ 78 82 uint32_t __fpcntl[2]; \ … … 93 97 94 98 #else 95 #error un knownhardware architecture99 #error unsupported hardware architecture 96 100 #endif 97 101 -
libcfa/src/concurrency/preemption.cfa
r56c44dc rce55a81 10 10 // Created On : Mon Jun 5 14:20:42 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Aug 21 13:45:32202013 // Update Count : 5 212 // Last Modified On : Wed Aug 26 16:46:03 2020 13 // Update Count : 53 14 14 // 15 15 … … 56 56 #elif defined( __x86_64 ) 57 57 #define CFA_REG_IP gregs[REG_RIP] 58 #elif defined( __ARM_ARCH ) 58 #elif defined( __arm__ ) 59 #define CFA_REG_IP arm_pc 60 #elif defined( __aarch64__ ) 59 61 #define CFA_REG_IP pc 60 62 #else 61 #error un knownhardware architecture63 #error unsupported hardware architecture 62 64 #endif 63 65 -
libcfa/src/exception.c
r56c44dc rce55a81 10 10 // Created On : Mon Jun 26 15:13:00 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Aug 21 11:27:56202013 // Update Count : 2912 // Last Modified On : Sat Aug 29 15:52:22 2020 13 // Update Count : 34 14 14 // 15 15 … … 18 18 19 19 #include "exception.h" 20 21 // Implementation of the secret header is hardware dependent.22 #if defined( __x86_64 ) || defined( __i386 )23 #elif defined( __ARM_ARCH )24 #warning FIX ME: check if anything needed for ARM25 #else26 #warning Exception Handling: No known architecture detected.27 #endif28 20 29 21 #include <stdlib.h> … … 34 26 #include "stdhdr/assert.h" 35 27 36 // FIX ME: temporary hack to keep ARM build working 28 #if defined( __ARM_ARCH ) 29 #warning FIX ME: temporary hack to keep ARM build working 37 30 #ifndef _URC_FATAL_PHASE1_ERROR 38 31 #define _URC_FATAL_PHASE1_ERROR 3 … … 41 34 #define _URC_FATAL_PHASE2_ERROR 2 42 35 #endif // ! _URC_FATAL_PHASE2_ERROR 36 #endif // __ARM_ARCH 43 37 44 38 #include "lsda.h" … … 626 620 627 621 #pragma GCC pop_options 622 623 #elif defined( __ARM_ARCH ) 624 _Unwind_Reason_Code __gcfa_personality_v0( 625 int version, 626 _Unwind_Action actions, 627 unsigned long long exception_class, 628 struct _Unwind_Exception * unwind_exception, 629 struct _Unwind_Context * unwind_context) { 630 return _URC_CONTINUE_UNWIND; 631 } 632 633 __attribute__((noinline)) 634 void __cfaehm_try_terminate(void (*try_block)(), 635 void (*catch_block)(int index, exception_t * except), 636 __attribute__((unused)) int (*match_block)(exception_t * except)) { 637 } 638 #else 639 #error unsupported hardware architecture 628 640 #endif // __x86_64 || __i386 -
libcfa/src/heap.cfa
r56c44dc rce55a81 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Aug 24 20:29:24 202013 // Update Count : 9 2612 // Last Modified On : Thu Sep 3 16:22:54 2020 13 // Update Count : 943 14 14 // 15 15 … … 29 29 #include "math.hfa" // ceiling 30 30 #include "bitmanip.hfa" // is_pow2, ceiling2 31 32 #define MIN(x, y) (y > x ? x : y)33 31 34 32 static bool traceHeap = false; … … 956 954 957 955 headers( "realloc", naddr, header, freeElem, bsize, oalign ); 958 memcpy( naddr, oaddr, MIN( osize, size ) ); // copy bytes956 memcpy( naddr, oaddr, min( osize, size ) ); // copy bytes 959 957 free( oaddr ); 960 958 … … 1218 1216 #endif // __STATISTICS__ 1219 1217 1220 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.1221 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases1222 if ( unlikely( oaddr == 0p ) ) {1223 #ifdef __STATISTICS__1224 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST );1225 #endif // __STATISTICS__1226 return memalignNoStats( nalign, size );1227 } // if1228 1229 1218 if ( unlikely( nalign < libAlign() ) ) nalign = libAlign(); // reset alignment to minimum 1230 1219 #ifdef __CFA_DEBUG__ … … 1233 1222 #endif // __CFA_DEBUG__ 1234 1223 1235 HeapManager.Storage.Header * header; 1236 HeapManager.FreeHeader * freeElem; 1237 size_t bsize, oalign; 1238 headers( "resize", oaddr, header, freeElem, bsize, oalign ); 1239 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 1240 1241 if ( oalign <= nalign && (uintptr_t)oaddr % nalign == 0 ) { // <= alignment and new alignment happens to match 1242 if ( oalign > libAlign() ) { // fake header ? 1224 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 1225 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases 1226 if ( unlikely( oaddr == 0p ) ) { 1227 #ifdef __STATISTICS__ 1228 __atomic_add_fetch( &resize_storage, size, __ATOMIC_SEQ_CST ); 1229 #endif // __STATISTICS__ 1230 return memalignNoStats( nalign, size ); 1231 } // if 1232 1233 // Attempt to reuse existing storage. 1234 HeapManager.Storage.Header * header = headerAddr( oaddr ); 1235 if ( unlikely ( ( header->kind.fake.alignment & 1 == 1 && // old fake header ? 1236 (uintptr_t)oaddr % nalign == 0 && // lucky match ? 1237 header->kind.fake.alignment <= nalign && // ok to leave LSB at 1 1238 nalign <= 128 ) // not too much alignment storage wasted ? 1239 || ( header->kind.fake.alignment & 1 != 1 && // old real header ( aligned on libAlign ) ? 1240 nalign == libAlign() ) ) ) { // new alignment also on libAlign 1241 1242 HeapManager.FreeHeader * freeElem; 1243 size_t bsize, oalign; 1244 headers( "resize", oaddr, header, freeElem, bsize, oalign ); 1245 size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket 1246 1247 if ( size <= odsize && odsize <= size * 2 ) { // allow 50% wasted data storage 1243 1248 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1244 } // if 1245 if ( size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size 1246 header->kind.real.blockSize &= -2; // turn off 0 fill 1247 header->kind.real.size = size; // reset allocation size 1249 1250 header->kind.real.blockSize &= -2; // turn off 0 fill 1251 header->kind.real.size = size; // reset allocation size 1248 1252 return oaddr; 1249 1253 } // if … … 1267 1271 #endif // __CFA_DEBUG__ 1268 1272 1273 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned. 1274 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases 1275 if ( unlikely( oaddr == 0p ) ) { 1276 #ifdef __STATISTICS__ 1277 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 1278 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 1279 #endif // __STATISTICS__ 1280 return memalignNoStats( nalign, size ); 1281 } // if 1282 1269 1283 HeapManager.Storage.Header * header; 1270 1284 HeapManager.FreeHeader * freeElem; … … 1272 1286 headers( "realloc", oaddr, header, freeElem, bsize, oalign ); 1273 1287 1274 if ( oalign <= nalign && (uintptr_t)oaddr % nalign == 0 ) { // <= alignment and new alignment happens to match 1275 if ( oalign > libAlign() ) { // fake header ? 1276 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1277 } // if 1288 // Attempt to reuse existing storage. 1289 if ( unlikely ( ( header->kind.fake.alignment & 1 == 1 && // old fake header ? 1290 (uintptr_t)oaddr % nalign == 0 && // lucky match ? 1291 header->kind.fake.alignment <= nalign && // ok to leave LSB at 1 1292 nalign <= 128 ) // not too much alignment storage wasted ? 1293 || ( header->kind.fake.alignment & 1 != 1 && // old real header ( aligned on libAlign ) ? 1294 nalign == libAlign() ) ) ) { // new alignment also on libAlign 1295 1296 headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same) 1278 1297 return realloc( oaddr, size ); 1298 1279 1299 } // if 1280 1300 … … 1286 1306 #endif // __STATISTICS__ 1287 1307 1288 // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.1289 if ( unlikely( size == 0 ) ) { free( oaddr ); return 0p; } // special cases1290 if ( unlikely( oaddr == 0p ) ) return memalignNoStats( nalign, size );1291 1292 1308 size_t osize = header->kind.real.size; // old allocation size 1293 1309 bool ozfill = (header->kind.real.blockSize & 2) != 0; // old allocation zero filled … … 1296 1312 1297 1313 headers( "realloc", naddr, header, freeElem, bsize, oalign ); 1298 memcpy( naddr, oaddr, MIN( osize, size ) ); // copy bytes1314 memcpy( naddr, oaddr, min( osize, size ) ); // copy bytes 1299 1315 free( oaddr ); 1300 1316 -
libcfa/src/stdlib.hfa
r56c44dc rce55a81 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Aug 14 23:38:50202013 // Update Count : 50 412 // Last Modified On : Tue Sep 1 20:32:34 2020 13 // Update Count : 505 14 14 // 15 15 … … 44 44 45 45 // Macro because of returns 46 #define $VAR_ALLOC( allocation, alignment ) \47 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)allocation( (size_t)sizeof(T) ); /* C allocation */ \48 else return (T *)alignment( _Alignof(T), sizeof(T) )49 50 46 #define $ARRAY_ALLOC( allocation, alignment, dim ) \ 51 47 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)allocation( dim, (size_t)sizeof(T) ); /* C allocation */ \ 52 48 else return (T *)alignment( _Alignof(T), dim, sizeof(T) ) 53 49 54 #define $RE_SPECIALS( ptr, size, allocation, alignment ) \55 if ( unlikely( size == 0 ) || unlikely( ptr == 0p ) ) { \56 if ( unlikely( size == 0 ) ) free( ptr ); \57 $VAR_ALLOC( malloc, memalign ); \58 } /* if */59 60 50 static inline forall( dtype T | sized(T) ) { 61 51 // Cforall safe equivalents, i.e., implicit size specification 62 52 63 53 T * malloc( void ) { 64 $VAR_ALLOC( malloc, memalign ); 54 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)malloc( (size_t)sizeof(T) ); // C allocation 55 else return (T *)memalign( _Alignof(T), sizeof(T) ); 65 56 } // malloc 66 57 … … 74 65 75 66 T * resize( T * ptr, size_t size ) { // CFA resize, eliminate return-type cast 76 $RE_SPECIALS( ptr, size, malloc, memalign );77 67 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)resize( (void *)ptr, size ); // CFA resize 78 68 else return (T *)(void *)resize( (void *)ptr, _Alignof(T), size ); // CFA resize … … 80 70 81 71 T * realloc( T * ptr, size_t size ) { // CFA realloc, eliminate return-type cast 82 $RE_SPECIALS( ptr, size, malloc, memalign );83 72 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)realloc( (void *)ptr, size ); // C realloc 84 73 else return (T *)(void *)realloc( (void *)ptr, _Alignof(T), size ); // CFA realloc … … 189 178 size_t copy_end = 0; 190 179 191 if (Resize) {192 ptr = (T*) (void *) resize( ( int*)Resize, Align, Dim * size );193 } else if ( Realloc) {180 if ( Resize ) { 181 ptr = (T*) (void *) resize( (void *)Resize, Align, Dim * size ); 182 } else if ( Realloc ) { 194 183 if (Fill.tag != '0') copy_end = min(malloc_size( Realloc ), Dim * size); 195 ptr = (T*) (void *) realloc( ( int*)Realloc, Align, Dim * size );184 ptr = (T*) (void *) realloc( (void *)Realloc, Align, Dim * size ); 196 185 } else { 197 186 ptr = (T*) (void *) memalign( Align, Dim * size ); … … 201 190 memset( (char *)ptr + copy_end, (int)Fill.c, Dim * size - copy_end ); 202 191 } else if(Fill.tag == 't') { 203 for ( int i = copy_end; i < = Dim * size - size; i += size ) {192 for ( int i = copy_end; i < Dim * size; i += size ) { 204 193 memcpy( (char *)ptr + i, &Fill.t, size ); 205 194 } … … 207 196 memcpy( (char *)ptr + copy_end, Fill.at, min(Dim * size - copy_end, Fill.size) ); 208 197 } else if(Fill.tag == 'T') { 209 for ( int i = copy_end; i < = Dim * size - size; i += size ) {198 for ( int i = copy_end; i < Dim * size; i += size ) { 210 199 memcpy( (char *)ptr + i, Fill.at, size ); 211 200 }
Note:
See TracChangeset
for help on using the changeset viewer.