diff --git a/CHANGELOG b/CHANGELOG index 30b12fa8e..68007cc6c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -51,6 +51,7 @@ passed empty environment is used - compiler: when gcc fails ecl prints the failing command output - ASDF has been updated to 3.1.8.8 +- The Boehm-Demers-Weiser garbage collector has been updated to version 7.6.8 - package local nicknames has been implemented (after SBCL) - hash table extensions are documented in newdoc - various cleanups performed in the compiler diff --git a/src/bdwgc/AUTHORS b/src/bdwgc/AUTHORS index 88ef62c84..2e6cf81da 100644 --- a/src/bdwgc/AUTHORS +++ b/src/bdwgc/AUTHORS @@ -2,6 +2,8 @@ This is an attempt to acknowledge contributions to the garbage collector. Early contributions also mentioned (duplicated) in ChangeLog file; details of later ones should be in "git log". +Currently maintained by Ivan Maidanski. + HISTORY - Early versions of this collector were developed as a part of research @@ -21,11 +23,14 @@ Other contributors (my apologies for any omissions): Adam Megacz Adnan Ali Adrian Bunk +Adrian Pop Akira Tagoh Alain Novak Alan Dosser Alan J. Demers Aleksey Demakov +Alessandro Bruni +Alex Ronne Petersen Alexander Belchenko Alexander Gavrilov Alexander Herz @@ -36,10 +41,11 @@ Alistair G. Crooks Allan Hsu Andre Leiradella Andreas Jaeger -Andreas Tobler +Andreas Tobler Andrei Polushin Andrej Cedilnik Andrew Begel +Andrew Buss Andrew Gray Andrew Haley Andrew Horton @@ -47,6 +53,7 @@ Andrew McKinlay Andrew Pinski Andrew Stitcher Andrew Stone +Andy Li Andy Wingo Anselm Baird-Smith Anthony Green @@ -63,6 +70,7 @@ Ben Hutchings Ben Maurer Benjamin Lerman Bernd Edlinger +Bernd Kuhls Bernie Solomon Bill Janssen Bo Thorsen @@ -80,11 +88,14 @@ Bruce Mitchener Bruno Haible Bryce McKinlay Burkhard Linke +Calvin Hill +Carlos J. Puga Medina Cesar Eduardo Barros Charles Fiterman Charles Mills Chris Dodd Chris Lingard +Chris Metcalf Christian Joensson Christian Limpach Christian Thalinger @@ -115,6 +126,8 @@ David Mossberger David Peroutka David Pickens David Stes +David Terei +David Van Horn Davide Angelocola Dick Porter Dietmar Planitzer @@ -124,33 +137,39 @@ Djamel Magri Doug Kaufman Doug Moen Douglas Steel +Eli Barzilay Elijah Taylor Elvenlord Elrond Emmanual Stumpf Eric Benson Eric Holk +Erik M. Bray Fabian Thylman Fergus Henderson Franklin Chen Fred Gilham Fred Stearns Friedrich Dominicus +Gabor Drescher Gary Leavens Geoff Norton George Talbot Gerard A Allan Glauco Masotti Grzegorz Jakacki +Gustavo Giraldez Gustavo Rodriguez-Rivera H.J. Lu +Hamayama Hannes Mehnert Hanno Boeck Hans Boehm -Hans-Peter Nilsson +Hans-Peter Nilsson Henning Makholm Henrik Theiling Hironori Sakamoto Hiroshi Kawashima +Hiroshi Yokota Hubert Garavel Iain Sandoe Ian Piumarta @@ -167,6 +186,8 @@ James Dominy Jan Alexander Steffens Jan Wielemaker Jani Kajala +Jared McNeill +Jay Krell Jean-Baptiste Nivois Jean-Claude Beaudoin Jean-Daniel Fekete @@ -182,6 +203,7 @@ Ji-Yong Chung Jie Liu Jim Marshall Jim Meyering +Joao Abecasis Joerg Sonnenberger Johannes Schmidt Johannes Totz @@ -190,22 +212,27 @@ John Clements John Ellis John Merryweather Cooper Jon Moore +Jonas Echterhoff Jonathan Bachrach Jonathan Chambers Jonathan Clark Jonathan Pryor +Josh Peterson +Joshua Richardson Juan Jose Garcia-Ripoll Kai Tietz Kaz Kojima Kazu Hirata Kazuhiro Inaoka +Keith Seitz Kenjiro Taura Kenneth Schalk Kevin Kenny Kevin Tew Kevin Warne -Kjetil S. Matheussen +Kjetil Matheussen Klaus Treichel +Klemens Zwischenbrugger Knut Tvedten Krister Walfridsson Kristian Kristensen @@ -213,9 +240,11 @@ Kumar Srikantan Kurt Miller Lars Farm Laurent Morichetti +Leonardo Taccari Linas Vepstas Loren J. Rittle Louis Zhuang +Lucas Meijer Ludovic Courtes Maarten Thibaut Manuel A. Fernandez Montecelo @@ -224,6 +253,7 @@ Marc Recht Marco Maggi Marcos Dione Marcus Herbert +Marek Vasut Margaret Fleck Mark Boulter Mark Mitchell @@ -237,17 +267,23 @@ Matthew Flatt Matthias Andree Matthias Drochner Maurizio Vairani +Max Mouratov Melissa O'Neill Michael Arnoldus +Michael Fox Michael Smith Michael Spertus Michel Schinz Miguel de Icaza +Mikael Djurfeldt +Mike Frysinger Mike Gran Mike McGaughey Mike Stump Mitch Harris Mohan Embar +Naoyuki Sawa +Natanael Copa Nathanael Nerode Neale Ferguson Neil Sharman @@ -263,6 +299,7 @@ Parag Patel Patrick Bridges Patrick C. Beard Patrick Doyle +Paul Bone Paul Brook Paul Graham Paul Nash @@ -300,13 +337,17 @@ Richard Henderson Richard Sandiford Rob Haack Robert Brazile +Rodrigo Kumpera Roger Sayle Roland McGrath Roman Hodek +Romain Naour Romano Paolo Tenca Rutger Ovidius +Ryan Gonzalez Ryan Murray Salvador Eduardo Tropea +Samuel Martin Samuel Thibault Scott Ananian Scott Schwartz @@ -323,10 +364,13 @@ Sven Hartrumpf Sven Verdoolaege Takis Psarogiannakopoulos Tatsuya Bizenn +Terrell Russell Thiemo Seufer Thomas Funke Thomas Klausner +Thomas Linder Puls Thomas Maier +Thomas Schwinge Thorsten Glaser Tilman Vogel Tim Bingham @@ -354,6 +398,7 @@ Xi Wang Xiaokun Zhu Yann Dirson Yannis Bres +Yuki Okumura Yusuke Suzuki Yvan Roux Zach Saw diff --git a/src/bdwgc/BCC_MAKEFILE b/src/bdwgc/BCC_MAKEFILE index 4e4533460..1f4a1b6f2 100644 --- a/src/bdwgc/BCC_MAKEFILE +++ b/src/bdwgc/BCC_MAKEFILE @@ -1,21 +1,19 @@ # Makefile for Borland C++ 5.5 on NT -# If you have the Borland assembler, remove "-DUSE_GENERIC" # bc= c:\Borland\BCC55 bcbin= $(bc)\bin bclib= $(bc)\lib bcinclude= $(bc)\include -gcinclude1 = $(bc)\gc6.2\include -gcinclude2 = $(bc)\gc6.2\cord +gcinclude1 = .\include cc= $(bcbin)\bcc32 rc= $(bcbin)\brc32 lib= $(bcbin)\tlib link= $(bcbin)\ilink32 -cflags= -O2 -R -v- -vi -H -H=gc.csm -I$(bcinclude);$(gcinclude1);$(gcinclude2) -L$(bclib) \ - -w-pro -w-aus -w-par -w-ccc -w-rch -a4 -defines= -DALL_INTERIOR_POINTERS -DUSE_GENERIC -DNO_GETENV -DJAVA_FINALIZATION -DGC_OPERATOR_NEW_ARRAY +cflags= -O2 -R -v- -vi -H -H=gc.csm -I$(bcinclude);$(gcinclude1) -L$(bclib) \ + -w-pro -w-aus -w-par -w-ccc -w-inl -w-rch -a4 +defines= -DALL_INTERIOR_POINTERS -DNO_GETENV -DJAVA_FINALIZATION -DGC_OPERATOR_NEW_ARRAY .c.obj: $(cc) @&&| @@ -28,7 +26,7 @@ defines= -DALL_INTERIOR_POINTERS -DUSE_GENERIC -DNO_GETENV -DJAVA_FINALIZATION - | .rc.res: - $(rc) -i$(bcinclude) -r -fo$* $*.rc + $(rc) -i$(bcinclude) -r -fo$* $*.rc XXXOBJS= XXXalloc.obj XXXreclaim.obj XXXallchblk.obj XXXmisc.obj \ XXXmach_dep.obj XXXos_dep.obj XXXmark_rts.obj XXXheaders.obj XXXmark.obj \ @@ -44,13 +42,13 @@ all: gctest.exe cord\de.exe test_cpp.exe $(OBJS) test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h MAKEFILE gc.lib: $(OBJS) - del gc.lib + -del gc.lib $(lib) $* @&&| $(XXXOBJS:XXX=+) | gctest.exe: tests\test.obj gc.lib - $(cc) @&&| + $(cc) @&&| $(cflags) -W -e$* tests\test.obj gc.lib | @@ -63,25 +61,19 @@ cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj \ $(cflags) -W -e$* cord\cordbscs.obj cord\cordxtra.obj \ cord\tests\de.obj cord\tests\de_win.obj gc.lib | - $(rc) cord\tests\de_win.res cord\de.exe + $(rc) cord\tests\de_win.res cord\de.exe -gc_cpp.obj: include\gc_cpp.h include\gc.h - -gc_cpp.cpp: gc_cpp.cc - copy gc_cpp.cc gc_cpp.cpp +gc_cpp.obj: gc_cpp.cc include\gc_cpp.h include\gc.h test_cpp.cpp: tests\test_cpp.cc copy tests\test_cpp.cc test_cpp.cpp test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib - $(cc) @&&| + $(cc) @&&| $(cflags) -W -e$* test_cpp.obj gc.lib | -scratch: - -del *.obj *.res *.exe *.csm cord\*.obj cord\*.res cord\*.exe cord\*.csm - clean: - del gc.lib - del *.obj - del tests\test.obj + -del *.obj *.res *.exe *.csm cord\*.obj cord\*.res cord\*.exe cord\*.csm + -del cord\*.tds cord\tests\*.obj cord\tests\*.res + -del *.log *.tds gc.lib tests\test.obj "gc.#0*" diff --git a/src/bdwgc/CMakeLists.txt b/src/bdwgc/CMakeLists.txt index bd7b92703..d04abe953 100644 --- a/src/bdwgc/CMakeLists.txt +++ b/src/bdwgc/CMakeLists.txt @@ -25,6 +25,8 @@ SET(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required PROJECT(gc) +INCLUDE(CTest) + CMAKE_MINIMUM_REQUIRED(VERSION 2.6) ADD_DEFINITIONS("-D_CRT_SECURE_NO_DEPRECATE @@ -49,8 +51,7 @@ INCLUDE_DIRECTORIES(libatomic_ops/src) SET(SRC alloc.c reclaim.c allchblk.c misc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c blacklst.c finalize.c new_hblk.c dbg_mlc.c malloc.c stubborn.c dyn_load.c - typd_mlc.c ptr_chck.c gc_cpp.cc mallocx.c checksums.c - thread_local_alloc.c) + typd_mlc.c ptr_chck.c mallocx.c gc_cpp.cc) SET(LIBS) OPTION(enable_threads "TODO" NO) IF(enable_threads) @@ -69,6 +70,7 @@ OPTION(enable_parallel_mark "Parallelize marking and free list construction" NO) #ENDIF(Threads_FOUND) IF(enable_parallel_mark) + ADD_DEFINITIONS("-DPARALLEL_MARK") ENDIF(enable_parallel_mark) OPTION(enable_cplusplus "install C++ support" NO) @@ -82,66 +84,61 @@ MESSAGE("HOST = ${HOST}") #TODO check cmake detection IF(CMAKE_USE_PTHREADS_INIT) SET(SRC ${SRC} pthread_start.c pthread_support.c pthread_stop_world.c) - IF( "HOST" MATCHES x86-.*-linux.*|ia64-.*-linux.*|i586-.*-linux.*|i686-.*-linux.*|x86_64-.*-linux.*|alpha-.*-linux.*|sparc.*-.*-linux.*) + IF( HOST MATCHES x86-.*-linux.*|ia64-.*-linux.*|i586-.*-linux.*|i686-.*-linux.*|x86_64-.*-linux.*|alpha-.*-linux.*|sparc.*-.*-linux.*) ADD_DEFINITIONS("-DGC_LINUX_THREADS") ADD_DEFINITIONS("-D_REENTRANT") - IF (${enable_parallel_mark}) - ADD_DEFINITIONS("-DPARALLEL_MARK") - ENDIF() ADD_DEFINITIONS("-DTHREAD_LOCAL_ALLOC") + SET(SRC ${SRC} thread_local_alloc.c) MESSAGE("Explicit GC_INIT() calls may be required.") ENDIF() - IF ( "HOST" MATCHES .*-.*-linux.*) + IF ( HOST MATCHES .*-.*-linux.*) ADD_DEFINITIONS("-DGC_LINUX_THREADS") ADD_DEFINITIONS("-D_REENTRANT") ENDIF() - IF ( "HOST" MATCHES .*-.*-aix.*) + IF ( HOST MATCHES .*-.*-aix.*) ADD_DEFINITIONS("-DGC_AIX_THREADS") ADD_DEFINITIONS("-D_REENTRANT") ENDIF() - IF ( "HOST" MATCHES .*-.*-hpux11.*) + IF ( HOST MATCHES .*-.*-hpux11.*) MESSAGE("Only HP/UX 11 POSIX threads are supported.") ADD_DEFINITIONS("-DGC_HPUX_THREADS") ADD_DEFINITIONS("-D_POSIX_C_SOURCE=199506L") #TODO test -DVAR=value. Alternative is COMPILE_DEFINITIONS property - IF (${enable_parallel_mark}) - ADD_DEFINITIONS("-DPARALLEL_MARK") - ENDIF() MESSAGE("Explicit GC_INIT() calls may be required.") ADD_DEFINITIONS("-D_REENTRANT") #TODO ENDIF() - IF ( "HOST" MATCHES .*-.*-hpux10.*) + IF ( HOST MATCHES .*-.*-hpux10.*) MESSAGE("Only HP/UX 11 POSIX threads are supported.") ENDIF() - IF ( "HOST" MATCHES .*-.*-openbsd.*) + IF ( HOST MATCHES .*-.*-openbsd.*) ADD_DEFINITIONS("-DGC_OPENBSD_THREADS") ENDIF() - IF ( "HOST" MATCHES .*-.*-freebsd.*) + IF ( HOST MATCHES .*-.*-freebsd.*) MESSAGE("FreeBSD does not yet fully support threads with Boehm GC.") ADD_DEFINITIONS("-DGC_FREEBSD_THREADS") ENDIF() - IF ( "HOST" MATCHES .*-.*-kfreebsd.*-gnu) + IF ( HOST MATCHES .*-.*-kfreebsd.*-gnu) ADD_DEFINITIONS("-DGC_FREEBSD_THREADS") ADD_DEFINITIONS("-D_REENTRANT") - IF (${enable_parallel_mark}) - ADD_DEFINITIONS("-DPARALLEL_MARK") - ENDIF() ADD_DEFINITIONS("-DTHREAD_LOCAL_ALLOC") ADD_DEFINITIONS("-DUSE_COMPILER_TLS") + SET(SRC ${SRC} thread_local_alloc.c) ENDIF() - IF ( "HOST" MATCHES .*-.*-gnu.*) + IF ( HOST MATCHES .*-.*-gnu.*) ADD_DEFINITIONS("-DGC_GNU_THREADS") ADD_DEFINITIONS("-D_REENTRANT") ADD_DEFINITIONS("-DTHREAD_LOCAL_ALLOC") + SET(SRC ${SRC} thread_local_alloc.c) ENDIF() - IF ( "HOST" MATCHES .*-.*-netbsd.*) + IF ( HOST MATCHES .*-.*-netbsd.*) MESSAGE("Only on NetBSD 2.0 or later.") ADD_DEFINITIONS("-DGC_NETBSD_THREADS") ADD_DEFINITIONS("-D_REENTRANT") ADD_DEFINITIONS("-D_PTHREADS") ENDIF() - IF ( "HOST" MATCHES .*-.*-solaris.*) + IF ( HOST MATCHES .*-.*-solaris.*) ADD_DEFINITIONS("-DGC_SOLARIS_THREADS") ADD_DEFINITIONS("-DTHREAD_LOCAL_ALLOC") + SET(SRC ${SRC} thread_local_alloc.c) #TODO # if test "$GCC" != yes; then # CFLAGS="$CFLAGS -O" @@ -149,41 +146,33 @@ IF(CMAKE_USE_PTHREADS_INIT) # fi ENDIF() - IF ( "HOST" MATCHES .*-.*-irix.*) + IF ( HOST MATCHES .*-.*-irix.*) ADD_DEFINITIONS("-DGC_IRIX_THREADS") ENDIF() - IF ( "HOST" MATCHES .*-.*-cygwin.*) + IF ( HOST MATCHES .*-.*-cygwin.*) ADD_DEFINITIONS("-DGC_THREADS") - IF (${enable_parallel_mark}) - ADD_DEFINITIONS("-DPARALLEL_MARK") - ENDIF() ADD_DEFINITIONS("-DTHREAD_LOCAL_ALLOC") - -#TODO -# win32_threads=true + SET(SRC ${SRC} thread_local_alloc.c win32_threads.c) ENDIF() - IF ( "HOST" MATCHES .*-.*-darwin.*) + IF ( HOST MATCHES .*-.*-darwin.*) ADD_DEFINITIONS("-DGC_DARWIN_THREADS") ADD_DEFINITIONS("-DTHREAD_LOCAL_ALLOC") MESSAGE("Explicit GC_INIT() calls may be required.") - SET(SRC ${SRC} darwin_stop_world.c) - IF (${enable_parallel_mark}) - ADD_DEFINITIONS("-DPARALLEL_MARK") - ENDIF() + SET(SRC ${SRC} darwin_stop_world.c thread_local_alloc.c) #TODO #darwin_threads=true ENDIF() - IF ( "HOST" MATCHES .*-.*-osf*) + IF ( HOST MATCHES .*-.*-osf.*) ADD_DEFINITIONS("-DGC_OSF1_THREADS") - IF (${enable_parallel_mark}) - ADD_DEFINITIONS("-DPARALLEL_MARK") + IF(enable_parallel_mark) ADD_DEFINITIONS("-DTHREAD_LOCAL_ALLOC") + SET(SRC ${SRC} thread_local_alloc.c) MESSAGE("Explicit GC_INIT() calls may be required.") # May want to enable it in other cases, too. # Measurements haven't yet been done. ENDIF() ENDIF() - IF ( "HOST" MATCHES .*-.*-linux.*) + IF ( HOST MATCHES .*-.*-linux.*) ADD_DEFINITIONS("-DGC_LINUX_THREADS") ADD_DEFINITIONS("-D_REENTRANT") ENDIF() @@ -191,10 +180,9 @@ ENDIF(CMAKE_USE_PTHREADS_INIT) IF(CMAKE_USE_WIN32_THREADS_INIT) ADD_DEFINITIONS("-DGC_THREADS") - #win32_threads=true TODO - IF (${enable_parallel_mark}) - ADD_DEFINITIONS("-DPARALLEL_MARK") + IF(enable_parallel_mark) ADD_DEFINITIONS("-DTHREAD_LOCAL_ALLOC") + SET(SRC ${SRC} thread_local_alloc.c) ENDIF() ADD_DEFINITIONS("-DEMPTY_GETENV_RESULTS") #TODO test SET(SRC ${SRC} win32_threads.c) @@ -203,6 +191,10 @@ ENDIF(CMAKE_USE_WIN32_THREADS_INIT) OPTION(enable_gcj_support "Support for gcj" NO) IF(enable_gcj_support) ADD_DEFINITIONS("-DGC_GCJ_SUPPORT") + IF(enable_threads) + ADD_DEFINITIONS("-DGC_ENABLE_SUSPEND_THREAD") + ENDIF(enable_threads) + SET(SRC ${SRC} gcj_mlc.c) ENDIF(enable_gcj_support) diff --git a/src/bdwgc/ChangeLog b/src/bdwgc/ChangeLog index 12b3aad94..f6e799c6e 100644 --- a/src/bdwgc/ChangeLog +++ b/src/bdwgc/ChangeLog @@ -1,444 +1,1258 @@ -== [7.5.0] (development) == +== [7.6.8] 2018-08-12 == -* Add API function to set/modify GC log file descriptor (Unix). -* Add alloc_size attribute to GC_generic_malloc. -* Added instructions to README.md for building from git. -* Allow to force GC_dump_regularly set on at compilation. -* Change 'cord' no-argument functions declaration style to ANSI C. -* Define ROUNDUP_PAGESIZE, ROUNDUP_GRANULE_SIZE macros (code refactoring). -* Define public GC_GENERIC_OR_SPECIAL_MALLOC and GC_get_kind_and_size. -* Eliminate redundant *flh check for null in GC_allocobj. -* GC_scratch_alloc code refactoring (and WARN message improvement). -* Group all compact fields of GC_arrays to fit in single page. -* Improve documentation for disappearing links in gc.h. -* Make heap growth more conservative after GC_gcollect_and_unmap call. -* New macro (GC_ALWAYS_MULTITHREADED) to set multi-threaded mode implicitly. -* Refine description in README how to build from source repository. -* Remove 'opp' local variable in GC_malloc_X. -* Remove hb_large_block field (use 1 extra bit of hb_flags instead). -* Remove obsolete BACKING_STORE_ALIGNMENT/DISPLACEMENT macros for Linux/IA64. -* Remove redundant casts in GC_generic_or_special_malloc and similar. -* Use magic header on objects to improve disclaim_test. -Also, includes 7.4.2 changes. +* Add cpu, make_as_lib, nothreads options to NT_MAKEFILE +* Add NetBSD/aarch64 and initial RISC-V support +* Adjust formatting of configure help messages and config.h comments +* Avoid multiple 'getcontext failed' warnings if getcontext is broken +* Cleanup BCC Makefile (remove absolute GC paths, fix del cmd, update clean) +* Collapse multiple NT_*_MAKEFILE scripts into a single NT_MAKEFILE +* Do not call GC_dirty_inner unless GC_incremental +* Do not use NULL in gc_inline.h +* Eliminate 'cast between incompatible function types' compiler warning +* Eliminate 'comparing signed and unsigned values' compiler warnings (bcc) +* Eliminate 'condition is always true' cppcheck warning in init_gcj_malloc +* Eliminate 'declaration of var hides global declaration' compiler warning +* Eliminate 'language extension used' Clang warning in gc.h +* Eliminate 'possibly incorrect assignment in CORD_vsprintf' compiler warning +* Eliminate 'ptr arithmetic with NULL' cppcheck warning in alloc_mark_stack +* Eliminate 'scope of var can be reduced' cppcheck warning in pthread_join +* Eliminate 'switch statement contains no case label' compiler warning +* Eliminate 'variable might be uninitialized' warning in win32_start_inner +* Eliminate duplicate clear_mark_bit call when removing disappearing link +* Fast fail on invalid CPU parameter passed to NT_MAKEFILE +* Fix 'collecting from unknown thread' abort in leak-finding mode +* Fix 'pointer arithmetic with NULL' code defect in print_callers +* Fix Borland version in documentation to match that in BCC_MAKEFILE +* Fix comment about inv_sz computation in setup_header +* Fix comments style in configure.ac and Makefile.am +* Fix compilation by digimars.mak (DMC) +* Fix compilation by WCC makefile +* Fix compilation of darwin_stop_world for iOS 8+ +* Fix cords for MANUAL_VDB +* Fix dependency on gc_cpp source in BCC_MAKEFILE and NT_MAKEFILE +* Fix GC_is_valid_displacement and GC_is_visible for non-small objects +* Fix gctest in leak-finding mode +* Fix infinite restarting of mark_some when a static root disappeared (Linux) +* Fix large object base computation in PUSH_CONTENTS() if MARK_BIT_PER_OBJ +* Fix mark stack overflow checking in push_selected +* Fix missing GC_dirty calls for GC-allocated objects used internally +* Fix missing GC_dirty invocation from debug_end_stubborn_change +* Fix MSWIN32 macro redefinition (WCC) +* Fix multi-threaded gctest for the case of NTHREADS is set to zero +* Fix new and delete operators definition for DigitalMars compiler +* Fix NT_MAKEFILE for VS 2017 +* Fix potential null dereference in GC_CONS +* Fix register_dynamic_libraries on Windows 10 +* Fix result computation in n_set_marks +* Fix return type in GC_set_warn_proc API documentation +* Fix tests for GC compiled with MANUAL_VDB +* Fix the build for Emscripten +* Fix typo in comment for CORD_ec_flush_buf prototype +* Fix typos in ChangeLog and generic_malloc +* Fix UNTESTED for multi-threaded API functions in gctest +* Fix VirtualQuery call in case of malloc failure (Win32) +* Install gc.3 man page instead of copying gc.man to doc folder (configure) +* Keep pointer to the start of previous entry in remove_specific_after_fork +* Move de_win compiled resource files to cord/tests +* Never return null by C++ GC allocators and gc_cpp operator new +* Perform thread_suspend in loop as it may be interrupted (Darwin) +* Really abort if failed to read /proc for library registration (Linux) +* Remove code duplication in gcj_malloc and malloc_explicitly_typed +* Remove duplicate local variable in reclaim_block +* Remove information how to send bugs from README.cords file +* Remove libatomic_ops license information +* Remove unused USE_GENERIC macro definition and description +* Suppress 'functions containing switch are not expanded inline' bcc warning +* Suppress 'non-member operator new/delete may not be inline' VC++ warning +* Turn on incremental collection in gctest also if MANUAL_VDB +* Update copyright information in alloc.c, gc.c/h and the documentation +* Update EXTRA_DIST in Makefile, Win32/64 docs after NT_*_MAKEFILE removal +* Update NT_MAKEFILE usage information in README files for Win32 and Win64 +* Workaround 'class C does not have a copy constructor' cppcheck warning +* Workaround 'function nested_sp is never used' cppcheck style warning +* Workaround 'opposite expression on both sides of &' cppcheck style warning +* Workaround 'template-id not supported in this context' compiler error (WCC) + + +== [7.6.6] 2018-04-20 == + +* Define GC_FREEBSD_THREADS and GC_ADD_CALLER macros for kFreeBSD +* Eliminate 'boolean result used in bitwise operation' cppcheck warning +* Eliminate 'there is pointer arithmetic with NULL' cppcheck warning +* Explicitly unblock GC signals on GC initialization +* Fix 'scope of var can be reduced' cppcheck err in enqueue_all_finalizers +* Fix 'undefined reference to __builtin_unwind_init' linker error (ArmCC) +* Fix arguments delimiter in pcr_interface.c (PCR) +* Fix assertion violation in DllMain of win32_threads +* Fix comment for debug_generic_malloc_inner[_ignore_off_page] +* Fix data race during apply_to_each_object(reset_back_edge) +* Fix dbg_mlc.c/o file name in documentation +* Fix gctest with musl libc on s390x +* Fix include gc_gcj.h in thread_local_alloc.c +* Fix man section number (3) +* Fix missing GC_generic_malloc_words_small implementation in new_gc_alloc.h +* Fix missing new-line in ABORT_ARG definition +* Fix missing SIGBUS handler setup for kFreeBSD +* Fix null dereference in print_callers on backtrace_symbols failure +* Fix null pointer dereference in get_private_path_and_zero_file (Symbian) +* Fix the collector hang when it is configured with --enable-gc-debug +* Fix thread_suspend fail for threads registered from key destructor (OS X) +* Fix type of local variables receiving result of PHT_HASH +* Fix typo in AIX macro name +* Fix typo in comment in specific.h +* Fix unbounded heap growth in case of intensive disappearing links usage +* Remove API symbols renaming in WCC_MAKEFILE +* Support Haiku/amd64 and Haiku/x86 hosts +* Support threads for DragonFly in configure +* Workaround 'address of auto-variable returned' cppcheck error +* Workaround gctest hang on kFreeBSD (if thread-local allocations are on) + + +== [7.6.4] 2018-01-26 == + +* Add note of set_free_space_divisor, set_warn_proc ABI change after gc-7.1 +* Change compiler invocation example in gc.man to use dynamic libgc +* Delete dont_ar_* build intermediate files on make clean (Makefile.direct) +* Do not declare dl_iterate_phdr as weak for DragonFly +* Fix 'cords' parallel build in Makefile.direct +* Fix 'undeclared identifier USRSTACK' compiler error on OpenBSD-6.2 +* Fix error code in abort message if sem_wait failed in start_world (NetBSD) +* Fix GC allocation mutex in child after a fork +* Fix global operator delete definition for C++14 in gc_cpp +* Fix last_reclaimed..gc_no interval comparison to threshold in unmap_old +* Fix libgc version which was changed in linkage breaking way +* Fix missing EOLn output in threadlibs tool +* Fix threadlibs tool to output '-lpthread' for DragonFly +* Prevent DATASTART redefinition for NaCl +* Remove obsolete advice about linking with _DYNAMIC=0 (Linux) + + +== [7.6.2] 2017-12-23 == + +* Add assertion that no hb_n_marks underflow occurs +* Add minimal testing of GC_MALLOC_[ATOMIC_]WORDS and GC_CONS (gctest) +* Add minimal testing of GC_set_bit (gctest) +* Add more cases to huge_test to cover sizes close to word-type maximum +* Add testing of new[]/delete[] (test_cpp) +* Adjust AO_HAVE_x check to match AO_fetch_and_add primitive variant used +* Adjust code indentation of calloc_explicitly_typed +* Align local_mark_stack in help_marker explicitly +* Allow custom TRACE_ENTRIES value +* Allow gctest and thread_leak_test with zero NTHREADS +* Avoid data race in finalized_count (gctest) +* Code refactoring of divide-by-HBLKSIZE occurrences +* Code refactoring of huge_test +* Code refactoring of tests/subthread_create regarding AO add primitive +* Compile thread_local_alloc only if multi-threaded build (Makefile.am) +* Delete preprocessor output on make clean (Makefile.direct) +* Disable implicit multi-threaded mode for Win32 to avoid LOCK crash +* Do not disable parallel mark for WRAP_MARK_SOME +* Do not enable mprotect-based incremental mode if unmapping is on (gctest) +* Do not install documentation if configure --disable-docs (new option) +* Do not use tkill (Android) +* Document base and size of objects allocated by finalized_malloc +* Document configure 'syntax error' issue in README +* Eliminate 'address of local variable returned' static analyzer warning +* Eliminate 'array vs singleton' code defect in typed_test (gctest) +* Eliminate 'assigned value never used' CSA warning in min_bytes_allocd +* Eliminate 'boolean result used in bitwise op' cppcheck false warning +* Eliminate 'C-style pointer casting' cppcheck style warnings in test +* Eliminate 'checking if unsigned variable is <0' cppcheck style warning +* Eliminate 'class member var with name also defined in parent' warning +* Eliminate 'comparison is always false' static analyzer warning in finalize +* Eliminate 'Condition 0==datastart always false' cppcheck warning (dyn_load) +* Eliminate 'condition is always true' cppcheck style warning +* Eliminate 'constructor with 1 argument is not explicit' cppcheck warning +* Eliminate 'CORD_*printf is never used' cppcheck style warnings (cordtest) +* Eliminate 'dereference of null' CSA false warning in array_mark_proc +* Eliminate 'function result not used' code defect in GC_mark_local +* Eliminate 'GC_collecting is set but never used' code defect (Win32) +* Eliminate 'GC_record_fault is never used' cppcheck style warning +* Eliminate 'integer shift by a negative amount' code defect in finalize +* Eliminate 'label not used' cppcheck false warnings in GC_mark_X +* Eliminate 'memory leak' code defect for scratch-allocated memory +* Eliminate 'memory leak' code defect in remove_specific +* Eliminate 'non-null arg compared to null' warning in toggleref_add (GCC) +* Eliminate 'non-reentrant function strtok called' cppcheck warning (POSIX) +* Eliminate 'possible integer underflow' code defect (cord-de) +* Eliminate 'potential overflow' static analyzer warning in test +* Eliminate 'printf format specifies type void*' GCC pedantic warnings +* Eliminate 'scope of variable can be reduced' cppcheck warnings +* Eliminate 'suspicious pointer subtraction' cppcheck warning (gc_cpp) +* Eliminate 'this statement may fall through' GCC warnings +* Eliminate 'unnecessary comparison of static strings' cppcheck warning +* Eliminate 'unsafe vsprintf is deprecated' compiler warning +* Eliminate 'unused formal parameter' compiler warnings in C++ code (MS VC) +* Eliminate 'unused variable' compiler warning in remove_all_threads_but_me +* Eliminate 'use of vulnerable sprintf' code defect in de_win test (cord) +* Eliminate 'value exceeds maximum object size' GCC warning in huge_test +* Eliminate 'value of CLOCK_TYPE unknown' cppcheck info message +* Eliminate 'value of DATASTART2 unknown' cppcheck info messages +* Eliminate 'value of GC_PTHREAD_EXIT_ATTRIBUTE unknown' cppcheck messages +* Eliminate 'value of GC_RETURN_ADDR_PARENT unknown' cppcheck info messages +* Eliminate 'value of NEED_FIXUP_POINTER unknown' cppcheck info messages +* Eliminate 'write to memory that was const-qualified' code analyzer warning +* Eliminate all 'scope of variable can be reduced' cppcheck style warnings +* Eliminate CSA warning about incorrect cast applied to HBLK_OBJS +* Eliminate CSA warning about narrowing cast in CleanUp of test_cpp +* Eliminate CSA warning of non-virtual destructor in test_cpp base class +* Eliminate CSA warning of staticroot that can be a local variable (tests) +* Eliminate CSA warning of unmodified non-const static var (disclaim_test) +* Eliminate redundant local variable in register_finalizer +* Eliminate TSan (Thread Sanitizer) warnings in gctest +* Eliminate UBSan warning of overflow during descr subtraction in mark_from +* Eliminate unreachable PROC/DEFAULT_VDB GC_printf calls in gctest main() +* Eliminate unsigned fl_builder_count underflow in mark_thread +* Enable GC_is_tmp_root for all platforms +* Execute more single-threaded GC tests by CMake +* Expand tabs to spaces in de_win.rc (tests) +* Export GC_dump_finalization/regions() +* Export GC_is_tmp_root() and GC_print_trace[_inner]() +* Export GC_print_free_list() +* Fix '32-bit value shift followed by expansion to 64-bit' code defect +* Fix 'GC_written_pages never read' code defect (GWW_VDB) +* Fix 'label cannot be reached' static analyzer warning in disclaim_test +* Fix 'size of tv is unknown' error in brief_async_signal_safe_sleep (musl) +* Fix 'syntax error' reported by cppcheck for mach_dep +* Fix 'unknown type name GC_INNER' compilation error (FreeBSD) +* Fix 'variable assigned a value that is never used' cppcheck style warnings +* Fix 'void pointers in calculations: behavior undefined' cppcheck warning +* Fix assertion violation about disabled cancel in try_to_collect_inner +* Fix atomic_ops build in Makefile.direct for Solaris +* Fix Clang static analyzer warning about not found gc_priv.h in extra files +* Fix compilation error in get_main_stack_base (Emscripten) +* Fix compilation for winpthreads if HANDLE_FORK +* Fix compilation if configured with --enable-werror on OS X +* Fix cord/de build in Makefile.direct (Linux) +* Fix data race in a list referenced by A.aa (gctest) +* Fix data race in collectable_count (gctest) +* Fix data race in do_local_mark when comparing active_count to helper_count +* Fix data race in GC_suspend/resume_thread +* Fix data race in last_stop_count access (suspend_handler_inner) +* Fix data race in make_descriptor when setting explicit_typing_initialized +* Fix data race in mark_thread when updating mark_no +* Fix data race when getting object size in explicitly-typed allocators +* Fix deadlock in GC_suspend_thread +* Fix gctest failure for Darwin if CPPCHECK is defined +* Fix lack of barriers to synchronize memory for suspend_handler +* Fix marking of disclaim-reachable objects in the incremental mode +* Fix message of VDB implementation used if MPROTECT_VDB+GWW_VDB (gctest) +* Fix missing started_thread_while_stopped call from mark_some if GCC/Clang +* Fix null dereference in GC_stack_range_for if not DARWIN_DONT_PARSE_STACK +* Fix page calculation in checksums +* Fix parallel build in Makefile.direct +* Fix test_cpp and c++ parallel build in Makefile.direct +* Fix typo in comment of GC_mark_some +* Fix typos in cdescr.html and README.sgi +* Make GC_INIT optional for clients even if thread-local allocations enabled +* Match uclinux pattern in configure +* Move conditional GC_need_to_lock setting to gc_locks.h (refactoring) +* Move README.QUICK from DOC_FILES to OTHER_FILES in Makefile.direct +* New API function (GC_is_init_called) to check if BDWGC is initialized +* New target (check-cpp) in Makefile.direct +* Prevent abort in register_data_segments for Symbian and Emscripten +* Prevent multiple 'Caught ACCESS_VIOLATION in marker' per collection +* Print realloc_count value in gctest +* Put invariant name in quotes to make mark_state comments clearer +* Refine configure messages when checking for compiler option support +* Remove extraneous semicolons after AC_MSG_WARN (configure) +* Remove page_was_dirty and remove_protection duplicate definitions +* Remove unnecessary type casts of printf arguments to unsigned long +* Remove unused ALIGN_DOUBLE, USE_GENERIC_PUSH_REGS macros (TILE-Gx/Pro) +* Rename 'test' to 'check' target in Makefile.direct +* Replace deprecated rewind to fseek in cordxtra +* Report gcc/clang pedantic warnings (configure) +* Skip thread suspend/resume API testing for Tru64 (OSF1) +* Support AddressSanitizer (Clang/GCC) and MemorySanitizer (Clang) +* Support GC_init (and get_stack_base) from non-main thread on FreeBSD/NetBSD +* Suppress 'tainted string passed to vulnerable operation' false defects +* Suppress 'taking address of label non-standard' GCC/Clang pedantic warning +* Test GC initialization from non-main thread on FreeBSD and NetBSD +* Test GCJ object creation with length-based descriptor (gctest) +* Update comment in finalized_disclaim to match FINALIZER_CLOSURE_FLAG +* Update README regarding make cords with Makefile.direct +* Update README to use autogen.sh on build from the source repository +* Update shared libraries version info to differentiate against v7.4 +* Use mprotect instead of mmap in GC_unmap() on Cygwin +* Use same style of include gc.h in documentation +* Workaround '!GC_page_size is always false' cppcheck style warning +* Workaround '#error' cppcheck error messages +* Workaround '32-bit value shift by >31 bits is undefined' cppcheck warnings +* Workaround 'array compared to 0', 'untrusted loop bound' false defects +* Workaround 'bad address arithmetic' static analysis tool false positive +* Workaround 'checking if unsigned value is negative' cppcheck warning +* Workaround 'checking unsigned value is negative' code defect in mark_from +* Workaround 'comparison of identical expressions' false code defects +* Workaround 'Condition 0!=GETENV() is always false' cppcheck style warnings +* Workaround 'condition is always false' cppcheck warning in get_next_stack +* Workaround 'condition is always true' cppcheck style warnings in GC_init +* Workaround 'function is never used' cppcheck style warnings +* Workaround 'insecure libc pseudo-random number generator used' code defect +* Workaround 'int shift by negative amount' false code defect in finalize +* Workaround 'local variable size too big' static analyzer warning +* Workaround 'memory leak: result' cppcheck false error (POSIX) +* Workaround 'null pointer dereference' false positive in push_next_marked +* Workaround 'obsolescent bcopy, bzero called' cppcheck warnings (POSIX) +* Workaround 'obsolescent usleep called' cppcheck warning (POSIX) +* Workaround 'obsolete function alloca() called' cppcheck warnings +* Workaround 'passing untyped NULL to variadic function' cppcheck warning +* Workaround 'pointer used before comparison to null' code defect (pthread) +* Workaround 'possible null pointer dereference' cppcheck warnings +* Workaround 'potential multiplication overflow' code defect in de_win (cord) +* Workaround 'redundant assignment of *result to itself' cppcheck warning +* Workaround 'resource leak' false positives in alloc_MS, bl/envfile_init +* Workaround 'same expression on both sides of ==' cppcheck style warning +* Workaround 'same expression on both sides of OR' cppcheck style warning +* Workaround 'struct member is never used' cppcheck style warnings +* Workaround 'tainted int used as loop bound' static analysis tool warning +* Workaround 'Uninitialized variable' cppcheck errors +* Workaround 'unused variable' cppcheck style warnings +* Workaround 'va_list used before va_start' cppcheck error in cord +* Workaround 'value of macro unknown' cppcheck info messages +* Workaround 'value of REDIRECT_MALLOC/FREE unknown' cppcheck info messages +* Workaround 'value of SIGBUS unknown' cppcheck info messages +* Workaround 'value of WINAPI unknown' cppcheck info messages +* Workaround 'variable hides enumerator with same name' cppcheck warnings +* Workaround 'variable reassigned before old value used' cppcheck warnings +* Workaround 'waiting while holding lock' code defect in stop_world (Unix) +* Workaround false 'uninitialized var use' code defect (initsecondarythread) + +Also, includes 7.4.6 changes + + +== [7.6.0] 2016-08-02 == + +* ABORT_ARGn log details at INFO level (Android) +* Add 'pragma message' to gc.h to detect inconsistent WIN64/_WIN64 (MS VC) +* Add API function to calculate total memory in use by all GC blocks +* Add API function to set/modify GC log file descriptor (Unix) +* Add alloc_size attribute to GC_generic_malloc +* Add alt-stack registration support +* Add assertion for GC_new_kind boolean arguments +* Add assertion on lock status to GC_alloc_large and its callers +* Add build scripts for VC 9 (Win32/64) +* Add build system plumbing for building with -Werror +* Add incremental GC support for Darwin/arm64 +* Add profiling callback events to indicate start/end of reclaim phase +* Add support for enumerating the reachable objects in the heap +* Add toggle-ref support (following Mono GC API) +* Added instructions to README.md for building from git +* Adjust code indentation of malloc/calloc/str[n]dup +* Allow fork() automatic handling on Android with API level 21+ +* Allow specific TLS attributes for GC_thread_key +* Allow thread local allocations from within pthread TLS destructors +* Allow to force GC_dump_regularly set on at compilation +* Altera NIOS2 support +* Change 'cord' no-argument functions declaration style to ANSI C +* Check DATASTART is less than DATAEND even assertions off +* Check for execinfo.h by configure +* Code refactoring of GC_push_finalizer/thread/typed_structures +* Code refactoring regarding 'data start' definition for FreeBSD +* Consistently set type of DATASTART/END to ptr_t (code refactoring) +* Consistently use int[] type for '_end' symbol (code refactoring) +* Consistently use outermost parentheses for DATASTART/END, STACKBOTTOM +* Define GC_LINUX_THREADS, NO_EXECUTE_PERMISSION in configure for NaCl +* Define ROUNDUP_PAGESIZE, ROUNDUP_GRANULE_SIZE macros (code refactoring) +* Define public GC_GENERIC_OR_SPECIAL_MALLOC and GC_get_kind_and_size +* Do no declare kernel_id field of GC_Thread_Rep for 64-bit Android +* Do not allow SHORT_DBG_HDRS if KEEP_BACK_PTRS or MAKE_BACK_GRAPH +* Do not warn of missing PT_GNU_RELRO segment when custom DSO filter used +* Document GC_register_my_thread returned value +* Dump the block information in CSV format +* Eliminate redundant *flh check for null in GC_allocobj +* Enable atomic-uncollectable in operator new in gc_cpp.h +* Enable build with musl libc +* Enable gc.h inclusion by client without implicit include windows.h (Win32) +* Enable huge_test for Win64 (and LLP64 target) +* Enable thread-local storage for Android Clang +* Enable thread-local storage usage for GC_malloc/calloc_explicitly_typed +* Export GC_push_all_eager, GC_push_finalizer_structures +* Fix 'arg parameter might be clobbered by setjmp' compiler warning +* Fix assertion in GC_mark_from for non-heap regions +* Fix compilation for Android clang/arm with bfd linker +* Fix integer shift undefined behavior in GC_init_explicit_typing +* Fix missing new-line and redundant trailing dot in WARN messages +* Fix STACKBOTTOM for Solaris 11/x86 +* Fix tag collision between ENABLE_DISCLAIM and KEEP_BACK_PTRS +* Fix unchecked fork() result in gctest (Unix, Cygwin) +* Fix user-defined signals drop by marker threads +* Fix various typos in comments and documentation +* FreeBSD/arm support improvement +* GC_make_descriptor code refactoring (eliminate two local variables) +* GC_malloc[_atomic] global and thread-local generalization with kind +* GC_malloc_[atomic_]uncollectable generalization +* GC_scratch_alloc code refactoring (and WARN message improvement) +* Group all compact fields of GC_arrays to fit in single page +* Handle load_segs overflow in register_dynlib_callback gracefully +* Harmonize OSX/iOS configuration; enable compiling for iPhone simulator +* Implement event callbacks for profiling (following Mono GC API) +* Implement the finalization extension API +* Implement thread suspend/resume API (Linux threads only) +* Improve documentation for disappearing links in gc.h +* Make heap growth more conservative after GC_gcollect_and_unmap call +* Mark fo_head, finalize_now with a single GC_push_all call (refactoring) +* Move MessageBox invocation code from GC_abort to a separate routine (Win32) +* NaCl/arm initial support; NaCl runtime fixes for other CPUs +* New macro (GC_ALWAYS_MULTITHREADED) to set multi-threaded mode implicitly +* New macro (NO_WINMAIN_ENTRY) to prefer main() instead of WinMain in test +* New macro (REDIRECT_MALLOC_IN_HEADER) to enable source-level redirection +* Process all PT_LOAD segments before PT_GNU_RELRO segments (Glibc) +* Re-implement GC_finalized_malloc using GC_malloc_kind +* Refactoring of android_thread_kill/pthread_kill calls +* Refactoring of GC_Xobjfreelist (use single array to keep free lists) +* Refactoring of thread-local *_freelists (use single array of free lists) +* Refine description in README how to build from source repository +* Refine GC_free_space_divisor comment regarding its initial value +* Reformat code of gc_cpp.cc/h +* Remove 'opp' local variable in GC_malloc_X +* Remove 'sig' argument of GC_suspend_handler_inner (code refactoring) +* Remove code commented out by 'ifdef UNDEFINED' +* Remove hb_large_block field (use 1 extra bit of hb_flags instead) +* Remove obsolete BACKING_STORE_ALIGNMENT/DISPLACEMENT macros for Linux/IA64 +* Remove redundant casts in GC_generic_or_special_malloc and similar +* Remove unsupported FreeBSD/ia64 case from gcconfig.h file +* Remove unused GC_gcjdebugobjfreelist +* Rename ATOMIC_UNCOLLECTABLE to GC_ATOMIC_UNCOLLECTABLE +* Replace non-API occurrences of GC_word to word (code refactoring) +* Return GC_UNIMPLEMENTED instead of abort in GC_get_stack_base (OS/2) +* Show WoW64 warning message if running 32-bit on Win64 (enabled by macro) +* Standalone profiling callback for threads suspend/resume +* Support (add machine description for) TILE-Gx and TILEPro targets +* Support build for Android 64-bit (arm64, mips64, x86_64) +* Support FreeBSD/aarch64, FreeBSD/mips +* Support iOS7 64-bit (AArch64) and iOS8+ 32/64-bit (Darwin) +* Support MinGW build in scripts +* Turn off sigsetjmp workaround for Android/x86 starting from NDK r8e +* Use magic header on objects to improve disclaim_test +* Workaround 'sa_sigaction member missing' compiler error (Android/x32) +* Workaround 'unresolved __tls_get_addr' error for Android NDK Clang +* Workaround a bug in winpthreads causing parallel marks deadlock (MinGW) + +Also, includes 7.4.4 changes + + +== [7.4.14] 2018-08-11 == + +* Cleanup BCC Makefile (remove absolute GC paths, fix del cmd, update clean) +* Do not call GC_dirty_inner unless GC_incremental +* Eliminate 'cast between incompatible function types' compiler warning +* Eliminate 'comparing signed and unsigned values' compiler warnings (bcc) +* Eliminate 'language extension used' Clang warning in gc.h +* Eliminate 'possibly incorrect assignment in CORD_vsprintf' compiler warning +* Eliminate 'switch statement contains no case label' compiler warning +* Eliminate 'variable might be uninitialized' warning in win32_start_inner +* Eliminate duplicate clear_mark_bit call when removing disappearing link +* Fix 'collecting from unknown thread' abort in leak-finding mode +* Fix compilation by digimars.mak (DMC) and by WCC makefile +* Fix cords for MANUAL_VDB +* Fix dependency on gc_cpp source in BCC_MAKEFILE and NT_MAKEFILE +* Fix gctest in leak-finding mode +* Fix missing GC_dirty calls for GC-allocated objects used internally +* Fix missing GC_dirty invocation from debug_end_stubborn_change +* Fix multi-threaded gctest for the case of NTHREADS is set to zero +* Fix typos in ChangeLog and generic_malloc +* Keep pointer to the start of previous entry in remove_specific_after_fork +* New API function (GC_is_init_called) to check if BDWGC is initialized +* Remove code duplication in gcj_malloc and malloc_explicitly_typed +* Remove duplicate local variable in reclaim_block +* Remove libatomic_ops license information from README +* Workaround 'dynamic exception specifications deprecated in C++11' warning + +Also, includes 7.2l changes + + +== [7.4.12] 2018-04-19 == + +* Define GC_FREEBSD_THREADS and GC_ADD_CALLER macros for kFreeBSD +* Fix comment for debug_generic_malloc_inner[_ignore_off_page] +* Fix gctest with musl libc on s390x +* Fix missing new-line in ABORT_ARG definition +* Fix null pointer dereference in get_private_path_and_zero_file (Symbian) +* Fix type of local variables receiving result of PHT_HASH +* Remove API symbols renaming in WCC_MAKEFILE + +Also, includes 7.2k changes + + +== [7.4.10] 2018-01-22 == + +* Fix error code in abort message if sem_wait failed in start_world (NetBSD) +Also, includes 7.2j changes + + +== [7.4.8] 2017-12-22 == + +* Eliminate 'this statement may fall through' GCC warnings +* Eliminate 'value exceeds maximum object size' GCC warning in huge_test +* Fix data race in make_descriptor when setting explicit_typing_initialized +* Fix marking of disclaim-reachable objects in the incremental mode +* Update comment in finalized_disclaim to match FINALIZER_CLOSURE_FLAG +Also, includes 7.2i changes + + +== [7.4.6] 2017-10-26 == + +* Add configure --enable-gcov option (enable code coverage analysis) +* Add configure check whether to define NO_GETCONTEXT +* Adjust GC_memalign comment +* Allow HAVE_DL_ITERATE_PHDR to be defined by client (musl) +* Allow PKG_CHECK_MODULES in configure.ac to be commented out easily +* Avoid busy waiting in mark_thread while GC_parallel is false +* Better document minimum value of size argument for typed allocations +* Change type of THREAD_TABLE_INDEX result to int in win32_threads.c +* Consistently use 'msec' instead of 'ms' in comments in pthread_support +* Do not define amiga_get_mem, MacTemporaryNewPtr unless really used (extra) +* Do not produce .tar.bz2 distribution file (configure) +* Do not require libatomic_ops for single-threaded builds (configure) +* Do not warn of missing PT_GNU_RELRO segment when custom DSO filter used +* Document GWW_VDB in gcdescr.html +* Eliminate 'cast to void* from int' compiler warnings (Darwin/x64) +* Eliminate 'conditional expression is always true' code defect in GC_init +* Eliminate 'FP divide-by-zero' static analyzer warning +* Eliminate 'incompatible function pointer' warning in mark_some (MinGW/x86) +* Eliminate 'ISO C forbids an empty translation unit' GCC pedantic warning +* Eliminate 'ISO C forbids object to function pointer conversion' warning +* Eliminate 'locally defined symbol imported' MS linker warnings (cord) +* Eliminate 'null dereference' code defect warning in register_finalizer +* Eliminate 'possible loss of data' compiler warnings (MS VC) +* Eliminate 'printf format specifier mismatch' compiler warning (tools) +* Eliminate 'type defaults to int in declaration' warning (REDIRECT_MALLOC) +* Eliminate 'value stored is never read' warning of Clang static analyzer +* Eliminate duplicate log messages in GC_mark_from +* Eliminate most of collisions in GC_threads on Linux/x64 +* Ensure GC initialized when atfork_prepare is called by client +* Fix 'arg parameter might be clobbered by setjmp' compiler warning +* Fix 'bogus LR' detection in FindTopOfStack (Darwin) +* Fix 'execvp argument incompatible pointer type' compiler warning (tools) +* Fix 'GetVersion deprecated' compiler warning in os_dep (MS VC) +* Fix 'incompatible pointer' compiler warning in GC_init_dyld (OS X 64-bit) +* Fix 'incompatible ptr-to-int conversion' compiler warning in push_all_stack +* Fix 'ISO C90 does not support %lf, %lg gnu_printf formats' GCC warnings +* Fix 'ISO C90 forbids mixed declarations and code' compiler warning +* Fix 'missing libc-version.h' build error (uClibc/x86[_64]) +* Fix 'replacement operator delete cannot be inline' GCC warning (Cygwin) +* Fix 'variable unused' compiler warning in FirstDLOpenedLinkMap +* Fix 'zero-size array is extension' Clang warning in os_dep (Linux/x86) +* Fix (adjust) GC_scratch_alloc actual argument type +* Fix deadlock in GC_help_marker caused by use of mark_cv of parent process +* Fix finalize.c compilation in 'strict ANSI' mode +* Fix GC shared library tests failure related to dl_iterate_phdr (musl) +* Fix gc.h compliance to strict ANSI (pthreads) +* Fix GC_bytes_allocd incrementation in case of allocation failure +* Fix GC_jmp_buf multiple definition +* Fix GC_noop6 definition to avoid its calls to be optimized away +* Fix gctest failure if PARALLEL_MARK (musl) +* Fix gctest thread stack overflow (musl-gcc) +* Fix initsecondarythread_test runtime failure if GC compiled w/o threads +* Fix lack of 2 trailing zeros in _MSC_VER numbers +* Fix local variable declarations in disclaim_bench +* Fix missing #error pragma +* Fix missing .exe for disclaim test filenames in Makefile (MinGW) +* Fix missing atomic/[un]collectable/realloc_count increments in gctest +* Fix missing new-line and redundant trailing dot in WARN messages +* Fix missing new-line at format strings end in subthread_create test +* Fix mixed include of GC public header and gc_priv.h in disclaim bench/test +* Fix potential overflow in decrement when computing GC_markers_m1 +* Fix printf format specifiers in extra files (cppcheck warnings) +* Fix pthread_start compilation if single-obj-compilation (Linux) +* Fix register_finalizer call in disclaim_bench for GC_DEBUG +* Fix static assertion violation in LONG_MULT for 64-bit targets +* Fix tag collision between ENABLE_DISCLAIM and KEEP_BACK_PTRS +* Fix thread id leaks in subthread_create and threadkey_test +* Fix threaded tests runtime crash if GC_NO_THREAD_REDIRECTS supplied +* Fix tools/setjmp_t to prevent nested_sp inlining +* Fix typo in CHECK_GCLIB_VERSION name (test) +* Fix typos in comments/documentation (ews4800, extend_size_map, push_roots) +* Fix unchecked fork() result in gctest (Unix, Cygwin) +* Improve detection of internal libatomic_ops (configure) +* Move libraries version info to the beginning of Makefile.am +* Prevent abort in register_data_segments for Symbian +* Process all PT_LOAD segments before PT_GNU_RELRO segments (Glibc) +* Refine Makefile.direct comment about multi-threaded GC build +* Refine README about library source downloading +* Refine should_invoke_finalizers documentation +* Remove all generated files by NT_X64_THREADS_MAKEFILE 'clean' target +* Remove non-existent configure option in simple_example.html +* Replace C++ style comments to C ones, remove commented out code (extra) +* Support CFLAGS_EXTRA to pass extra user-defined compiler flags (configure) +* Support CFLAGS_EXTRA when checking for inline and dladdr (configure) +* Suppress 'tainted string passed to vulnerable operation' false defects +* Suppress MS VC warnings about unused param, const condition (NT_MAKEFILE) +* Update bdwgc mailing list online archive link in documentation +* Update shared libraries version info to differentiate against v7.2 +* Use AC_DEFINE for defining NO_GETCONTEXT in configure +* Workaround 'index out of bounds' UBSan false warning in push_marked +* Workaround 'mmap() resource handle leak' static analyzer warning +* Workaround 'redundant assignment of *result to itself' cppcheck warning +* Workaround 'resource leak' error reported by cppcheck (tools, test) +Also, includes 7.2h changes + + +== [7.4.4] 2016-05-25 == + +* Allow GC_FAST_MALLOC_GRANS() multiple use in a function +* Also enable the TSX workaround for i386 (Linux) +* Avoid unstructured procfs on Solaris +* Change cord/de main() declaration style from K-R to ANSI C +* Change no-argument functions declaration style to ANSI C (cord) +* Do not include sigcontext.h and asm/sigcontext.h +* Eliminate 'divide by zero' compiler warning in cordtest +* Eliminate warning about 64-bit pointer-to-int cast (Win64/pthreads-w32) +* Eliminate warnings detected by Cppcheck in cord de[_win] +* Fix 'comparison of non-null parameter is always false' warning (Clang) +* Fix 'CORD_iter5 unused result' code defect in cordxtra +* Fix 'GC_generic_malloc_inner_ignore_off_page not used' compiler warning +* Fix 'implicit declaration of vsnprintf' GCC warning (if strict ANSI mode) +* Fix 'signed-to-bigger-unsigned value assignment' in GC_init_size_map +* Fix 'signed-to-bigger-unsigned value assignment' warning for hb_map +* Fix 'signed-to-bigger-unsigned value assignment' warning in GC_setpagesize +* Fix 'statement unreachable' compiler warning in GC_mark_from +* Fix 'statement unreachable' compiler warning in memalign +* Fix 'unused label' compiler warning in cord/de +* Fix 'value truncated' compiler warning in CORD_cat (MS VC) +* Fix 'variable unused' warning in GC_save_callers +* Fix 'visibility attribute not supported' GCC warning (IBM AIX) +* Fix CMake warning about CMP0054 by unquoting instances of HOST +* Fix Cygwin64 build +* Fix GC_REALLOC to call GC_FREE if new size is zero and pointer is non-NULL +* Fix Makefile.direct for Cygwin +* Fix __alloc_size__ availability detection (Clang) +* Fix abort message in GC_move_long_link +* Fix and code refactoring of lock elision workaround (Linux/x64) +* Fix assertion on mark_lock_holder for non-unique NUMERIC_THREAD_ID +* Fix data race in GC_init_explicit_typing +* Fix gc.mak regarding msvc_dbg and test (MSVC) +* Fix missing error handling of pthread_attr_init/getstacksize +* Fix missing error handling of pthreads_mutex_init and cond_wait +* Fix missing numeric casts in cord +* Fix potential left shift overflows in finalize.c (64-bit targets) +* Fix pthreads-win32 name in comments and documentation +* Fix setup_mark_lock missing prototype +* Fix unchecked fcntl() result +* Fix unchecked pointer dereference in check_ints (gctest) +* Fix unchecked pthread_join() result in threadkey_test +* Fix unchecked sigdelset() result in pthread_support +* Fix undefined PTRFREE/NORMAL in gc_inline.h +* Prefix PREFETCH_FOR_WRITE with GC_ as used in gc_inline.h public header +* Relax mark_mutex attribute needed to disable elision (Linux/x64) +* Remove (deprecate) TODO file +* Remove code duplication in GC_realloc +* Remove duplicate new-line in OUT_OF_MEMORY message (cord) +* Remove references to missing linux_threads.c from documentation +* Revert "Move asm machine-dependent files to 'src' folder" (partly) +* Support Android API level 21 +* Update compiler options in gc.mak (Win32) +* Use mmap instead of sbrk (Hurd) +* Workaround 'comparison is always false' GCC warning in GC_FAST_MALLOC_GRANS +* Workaround 'identical expr on both sides of bitwise op' warning +* Workaround Linux NTPL lock elision bug +* Workaround false warning about unreachable code path +* Workaround invalid '_end' symbol on Android clang 3.5+ +Also, includes 7.2g changes == [7.4.2] 2014-06-03 == -* Add config option to use STGRTMIN-based signals for thread suspend/resume. -* Allow parallel mark to be enabled on powerpc-linux systems. -* Check for Fujitsu compiler in builtin_unwind logic (enable FX10/K-Computer). -* Fix 'Array subscript is above array bounds' GCC warning in GC_new_kind/proc. -* Fix 'attribute declaration must precede definition' warning (clang-3.1). -* Fix (enable) Cygwin-64 build. -* Fix GC_finalized_malloc failure on disclaim_test. -* Fix GC_sig_suspend initialization when non-constant SIGRTMIN used. -* Fix MS VC redefinition warning for functions declared with GC_ATTR_MALLOC. -* Fix TEXT() usage for concatenated strings in GC_CreateLogFile (Win32). -* Fix data roots registration for Android/x86 and NDK ARM 'gold' linker. -* Fix find stackbottom on BlueGene P/Q systems. -* Fix machdep .lo files path in configure (SPARC, IA-64). -* Fix ok_init assignment (missing cast) in GC_new_kind_inner. -* Fix typos in names in AUTHORS and ChangeLog files. -* Remove barrett_diagram file duplicated by tree.html. -* Remove non-existing DISCARD_WORDS from GC data structure ASCII diagram. -* Restore contribution information for ancient releases in ChangeLog. -Also, includes 7.2f changes. +* Add config option to use STGRTMIN-based signals for thread suspend/resume +* Allow parallel mark to be enabled on powerpc-linux systems +* Check for Fujitsu compiler in builtin_unwind logic (enable FX10/K-Computer) +* Fix 'Array subscript is above array bounds' GCC warning in GC_new_kind/proc +* Fix 'attribute declaration must precede definition' warning (clang-3.1) +* Fix (enable) Cygwin-64 build +* Fix GC_finalized_malloc failure on disclaim_test +* Fix GC_sig_suspend initialization when non-constant SIGRTMIN used +* Fix MS VC redefinition warning for functions declared with GC_ATTR_MALLOC +* Fix TEXT() usage for concatenated strings in GC_CreateLogFile (Win32) +* Fix data roots registration for Android/x86 and NDK ARM 'gold' linker +* Fix find stackbottom on BlueGene P/Q systems +* Fix machdep .lo files path in configure (SPARC, IA-64) +* Fix ok_init assignment (missing cast) in GC_new_kind_inner +* Fix typos in names in AUTHORS and ChangeLog files +* Remove barrett_diagram file duplicated by tree.html +* Remove non-existing DISCARD_WORDS from GC data structure ASCII diagram +* Restore contribution information for ancient releases in ChangeLog +Also, includes 7.2f changes == [7.4.0] 2013-11-17 == -* Add 'bytes reclaimed' counters to public GC_prof_stats_s. -* Add AArch64 (64-bit ARM) target support. -* Add GC_LONG_REFS_NOT_NEEDED ifdefs to exclude long link functionality. -* Add GC_get_prof_stats[_unsafe]() to GC public API. -* Add GC_push_all/conditional() to GC public API. -* Add assertion on number_of_objs to GC_extend_size_map. -* Add assertion to GC_enable() ensuring no counter underflow. -* Add assertion to LOCK definition that lock is not already held. -* Add assertion to LONG_MULT and remove useless assert in PUSH_CONTENTS_HDR. -* Add double-lock assertion to GC_acquire_mark_lock. -* Add manual POSIX fork handling support (Android). -* Add note about 'pkg-config' solving problem with autoconf 2.68 or older. -* Add public GC_set/get_abort_func to replace default GC_on_abort. -* Add public GC_start_mark_threads() to allow parallel marker in fork child. -* Add public setter and getter for GC_push_other_roots. -* Add support of Android logger. -* Add tests for GC_register/move/unregister_long_link. -* Add thread suspend/resume signals public setters (POSIX threads). -* Added long weakref support. -* Adjust GC_dont_expand/gc/precollect and GC_print_stats type to match gc.h. -* Adjust README.md title and references to doc .html files in it. -* Adjust build scripts to enable additional test library in staticrootstest. -* Adjust logged messages in start_mark_threads and GC_thr_init. -* Adjust printf format specifiers in GC_print_trace. -* Allow not to rely on __data_start value (Linux). -* Allow pthread_kill error code logging in GC_suspend/resume (debugging). -* Allow to compile GC_inner_start_routine aside from extra/gc.c. -* Allow to omit libc atexit() call. -* Avoid LOCK/UNLOCK hard-coding in gc_locks.h for PS3 target. -* Better document GC_warn_proc in gc.h. -* Call GC_on_abort (with NULL argument) on exit(1). -* Call GC_stats/verbose_log_printf instead of GC_log_printf if print_stats. -* Change policy regarding version numbers ("micro" part instead of "alpha"). -* Changed C99-style designated init of GC_dl_hashtbl struct to use C89-style. -* Check GC_base result in GC_print_all_smashed_proc. -* Check that SIG_SUSPEND and SIG_THR_RESTART are different (Pthreads). -* Check traceable_allocator.allocate result before dereference in test_cpp. -* Code refactoring of GC_x_printf (move shared code to macro). -* Convert readme to markdown. -* Default to use libc_stack_end in single-threaded GC on glibc targets. -* Define GC_VSNPRINTF internal macro in misc.c (code refactoring). -* Define functions in darwin_semaphore.h as inline instead of static. -* Define old_bus_handler static variable only if used (Unix). -* Detect dladdr() presence by configure. -* Disable find-leak GC_gcollect on GC abnormal EXIT. -* Do not define _setjmp/_longjmp macros in mach_dep.c. -* Do not duplicate android_log_write output to GC log file (Android). -* Do not include sigcontext.h if NO_SIGCONTEXT_H (Linux). -* Do not set GC_lock_holder by call_with_alloc_lock if assertions disabled. -* Do not use pthread_getattr_np if NO_PTHREAD_GETATTR_NP specified. -* Elaborate comment on dependencies in autogen.sh. -* Eliminate 'cast from int to pointer' warning in GC_exclude_static_roots. -* Eliminate 'missing exception specification' warning in gc_cpp.cc (Clang). -* Eliminate 'uninitialized variable use' warning in test_printf (cord). -* Eliminate 'unused result' compiler warning in main() of test_cpp. -* Eliminate 'unused value' compiler warning in GC_stop_world (Pthreads). -* Eliminate 'unused variable' compiler warning in start_mark_threads (HP/UX). -* Eliminate Clang warning for GC_pthread_exit attribute. -* Eliminate GCC warning about uninitialized 'hhdr' in GC_allochblk_nth. -* Eliminate GCC warning in GC_get_main_stack_base (OpenBSD). -* Eliminate GCC warnings in setjmp_t.c, test_cpp and cord 'de' app. -* Eliminate GC_first_nonempty atomic value reload in GC_mark_local assertion. -* Eliminate SIGBUS-related dead code in GC_write_fault_handler (Linux). -* Eliminate warning and simplify expression in GC_init_explicit_typing. -* Enable 'force GC at every GC_malloc' debug-related functionality. -* Enable on-demand debug logging in GC_FindTopOfStack (Darwin). -* Enable prefetch operations by default (GCC 3.0+). -* Enable staticrootstest for the case of GC shared library build. -* Enable thread-local allocation support for Clang on Cygwin. -* Explicitly specify that Darwin, Linux and Solaris platforms have dladdr. -* Fix ABORT definition for mingw32ce (WinCE). -* Fix AM_CONFIG_HEADER in configure for autoconf-2.69-1. -* Fix GC_CreateThread and GC_beginthreadex definition for Cygwin. -* Fix GC_INIT_CONF_ROOTS in gc.h for Android. -* Fix GC_INLINE definition to comply with ISO C90 standard (GCC). -* Fix GC_remove_all_threads_but_me for Android (fork support). -* Fix debug_register_displacement calls from GC_debug_generic_malloc_inner. -* Fix dyn_load.c compilation for Android 4.3. -* Fix make disclaim_test to link with new GNU ld linking rules. -* Improve GC error printing atomicity in GC_debug_X and GC_print_obj. -* Improve GC output atomicity in GC_print_obj, GC_print_all_errors. -* Improve debug-only messages of add/remove_roots and init_linux_data_start. -* Improve fork test logging in gctest. -* Improve logged messages about heap size and usage. -* Improve logging for Android differentiating messages by log level. -* Improve staticrootstest (add global data to library, add lib w/o GC_INIT). -* Improve staticrootstest checks (tests). -* Include "config.h" instead of "private/config.h" on HAVE_CONFIG_H. -* Include proper header file in 'tools' for configuration macros. -* Include pthread_np.h from pthread_stop_world.c on OpenBSD. -* Log error messages to stderr instead of stdout in tests. -* Make GC_generic_malloc_ignore_off_page() public. -* Make GC_mark_lock_holder variable static. -* Make GC_print_trace always thread-safe and remove 'lock' argument. -* Mark GC_started_thread_while_stopped() as GC_INNER. -* Minimize code duplication in GC_mark_and_push. -* Move 'include setjmp.h' from mach_dep.c to gc_priv.h. -* Move GC_OPENBSD_UTHREADS definition to private/gcconfig.h (OpenBSD). -* Move GC_get_suspend/thr_restart_signal to misc.c for NaCl and OpenBSD. -* Move LOCK/UNLOCK from GC_unregister_disappearing_link_inner outer. -* Port BDWGC to Android/x86. -* Postpone the suspend signal in GC_dirty_init only if used to stop world. -* Prepend '#' symbol to GC number in logged messages. -* Prevent POSIX fork if mprotect_thread is started (Darwin). -* Prevent abort on GC_err/warn_printf write failure. -* Prevent misleading AC_MSG_ERROR/AS_IF errors reported in configure.ac. -* Put gc_cpp symbols into 'boehmgc' namespace if GC_NAMESPACE defined. -* Recognize GC_DONT_GC macro in gc.h (causes GC_INIT to turn off GC). -* Recognize GC_SIG_SUSPEND and GC_SIG_THR_RESTART tuning macros in gc.h. -* Redirect WRITE to __android_log_write if GC_ANDROID_LOG (Android). -* Refine comment of GC_is_heap_ptr and GC_thread_is_registered in gc.h. -* Register dynamic libraries via dl_iterate_phdr on Android and OpenBSD. -* Remove DebugBreak on WriteFile failure (Win32). -* Remove GC_BUILD definition from build scripts. -* Remove abort on open log failure from GC_write (Win32). -* Remove configure.ac outdated revision number. -* Remove nested EXPECT in GC_core_finalized_malloc. -* Remove nested always-false ifdef for HPUX and FREEBSD. -* Remove redundant GC_err_printf before abort. -* Remove unused UTHREAD_SP_OFFSET macro (OpenBSD). -* Rename subthread_create to subthreadcreate_test (Makefile). -* Replace GC_COND_LOG_PRINTF calls with WARN for allocation failure messages. -* Replace GC_log/err_printf() followed by ABORT with ABORT_ARGn(). -* Replace GC_stats_log_printf with GC_DBG/INFOLOG_PRINTF. -* Replace SIG_SUSPEND/THR_RESTART macros to variables in pthread_stop_world. -* Replace Win32 GC_delete_gc_thread with GC_delete_gc_thread_no_free. -* Replace conditional GC_log_printf calls with GC_COND/VERBOSE_LOG_PRINTF. -* Replace sprintf with defensive snprintf. -* Replace var-args GC_noop with GC_noop6 (to eliminate Clang warning). -* Simplify LOCK/UNLOCK macro definition for static code analysis tools. -* Specify GC_malloc result is unused in some tests. -* Specify GC_pthread_join result is unused in threadkey_test. -* Specify LT_INIT in configure.ac. -* Start of port to QNX. -* Support rthreads introduced in OpenBSD 5.2+. -* Suppress 'GC_dont_gc deprecated' warning in gc.h if GC_DONT_GC. -* Tag GC malloc routines with alloc_size attribute for Clang 3.2+. -* Test NO_WRAP_MARK_SOME macro to suppress WRAP_MARK_SOME-specific code. -* Turn off GC_LOOP_ON_ABORT functionality if GC compiled with NO_DEBUGGING. -* Turn on world-stop delay logging at debug level by default for Android. -* Use EXPECT in GC_COND/VERBOSE_LOG_PRINTF. -* Use GC_log_printf for logging instead of GC_[err_]printf. -* Use compiler TLS for Android NDK gcc/arm. -* Use memcpy (BCOPY) instead of strcpy (to suppress GCC warning). -* Use pthread API to operate thread-local data on Linux if no compiler TLS. -* Workaround 'ELF_DATA/EM_ALPHA redefined' warning in Android linker.h. -* Workaround 'unresolved __tls_get_addr' error for Android NDK Clang. -Also, includes 7.2e, 7.2d, 7.2c, 7.2b changes. +* Add 'bytes reclaimed' counters to public GC_prof_stats_s +* Add AArch64 (64-bit ARM) target support +* Add GC_LONG_REFS_NOT_NEEDED ifdefs to exclude long link functionality +* Add GC_get_prof_stats[_unsafe]() to GC public API +* Add GC_push_all/conditional() to GC public API +* Add assertion on number_of_objs to GC_extend_size_map +* Add assertion to GC_enable() ensuring no counter underflow +* Add assertion to LOCK definition that lock is not already held +* Add assertion to LONG_MULT and remove useless assert in PUSH_CONTENTS_HDR +* Add double-lock assertion to GC_acquire_mark_lock +* Add manual POSIX fork handling support (Android) +* Add note about 'pkg-config' solving problem with autoconf 2.68 or older +* Add public GC_set/get_abort_func to replace default GC_on_abort +* Add public GC_start_mark_threads() to allow parallel marker in fork child +* Add public setter and getter for GC_push_other_roots +* Add support of Android logger +* Add tests for GC_register/move/unregister_long_link +* Add thread suspend/resume signals public setters (POSIX threads) +* Added long weakref support +* Adjust GC_dont_expand/gc/precollect and GC_print_stats type to match gc.h +* Adjust README.md title and references to doc .html files in it +* Adjust build scripts to enable additional test library in staticrootstest +* Adjust logged messages in start_mark_threads and GC_thr_init +* Adjust printf format specifiers in GC_print_trace +* Allow not to rely on __data_start value (Linux) +* Allow pthread_kill error code logging in GC_suspend/resume (debugging) +* Allow to compile GC_inner_start_routine aside from extra/gc.c +* Allow to omit libc atexit() call +* Avoid LOCK/UNLOCK hard-coding in gc_locks.h for PS3 target +* Better document GC_warn_proc in gc.h +* Call GC_on_abort (with NULL argument) on exit(1) +* Call GC_stats/verbose_log_printf instead of GC_log_printf if print_stats +* Change policy regarding version numbers ("micro" part instead of "alpha") +* Changed C99-style designated init of GC_dl_hashtbl struct to use C89-style +* Check GC_base result in GC_print_all_smashed_proc +* Check that SIG_SUSPEND and SIG_THR_RESTART are different (Pthreads) +* Check traceable_allocator.allocate result before dereference in test_cpp +* Code refactoring of GC_x_printf (move shared code to macro) +* Convert readme to markdown +* Default to use libc_stack_end in single-threaded GC on glibc targets +* Define GC_VSNPRINTF internal macro in misc.c (code refactoring) +* Define functions in darwin_semaphore.h as inline instead of static +* Define old_bus_handler static variable only if used (Unix) +* Detect dladdr() presence by configure +* Disable find-leak GC_gcollect on GC abnormal EXIT +* Do not define _setjmp/_longjmp macros in mach_dep.c +* Do not duplicate android_log_write output to GC log file (Android) +* Do not include sigcontext.h if NO_SIGCONTEXT_H (Linux) +* Do not set GC_lock_holder by call_with_alloc_lock if assertions disabled +* Do not use pthread_getattr_np if NO_PTHREAD_GETATTR_NP specified +* Elaborate comment on dependencies in autogen.sh +* Eliminate 'cast from int to pointer' warning in GC_exclude_static_roots +* Eliminate 'missing exception specification' warning in gc_cpp.cc (Clang) +* Eliminate 'uninitialized variable use' warning in test_printf (cord) +* Eliminate 'unused result' compiler warning in main() of test_cpp +* Eliminate 'unused value' compiler warning in GC_stop_world (Pthreads) +* Eliminate 'unused variable' compiler warning in start_mark_threads (HP/UX) +* Eliminate Clang warning for GC_pthread_exit attribute +* Eliminate GCC warning about uninitialized 'hhdr' in GC_allochblk_nth +* Eliminate GCC warning in GC_get_main_stack_base (OpenBSD) +* Eliminate GCC warnings in setjmp_t.c, test_cpp and cord 'de' app +* Eliminate GC_first_nonempty atomic value reload in GC_mark_local assertion +* Eliminate SIGBUS-related dead code in GC_write_fault_handler (Linux) +* Eliminate warning and simplify expression in GC_init_explicit_typing +* Enable 'force GC at every GC_malloc' debug-related functionality +* Enable on-demand debug logging in GC_FindTopOfStack (Darwin) +* Enable prefetch operations by default (GCC 3.0+) +* Enable staticrootstest for the case of GC shared library build +* Enable thread-local allocation support for Clang on Cygwin +* Explicitly specify that Darwin, Linux and Solaris platforms have dladdr +* Fix ABORT definition for mingw32ce (WinCE) +* Fix AM_CONFIG_HEADER in configure for autoconf-2.69-1 +* Fix GC_CreateThread and GC_beginthreadex definition for Cygwin +* Fix GC_INIT_CONF_ROOTS in gc.h for Android +* Fix GC_INLINE definition to comply with ISO C90 standard (GCC) +* Fix GC_remove_all_threads_but_me for Android (fork support) +* Fix debug_register_displacement calls from GC_debug_generic_malloc_inner +* Fix dyn_load.c compilation for Android 4.3 +* Fix make disclaim_test to link with new GNU ld linking rules +* Improve GC error printing atomicity in GC_debug_X and GC_print_obj +* Improve GC output atomicity in GC_print_obj, GC_print_all_errors +* Improve debug-only messages of add/remove_roots and init_linux_data_start +* Improve fork test logging in gctest +* Improve logged messages about heap size and usage +* Improve logging for Android differentiating messages by log level +* Improve staticrootstest (add global data to library, add lib w/o GC_INIT) +* Improve staticrootstest checks (tests) +* Include "config.h" instead of "private/config.h" on HAVE_CONFIG_H +* Include proper header file in 'tools' for configuration macros +* Include pthread_np.h from pthread_stop_world.c on OpenBSD +* Log error messages to stderr instead of stdout in tests +* Make GC_generic_malloc_ignore_off_page() public +* Make GC_mark_lock_holder variable static +* Make GC_print_trace always thread-safe and remove 'lock' argument +* Mark GC_started_thread_while_stopped() as GC_INNER +* Minimize code duplication in GC_mark_and_push +* Move 'include setjmp.h' from mach_dep.c to gc_priv.h +* Move GC_OPENBSD_UTHREADS definition to private/gcconfig.h (OpenBSD) +* Move GC_get_suspend/thr_restart_signal to misc.c for NaCl and OpenBSD +* Move LOCK/UNLOCK from GC_unregister_disappearing_link_inner outer +* Port BDWGC to Android/x86 +* Postpone the suspend signal in GC_dirty_init only if used to stop world +* Prepend '#' symbol to GC number in logged messages +* Prevent POSIX fork if mprotect_thread is started (Darwin) +* Prevent abort on GC_err/warn_printf write failure +* Prevent misleading AC_MSG_ERROR/AS_IF errors reported in configure.ac +* Put gc_cpp symbols into 'boehmgc' namespace if GC_NAMESPACE defined +* Recognize GC_DONT_GC macro in gc.h (causes GC_INIT to turn off GC) +* Recognize GC_SIG_SUSPEND and GC_SIG_THR_RESTART tuning macros in gc.h +* Redirect WRITE to __android_log_write if GC_ANDROID_LOG (Android) +* Refine comment of GC_is_heap_ptr and GC_thread_is_registered in gc.h +* Register dynamic libraries via dl_iterate_phdr on Android and OpenBSD +* Remove DebugBreak on WriteFile failure (Win32) +* Remove GC_BUILD definition from build scripts +* Remove abort on open log failure from GC_write (Win32) +* Remove configure.ac outdated revision number +* Remove nested EXPECT in GC_core_finalized_malloc +* Remove nested always-false ifdef for HPUX and FREEBSD +* Remove redundant GC_err_printf before abort +* Remove unused UTHREAD_SP_OFFSET macro (OpenBSD) +* Rename subthread_create to subthreadcreate_test (Makefile) +* Replace GC_COND_LOG_PRINTF calls with WARN for allocation failure messages +* Replace GC_log/err_printf() followed by ABORT with ABORT_ARGn() +* Replace GC_stats_log_printf with GC_DBG/INFOLOG_PRINTF +* Replace SIG_SUSPEND/THR_RESTART macros to variables in pthread_stop_world +* Replace Win32 GC_delete_gc_thread with GC_delete_gc_thread_no_free +* Replace conditional GC_log_printf calls with GC_COND/VERBOSE_LOG_PRINTF +* Replace sprintf with defensive snprintf +* Replace var-args GC_noop with GC_noop6 (to eliminate Clang warning) +* Simplify LOCK/UNLOCK macro definition for static code analysis tools +* Specify GC_malloc result is unused in some tests +* Specify GC_pthread_join result is unused in threadkey_test +* Specify LT_INIT in configure.ac +* Start of port to QNX +* Support rthreads introduced in OpenBSD 5.2+ +* Suppress 'GC_dont_gc deprecated' warning in gc.h if GC_DONT_GC +* Tag GC malloc routines with alloc_size attribute for Clang 3.2+ +* Test NO_WRAP_MARK_SOME macro to suppress WRAP_MARK_SOME-specific code +* Turn off GC_LOOP_ON_ABORT functionality if GC compiled with NO_DEBUGGING +* Turn on world-stop delay logging at debug level by default for Android +* Use EXPECT in GC_COND/VERBOSE_LOG_PRINTF +* Use GC_log_printf for logging instead of GC_[err_]printf +* Use compiler TLS for Android NDK gcc/arm +* Use memcpy (BCOPY) instead of strcpy (to suppress GCC warning) +* Use pthread API to operate thread-local data on Linux if no compiler TLS +* Workaround 'ELF_DATA/EM_ALPHA redefined' warning in Android linker.h +* Workaround 'unresolved __tls_get_addr' error for Android NDK Clang +Also, includes 7.2e, 7.2d, 7.2c, 7.2b changes == [7.3alpha2] 2012-05-11 == -* Add 'const' qualifier to pointer argument of some API functions. -* Add GC_UNDERSCORE_STDCALL, UNICODE macro templates to configure (Win32). -* Add GC_get_thr_restart_signal, GC_thread_is_registered to GC API. -* Add GC_is_heap_ptr, GC_move_disappearing_link to GC API. -* Add SHORT_DBG_HDRS macro template to configure. -* Add Symbian port to mainline (porting done by Djamel Magri). -* Add TODO file. -* Add assertion ensuring proper alignment of 'pushed' GC symbols. -* Add assertion in GC_getspecific on qtid. -* Add assertion to GC_incremental_protection_needs, refine documentation. -* Add assertion to check GC_large_free_bytes by GC_finish_collection. -* Add configure option to compile all library .c files into single gc.o. -* Add cordtest to make check. -* Add disclaim callbacks for efficient finalization (ENABLE_DISCLAIM). -* Add finalization.html to 'doc' folder. -* Add javaxfc.h to the installation set of GC header files (configure). -* Add on-heap-resize event notification to API. -* Adjust GC_log_printf format specifiers (regarding signed/unsigned long). -* Adjust GC_requested_heapsize on GC_init if GC_INITIAL_HEAP_SIZE given. -* Allow GC_exclude_static_roots() region start to be unaligned. -* Allow Win32 DllMain chaining on the client side. -* Allow to exclude finalization support by GC_NO_FINALIZATION macro. -* Allow to get memory via Win32 VirtualAlloc (USE_WINALLOC) on Cygwin. -* Avoid unnecessary GC_find_limit invocation if GC_no_dls. -* Avoid use of deprecated GC_dont_gc and GC_stackbottom in gctest. -* Cast pointers to word (instead of unsigned long) in specific.h. -* Changed the order in autogen.sh so ltmain exists in time for automake. -* Declare privately and use handy GC_base_C() for constant object pointers. -* Define GC_DLL if DLL_EXPORT at GC build (for Cygwin/MinGW). -* Define GC_READ_ENV_FILE in configure for WinCE unless gc-debug is off. -* Do not compile backgraph.c unless configure '--enable-gc-debug'. -* Do not compile pthread_stop_world.c for Cygwin/Darwin (configure). -* Do not install ancient new_gc_alloc.h broken for modern STL (configure). -* Enable GC_MIN_MARKERS to set minimal number of pthread-based markers. -* Enable PARALLEL_MARK and THREAD_LOCAL_ALLOC for FreeBSD in configure. -* Enable parallel mark by default in configure (Darwin/Linux/Solaris/Win32). -* Export GC_is_marked, GC_clear/set_mark_bit (for mark-bit manipulation). -* Extend thread-related debug messages. -* Fix 'configure --enable-cplusplus' for Cygwin/MinGW. -* Fix DATASTART (and other minor improvements) for NaCl target. -* Fix GC_setspecific to prevent garbage collection inside. -* Fix compiler warning in cordtest. -* Fix minor warnings reported by GCC with '-pedantic' option. -* Fix static data roots registration on Android (if GC is shared). -* Implement GC_get_stack_base for Darwin for single-threaded mode. -* Improve GC_allochblk algorithm of block splitting when unmapping enabled. -* Improve GC_collect_or_expand algorithm for many finalizers registered case. -* In tests, print a message in case a test is a no-op. -* Instruct configure to hide internal libgc.so symbols if supported by GCC. -* Log amount of unmapped memory (if enabled) on marking-for-collection. -* Make __data_start a weak symbol to allow loading modules on mips. -* Move "cord" library tests to "cord/tests" folder. -* Move asm machine-dependent files to "src" folder. -* Move build tools sources to "tools" folder. -* Move cord_pos.h to public headers folder. -* Open log file in APPEND mode on Win32 (similar that on Unix/Cygwin). -* Optimize some functions by moving pthread_self calls out of LOCK section. -* Place only major per-release changes description to ChangeLog (this file). -* Prevent compiler warnings in GC_FindTopOfStack and GC_ports (Darwin). -* Recognize GC_LOG_TO_FILE_ALWAYS macro to log to 'gc.log' by default. -* Remove all auto-generated files from the repo. -* Remove binary icon file for de_win. -* Remove cordtest from "cord" library. -* Remove duplicate MacOS_Test_config.h file. -* Remove gc_amiga_redirects.h (included internally) from public headers. -* Remove obsolete Makefile.DLL (superseded by Cygwin/MinGW configure). -* Remove obsolete unused asm files for ALPHA, HPUX, SGI, RS6000, ULTRIX. -* Remove unsupported MMAP_STACKS (specific to Solaris threads). -* Remove unused ancient SILENT, __STDC__, NO_SIGNALS macros. -* Replace ARGSUSED comment-based annotation with GCC 'unused' attribute. -* Replace GC_ms_entry declaration with opaque definition for public API. -* Replace long GC_markers global variable with int GC_markers_m1. -* Replace pointer relational comparisons with non-pointer ones. -* Replace printf PRIxMAX specifier with '%p' for thread id debug output. -* Require autoconf 2.61 instead of v2.64. -* Simplify autogen.sh (use autoreconf). -* Split GC_abort with GC_on_abort and abort() invoked from ABORT. -* Support GC_ATTR_MALLOC for MS VisualStudio. -* Tag auxiliary malloc-like API functions with 'malloc' attribute. -* Tag deprecated variables in GC API. -* Tag must-be-non-null arguments of GC API functions. -* Turn on "extra" GCC warnings. -* Turn on unused-parameter checking for GCC. -* Update AUTHORS file. -* Use EXPECT for checking various 'initialized' boolean variables. -* Use USE_COMPILER_TLS on Cygwin. -* Use pthread_key for thread-local storage on FreeBSD. -* Use union of AO_t and word to favor strict-aliasing compiler optimization. -Also, includes 7.2 changes. +* Add 'const' qualifier to pointer argument of some API functions +* Add GC_UNDERSCORE_STDCALL, UNICODE macro templates to configure (Win32) +* Add GC_get_thr_restart_signal, GC_thread_is_registered to GC API +* Add GC_is_heap_ptr, GC_move_disappearing_link to GC API +* Add SHORT_DBG_HDRS macro template to configure +* Add Symbian port to mainline (porting done by Djamel Magri) +* Add TODO file +* Add assertion ensuring proper alignment of 'pushed' GC symbols +* Add assertion in GC_getspecific on qtid +* Add assertion to GC_incremental_protection_needs, refine documentation +* Add assertion to check GC_large_free_bytes by GC_finish_collection +* Add configure option to compile all library .c files into single gc.o +* Add cordtest to make check +* Add disclaim callbacks for efficient finalization (ENABLE_DISCLAIM) +* Add finalization.html to 'doc' folder +* Add javaxfc.h to the installation set of GC header files (configure) +* Add on-heap-resize event notification to API +* Adjust GC_log_printf format specifiers (regarding signed/unsigned long) +* Adjust GC_requested_heapsize on GC_init if GC_INITIAL_HEAP_SIZE given +* Allow GC_exclude_static_roots() region start to be unaligned +* Allow Win32 DllMain chaining on the client side +* Allow to exclude finalization support by GC_NO_FINALIZATION macro +* Allow to get memory via Win32 VirtualAlloc (USE_WINALLOC) on Cygwin +* Avoid unnecessary GC_find_limit invocation if GC_no_dls +* Avoid use of deprecated GC_dont_gc and GC_stackbottom in gctest +* Cast pointers to word (instead of unsigned long) in specific.h +* Changed the order in autogen.sh so ltmain exists in time for automake +* Declare privately and use handy GC_base_C() for constant object pointers +* Define GC_DLL if DLL_EXPORT at GC build (for Cygwin/MinGW) +* Define GC_READ_ENV_FILE in configure for WinCE unless gc-debug is off +* Do not compile backgraph.c unless configure '--enable-gc-debug' +* Do not compile pthread_stop_world.c for Cygwin/Darwin (configure) +* Do not install ancient new_gc_alloc.h broken for modern STL (configure) +* Enable GC_MIN_MARKERS to set minimal number of pthread-based markers +* Enable PARALLEL_MARK and THREAD_LOCAL_ALLOC for FreeBSD in configure +* Enable parallel mark by default in configure (Darwin/Linux/Solaris/Win32) +* Export GC_is_marked, GC_clear/set_mark_bit (for mark-bit manipulation) +* Extend thread-related debug messages +* Fix 'configure --enable-cplusplus' for Cygwin/MinGW +* Fix DATASTART (and other minor improvements) for NaCl target +* Fix GC_setspecific to prevent garbage collection inside +* Fix compiler warning in cordtest +* Fix minor warnings reported by GCC with '-pedantic' option +* Fix static data roots registration on Android (if GC is shared) +* Implement GC_get_stack_base for Darwin for single-threaded mode +* Improve GC_allochblk algorithm of block splitting when unmapping enabled +* Improve GC_collect_or_expand algorithm for many finalizers registered case +* In tests, print a message in case a test is a no-op +* Instruct configure to hide internal libgc.so symbols if supported by GCC +* Log amount of unmapped memory (if enabled) on marking-for-collection +* Make __data_start a weak symbol to allow loading modules on mips +* Move "cord" library tests to "cord/tests" folder +* Move asm machine-dependent files to "src" folder +* Move build tools sources to "tools" folder +* Move cord_pos.h to public headers folder +* Open log file in APPEND mode on Win32 (similar that on Unix/Cygwin) +* Optimize some functions by moving pthread_self calls out of LOCK section +* Place only major per-release changes description to ChangeLog (this file) +* Prevent compiler warnings in GC_FindTopOfStack and GC_ports (Darwin) +* Recognize GC_LOG_TO_FILE_ALWAYS macro to log to 'gc.log' by default +* Remove all auto-generated files from the repo +* Remove binary icon file for de_win +* Remove cordtest from "cord" library +* Remove duplicate MacOS_Test_config.h file +* Remove gc_amiga_redirects.h (included internally) from public headers +* Remove obsolete Makefile.DLL (superseded by Cygwin/MinGW configure) +* Remove obsolete unused asm files for ALPHA, HPUX, SGI, RS6000, ULTRIX +* Remove unsupported MMAP_STACKS (specific to Solaris threads) +* Remove unused ancient SILENT, __STDC__, NO_SIGNALS macros +* Replace ARGSUSED comment-based annotation with GCC 'unused' attribute +* Replace GC_ms_entry declaration with opaque definition for public API +* Replace long GC_markers global variable with int GC_markers_m1 +* Replace pointer relational comparisons with non-pointer ones +* Replace printf PRIxMAX specifier with '%p' for thread id debug output +* Require autoconf 2.61 instead of v2.64 +* Simplify autogen.sh (use autoreconf) +* Split GC_abort with GC_on_abort and abort() invoked from ABORT +* Support GC_ATTR_MALLOC for MS VisualStudio +* Tag auxiliary malloc-like API functions with 'malloc' attribute +* Tag deprecated variables in GC API +* Tag must-be-non-null arguments of GC API functions +* Turn on "extra" GCC warnings +* Turn on unused-parameter checking for GCC +* Update AUTHORS file +* Use EXPECT for checking various 'initialized' boolean variables +* Use USE_COMPILER_TLS on Cygwin +* Use pthread_key for thread-local storage on FreeBSD +* Use union of AO_t and word to favor strict-aliasing compiler optimization +Also, includes 7.2 changes + + +== [7.2l] 2018-08-10 == + +* Fix 'pointer arithmetic with NULL' code defect in print_callers +* Fix Borland version in documentation to match that in BCC_MAKEFILE +* Fix comment about inv_sz computation in setup_header +* Fix comments style in configure.ac and Makefile.am +* Fix GC_is_valid_displacement and GC_is_visible for non-small objects +* Fix global operator delete definition for C++14 in gc_cpp +* Fix infinite restarting of mark_some when a static root disappeared (Linux) +* Fix large object base computation in PUSH_CONTENTS() if MARK_BIT_PER_OBJ +* Fix mark stack overflow checking in push_selected +* Fix MSWIN32 macro redefinition (WCC) +* Fix potential null dereference in GC_CONS +* Fix register_dynamic_libraries on Windows 10 +* Fix result computation in n_set_marks +* Fix return type in GC_set_warn_proc API documentation +* Fix typo in comment for CORD_ec_flush_buf prototype +* Fix typos in ChangeLog +* Fix VirtualQuery call in case of malloc failure (Win32) +* Install gc.3 man page instead of copying gc.man to doc folder (configure) +* Perform thread_suspend in loop as it may be interrupted (Darwin) +* Workaround 'template-id not supported in this context' compiler error (WCC) + + +== [7.2k] 2018-04-19 == + +* Fix arguments delimiter in pcr_interface.c (PCR) +* Fix assertion violation in DllMain of win32_threads +* Fix data race during apply_to_each_object(reset_back_edge) +* Fix dbg_mlc.c/o file name in documentation +* Fix include gc_gcj.h in thread_local_alloc.c +* Fix man section number (3) +* Fix missing GC_generic_malloc_words_small implementation in new_gc_alloc.h +* Fix missing SIGBUS handler setup for kFreeBSD +* Fix null dereference in print_callers on backtrace_symbols failure +* Fix the collector hang when it is configured with --enable-gc-debug +* Fix thread_suspend fail for threads registered from key destructor (OS X) +* Fix typo in AIX macro name +* Fix typo in comment in specific.h + + +== [7.2j] 2018-01-21 == + +* Fix GC allocation mutex in child after a fork +* Fix last_reclaimed..gc_no interval comparison to threshold in unmap_old +* Fix libgc version which was changed in linkage breaking way +* Fix missing EOLn output in threadlibs tool + + +== [7.2i] 2017-12-21 == + +* Avoid data race in finalized_count (gctest) +* Fix assertion violation about disabled cancel in try_to_collect_inner +* Fix data race in a list referenced by A.aa (gctest) +* Fix data race in do_local_mark when comparing active_count to helper_count +* Fix data race in GC_init_explicit_typing +* Fix data race in last_stop_count access (suspend_handler_inner) +* Fix data race in mark_thread when updating mark_no +* Fix data race when getting object size in explicitly-typed allocators +* Fix lack of barriers to synchronize memory for suspend_handler +* Fix typos in cdescr.html, extend_size_map and ews4800 doc, README.sgi +* Prevent 'Unexpected heap growth' in single-threaded gctest (Linux/x64) + + +== [7.2h] 2017-10-12 == + +* Add gctest as a test (CMake) +* Change no-argument functions declaration style to ANSI C (extra files) +* Do not allow SHORT_DBG_HDRS if KEEP_BACK_PTRS or MAKE_BACK_GRAPH +* Ensure oom_fn callback executed on out-of-memory in calloc +* Fix '~' operator application to unsigned values shorter than word +* Fix 'context local variable might be clobbered by setjmp' compiler warning +* Fix 'doc' files installation folder +* Fix 'shift count >= width of type' compiler warning in GC_SQRT_SIZE_MAX +* Fix ALL_INTERIOR_POINTERS name in comments and documentation +* Fix AO_SRC_DIR target name in NT_*_MAKEFILE +* Fix assertion in GC_mark_from for non-heap regions +* Fix assertion in GC_steal_mark_stack for non-heap regions +* Fix assertion violation in GC_repeat_read if --enable-redirect-malloc +* Fix assertion violation in GC_wait_builder called from start_mark_threads +* Fix assertion violation in mark_local checking GC_mark_stack_top +* Fix assertion violation in return_single_freelist in child process +* Fix bm_huge initialization for 64-bit targets (gctest) +* Fix broken external links in documentation +* Fix bytes count passed to add_to_our_memory in backgraph new_back_edges +* Fix calloc_explicitly_typed in case of lb*n overflow +* Fix CMake warning about CMP0054 by unquoting instances of HOST +* Fix conditional expression in pos_fetch, next non-macro definitions (cord) +* Fix configure --disable-munmap handling +* Fix CORD_substr_closure for the case when CORD_from_fn returns C string +* Fix crash in FirstDLOpenedLinkMap if app linked statically (Alpine Linux) +* Fix double lock in pthread_detach (Cygwin, winpthreads) +* Fix double multiplication of lb by n in calloc_explicitly_typed +* Fix enable_parallel_mark condition in CMake script +* Fix external libatomic_ops pkg-config-based detection +* Fix gc_allocator.h file name in new_gc_alloc.h comment +* Fix gc_backptr.h, gc_mark.h, GC_DS_TAGS names in documentation +* Fix gc_cleanup destructor for non-heap objects (gc_cpp) +* Fix GC_collect_or_expand to prevent allocation size value wrap-around +* Fix GC_incremental declaration/definition type mismatch +* Fix GC_mark_stack_top assertion violation properly in mark_local +* Fix GC_remove_specific invocation from remove_all_threads_but_me +* Fix GC_requested_heapsize increment in GC_init +* Fix GC_setspecific to prevent garbage collection inside +* Fix GC_SIZE_MAX definition (Linux/musl-gcc) +* Fix GCJ support in CMake build script +* Fix gctest crash if configure --enable-handle-fork on Darwin +* Fix get_maps on proc maps file asynchronous growth +* Fix hb_n_marks underflow in clear_fl_marks if MARK_BIT_PER_OBJ +* Fix header filename in gcconfig.h comment +* Fix infinite mark_some calls after memory mapping disappeared (Glibc) +* Fix integer shift undefined behavior in GC_init_explicit_typing +* Fix leak_test crash in print_callers if free() is redirected +* Fix Makefile.direct recursive invocation +* Fix malloc routines to prevent size value wrap-around (fix CVE-2016-9427) +* Fix missing win32_threads.c compilation for Cygwin (CMake) +* Fix MS VC warning about compiling unused checksums and thread_local_alloc +* Fix name typos in GC_FAST_MALLOC_GRANS comment +* Fix null dereference in reclaim_block if DONT_ADD_BYTE_AT_END +* Fix OSF1 host pattern in CMakeLists.txt +* Fix PCR-Makefile by removing compilation of a missing file +* Fix potential data race in GC_SysVGetDataStart (SPARC) +* Fix potential integer overflow in GC_find_limit_* functions +* Fix printf arguments type in print_callers +* Fix pthread_detach for threads not yet registered (Cygwin, winpthreads) +* Fix pthread_join to avoid thread removal on failure (Cygwin, winpthreads) +* Fix pthread_join when thread is registered in thread key destructor +* Fix push_complex_descriptor to avoid unlimited global mark stack growth +* Fix removal of dead threads in a child process +* Fix SIGSEGV in GC_is_marked when gc_cleanup is used in leak-finding mode +* Fix SIGSEGV in mark_from called from do_local_mark if WRAP_MARK_SOME +* Fix Solaris/sparc detection in case of strict C compliance is enforced +* Fix STACKBOTTOM for Solaris 11/x86 +* Fix storage class of local variable in register_dynamic_libraries (Irix) +* Fix tools/setjmp_t hang (OS X) +* Fix typed_test to prevent fails in malloc_explicitly_typed (64-bit) +* Fix undefined HEAP_START in register_dynamic_libraries +* Fix USE_CUSTOM_SPECIFIC mode (if manually enabled) for Win32 +* Fix USE_GET_STACKBASE_FOR_MAIN definition in gcconfig.h +* Fix various typos in comments, documentation and printed messages +* Handle load_segs overflow in register_dynlib_callback gracefully +* Prevent misleading AC_MSG_ERROR/AS_IF errors reported in configure.ac +* Replace (fix) 'objs' acronym in comments with 'objects' word +* Revert "Skip GC_DS_PER_OBJECT objs with negative descriptor in GC_mark_from" +* Update documentation about bugs reporting and new releases notification +* Update Download information in GC overview document +* Update shared libraries version info (v7.2) +* Workaround a bug in winpthreads causing parallel marks deadlock (MinGW) +* Workaround missing getcontext() in Docker osrf/ubuntu_32bit + + +== [7.2g] 2016-05-23 == + +* Fix 'illegal option -xassembler-with-cpp' error (Oracle SunCC) +* Fix 'implicit declaration of function' compiler warnings in cord/de +* Fix CFLAGS in configure regarding -O flag passing to SunCC compiler +* Fix FirstDLOpenedLinkMap for case libgc not 1st dynamically linked (NetBSD) +* Fix GC initialization in cord de_win for Cygwin +* Fix GC_get_stack_base if called before GC_init (Win32) +* Fix OSX issue with pthread_attr_setstacksize failure +* Fix Unicode Win32 API calls in cord de_win +* Fix USE_COMPILER_TLS macro duplicate description in README +* Fix cord de_win WndProc prototype parameters for 64-bit (Win64) +* Fix file descriptor resource leak in GC_register_data_segments (OS/2) +* Fix filename printing in cordtest +* Fix missing cord_pos.h, ec.h among installed headers (Automake) +* Fix missing GC_get_stack_base for Amiga +* Fix missing msvc_dbg.h in dist_noinst_HEADERS (Automake) +* Fix mistyped ARM_THREAD_STATE macro (Darwin/arm) +* Fix null-pointer dereferences on out-of-memory in cord and tests +* Fix potential multiplication overflow in check_heap_stats (gctest) +* Fix race (and potential deadlock) at marker threads initialization +* Fix signedness of char values passed to isspace, iscntrl, isxdigit +* Fix typo (items numbering) in GC_finalize_all documentation +* Fix typos in ERROR_FL, GC_malloc_uncollectable comments +* Fix typos in gc_priv.h, in README for ews4800 +* Fix unresolved vsnprintf in misc.c and snprintf in cordtest (DJGPP, VC) +* Fix various spelling errors +* Fix vsprintf_args initialization/cleanup in CORD_vsprintf for EMX +* Regenerate configure files using official libtool release (v2.4.2) +* Remove documentation about obsolete GC_REDIRECT_TO_LOCAL +* Skip GC_DS_PER_OBJECT objects with negative descriptor in GC_mark_from +* windows-untested: Fix paths to msvc_dbg.c/h == [7.2f] 2014-06-03 == -* Fix 'Bad signal in suspend_handler' abort on FreeBSD-9.2. -* Fix 'source file in a subdirectory' Automake warnings. -* Fix ABORT message in GC_restart_handler. -* Fix ADD_DEFINITION in CMakeLists.txt for kFreeBSD. -* Fix CMakeLists.txt: do not override CMAKE_OSX_ARCHITECTURES. -* Fix GC_alloc_large by bumping GC_collect_at_heapsize in GC_add_to_heap. -* Fix GC_scratch_last_end_ptr update on GC_scratch_alloc failure. -* Fix GET_MEM argument rounding in GC_scratch_alloc and similar. -* Fix PARALLEL_MARK for Windows 7+. -* Fix build (broken by fenv.h inclusion) on Linux/x86_64 under uClibc. -* Fix crash when using GC_malloc_many() as first allocation call. -* Fix mark stack excessive growth during parallel mark. -* Fix or remove broken URLs in documentation. -* Fix out-of-memory case in new_back_edges, push_in_progress (backgraph). -* Fix typo in GC_collect_or_expand comment. -* Fix typos in GC overview file, gc_config_macros.h, gc_cpp.h, README.changes. -* Regenerate configure files by automake 1.14.1, libtool 2.4.2.418. -* Update emails/links due to project site and ML transition. +* Fix 'Bad signal in suspend_handler' abort on FreeBSD-9.2 +* Fix 'source file in a subdirectory' Automake warnings +* Fix ABORT message in GC_restart_handler +* Fix ADD_DEFINITION in CMakeLists.txt for kFreeBSD +* Fix CMakeLists.txt: do not override CMAKE_OSX_ARCHITECTURES +* Fix GC_alloc_large by bumping GC_collect_at_heapsize in GC_add_to_heap +* Fix GC_scratch_last_end_ptr update on GC_scratch_alloc failure +* Fix GET_MEM argument rounding in GC_scratch_alloc and similar +* Fix PARALLEL_MARK for Windows 7+ +* Fix build (broken by fenv.h inclusion) on Linux/x86_64 under uClibc +* Fix crash when using GC_malloc_many() as first allocation call +* Fix mark stack excessive growth during parallel mark +* Fix or remove broken URLs in documentation +* Fix out-of-memory case in new_back_edges, push_in_progress (backgraph) +* Fix typo in GC_collect_or_expand comment +* Fix typos in GC overview file, gc_config_macros.h, gc_cpp.h, README.changes +* Regenerate configure files by automake 1.14.1, libtool 2.4.2.418 +* Update emails/links due to project site and ML transition == [7.2e] 2013-11-10 == -* Add weak attribute to avoid __data_start undefined messages (s390x). -* Add weak stubs for pthread_cancel API. -* Adjust 'pthread_[un]register_cancel undefined ref' workaround (Pthreads). -* Append _test suffix to 'initsecondarythread' binary file names. -* Enable PARALLEL_MARK and THREAD_LOCAL_ALLOC for FreeBSD in configure. -* Fix 'stack section' pointer passed to push_all_stack_sections (Pthreads). -* Fix GC_CreateThread 'dwStackSize' argument type for Win64. -* Fix GC_PTHREAD_PTRVAL definition for GC_PTHREADS_PARAMARK (Win32). -* Fix GC_clear_stack by declaring 'dummy' local array as volatile. -* Fix GC_get_stack_base assembly code (Cygwin/Clang). -* Fix GC_malloc_explicitly_typed_ignore_off_page for large allocations. -* Fix GC_marker_Id elements initialization (WinCE). -* Fix GC_print_trace missing unlock. -* Fix GC_unix_mmap_get_mem for open of /dev/zero failure. -* Fix GC_win32_free_heap compilation error for Cygwin. -* Fix GC_win32_free_heap to prevent memory leak if USE_GLOBAL_ALLOC. -* Fix Win32 GC_write preventing potential infinite recursion at abort. -* Fix assertion violation in GC_mark_from prefetch loop. -* Fix collection of objects referenced only from GC_mark_stack_X variables. -* Fix dwSize argument of VirtualFree call in detect_GetWriteWatch (Win32). -* Fix heap sections overflow for Win32/Cygwin with enabled parallel marker. -* Fix min_bytes_allocd preventing potential infinite loop in GC_allocobj. -* Fix missing tabs in SMakefile.amiga file. -* Fix null-pointer dereference in CORD_substr_closure. -* Fix old_segv/bus_act variables initialization for FreeBSD. -* Fix potential double fclose in test_extras (cordtest). -* Fix pthread_attr_t resource leak in pthread_create. -* Fix race in GC_print_all_errors regarding GC_leaked. -* Fix sizeof in GC_push_thread_structures. -* Fix stackbottom/stack_end assignment in GC_call_with_gc_active. -* Fix tests makefile to link with new GNU ld linking rules. -* Fix typos in comments and documentation. -* Fix unportable '==' test operators in configure. -* Fix vsprintf_args cleanup in CORD_vsprintf. -* Merge FreeBSD New ports collection for boehm-gc v7.2d. -* Replace GC_DBG_RA with GC_DBG_EXTRAS macro. -* Replace deprecated [CXX]INCLUDES to AM_C[PP]FLAGS in configure.ac file. -* Use __builtin_extract_return_addr in GC_RETURN_ADDR_PARENT (gcc/x86). +* Add weak attribute to avoid __data_start undefined messages (s390x) +* Add weak stubs for pthread_cancel API +* Adjust 'pthread_[un]register_cancel undefined ref' workaround (Pthreads) +* Append _test suffix to 'initsecondarythread' binary file names +* Enable PARALLEL_MARK and THREAD_LOCAL_ALLOC for FreeBSD in configure +* Fix 'stack section' pointer passed to push_all_stack_sections (Pthreads) +* Fix GC_CreateThread 'dwStackSize' argument type for Win64 +* Fix GC_PTHREAD_PTRVAL definition for GC_PTHREADS_PARAMARK (Win32) +* Fix GC_clear_stack by declaring 'dummy' local array as volatile +* Fix GC_get_stack_base assembly code (Cygwin/Clang) +* Fix GC_malloc_explicitly_typed_ignore_off_page for large allocations +* Fix GC_marker_Id elements initialization (WinCE) +* Fix GC_print_trace missing unlock +* Fix GC_unix_mmap_get_mem for open of /dev/zero failure +* Fix GC_win32_free_heap compilation error for Cygwin +* Fix GC_win32_free_heap to prevent memory leak if USE_GLOBAL_ALLOC +* Fix Win32 GC_write preventing potential infinite recursion at abort +* Fix assertion violation in GC_mark_from prefetch loop +* Fix collection of objects referenced only from GC_mark_stack_X variables +* Fix dwSize argument of VirtualFree call in detect_GetWriteWatch (Win32) +* Fix heap sections overflow for Win32/Cygwin with enabled parallel marker +* Fix min_bytes_allocd preventing potential infinite loop in GC_allocobj +* Fix missing tabs in SMakefile.amiga file +* Fix null-pointer dereference in CORD_substr_closure +* Fix old_segv/bus_act variables initialization for FreeBSD +* Fix potential double fclose in test_extras (cordtest) +* Fix pthread_attr_t resource leak in pthread_create +* Fix race in GC_print_all_errors regarding GC_leaked +* Fix sizeof in GC_push_thread_structures +* Fix stackbottom/stack_end assignment in GC_call_with_gc_active +* Fix tests makefile to link with new GNU ld linking rules +* Fix typos in comments and documentation +* Fix unportable '==' test operators in configure +* Fix vsprintf_args cleanup in CORD_vsprintf +* Merge FreeBSD New ports collection for boehm-gc v7.2d +* Replace GC_DBG_RA with GC_DBG_EXTRAS macro +* Replace deprecated [CXX]INCLUDES to AM_C[PP]FLAGS in configure.ac file +* Use __builtin_extract_return_addr in GC_RETURN_ADDR_PARENT (gcc/x86) == [7.2d] 2012-08-09 == -* Fix GC_call_with_stack_base to prevent its tail-call optimization. -* Fix all address-of-dummy operations by using GC_approx_sp() instead. -* Fix stop_info.stack_ptr assignment in GC_suspend_all for OpenBSD. -* Fix test_cpp (ensure the collector recognizes pointers to interiors). -* Fix thread-related tests for pthreads-w32. -* test_cpp: Fix WinMain to prevent SEGV if zero arguments passed (MinGW). +* Fix GC_call_with_stack_base to prevent its tail-call optimization +* Fix all address-of-dummy operations by using GC_approx_sp() instead +* Fix stop_info.stack_ptr assignment in GC_suspend_all for OpenBSD +* Fix test_cpp (ensure the collector recognizes pointers to interiors) +* Fix thread-related tests for pthreads-w32 +* test_cpp: Fix WinMain to prevent SEGV if zero arguments passed (MinGW) == [7.2c] 2012-06-11 == -* Fix CORD_cat_char_star to prevent SEGV in case of out-of-memory. -* Fix GC_FirstDLOpenedLinkMap() for NetBSD 6 release. -* Fix GC_scratch_alloc and GC_get_maps invocations to prevent SEGV. -* Fix visibility of GC_clear/set_mark_bit (unhide symbols). -* Fix visibility of GC_push_all/conditional, GC_push_other_roots symbols. +* Fix CORD_cat_char_star to prevent SEGV in case of out-of-memory +* Fix GC_FirstDLOpenedLinkMap() for NetBSD 6 release +* Fix GC_scratch_alloc and GC_get_maps invocations to prevent SEGV +* Fix visibility of GC_clear/set_mark_bit (unhide symbols) +* Fix visibility of GC_push_all/conditional, GC_push_other_roots symbols == [7.2b] 2012-05-23 == -* Fix assertion in GC_malloc_[atomic_]uncollectable (THREADS case only). +* Fix assertion in GC_malloc_[atomic_]uncollectable (THREADS case only) == [7.2] 2012-05-11 == -* Abort in GC_thr_init on pthread_atfork failure (POSIX threads). -* Add GC_WIN32_PTHREADS target in configure. -* Add GC_is_disabled new function to GC API. -* Add info that getcontext() resets FPE mask no longer on Linux/x86_64. -* Add public GC_set_handle_fork to control forked child handling support. -* Add realloc_test.c test. -* Add support for Hexagon target. -* Add thread-safe GC_get_heap_usage_safe to GC API. -* Change GC_check_fl_marks prototype and implementation. -* Check pthread_create/join result in test. -* Define GC_DLL (in configure) if building only dynamic libraries. -* Define NO_DEBUGGING (in configure) if "--disable-gc-debug" is set. -* Disable incremental mode on Darwin if fork handling requested. -* Enable parallel marker in configure for Solaris. -* Fix "comparison of signed and unsigned values" compiler warnings. -* Fix 'volatile' keyword placement in GC_SysVGetDataStart. -* Fix ALIGNMENT, CPP_WORDSZ, GC_GRANULE_BYTES/WORDS for x32 target. -* Fix GC_READ_ENV_FILE code for Cygwin. -* Fix GC_add_roots_inner for Mac OS X (align segment start). -* Fix GC_check_fl_marks regarding concurrent access. -* Fix GC_finalizer_nested size to workaround alignment problem in Watcom. -* Fix GC_find_limit_with_bound to always reset fault handler on return. -* Fix GC_init static assertion for clang/x64 (Darwin). -* Fix GC_init[_lib_bounds] and GC_get_main_stack_base for malloc redirection. -* Fix GC_push_all/selected boundaries check. -* Fix GC_register_my_thread marking thread as detached (Cygwin/pthreads-w32). -* Fix GC_remove_all_threads_but_me to cleanup thread-specific data storage. -* Fix GC_restart_handler to preserve errno if needed. -* Fix GC_root_size update in GC_add_roots_inner (Win32). -* Fix GC_unregister_my_thread to ensure no ongoing incremental GC (Win32). -* Fix GC_with_callee_saves_pushed for clang (disable __builtin_unwind_init). -* Fix calloc, GC_generic_malloc to check for allocation size overflows. -* Fix compiler warning in GC_dyld_image_add/remove (Darwin). -* Fix configure --enable-cplusplus make install. -* Fix configure to disable GCC aliasing optimization unless forced to. -* Fix duplicate definitions in gcconfig.h for NetBSD. -* Fix fork() support on Cygwin and Darwin targets. -* Fix gc.h compatibility regression regarding GC_PTR, GC_I_HIDE_POINTERS. -* Fix gc_cpp.cc for Cygwin (remove duplicate function definition). -* Fix gcconfig.h to define USE_GET_STACKBASE_FOR_MAIN for Android. -* Fix gcconfig.h to handle mips64-linux target. -* Fix gctest (for Win32) to avoid GC_print_stats internal variable usage. -* Fix mach_dep.c to include sys/ucontext.h on Mac OS X 10.6. -* Fix tests to check GC_malloc result for NULL (out-of-memory). -* Fix thread model in configure for MinGW ("win32" instead of "posix"). -* Fix various warnings reported by LINT-like tools. -* Fix visibility of some GC internal symbols used by GNU GCJ currently. -* Port some thread tests to Win32. -* Refine API GC setters and getter comments regarding locking. -* Refine GC_stackbottom description in gc.h. -* Remove duplicate calls in GC_register_dynamic_libraries. -* Remove locking in API GC_get_bytes_since_gc and friends. -* Remove newly-added GC_get_heap_size/free_bytes_inner from API. -* Remove some local variables that are unused. -* Support multi-threading for RTEMS target. -* Use global GC_noop_sink variable in GC_noop1 to suppress compiler warning. -* Use pkg-config to pick up libatomic_ops, etc. -* Workaround some Linux/arm kernels bug to get correct GC_nprocs value. +* Abort in GC_thr_init on pthread_atfork failure (POSIX threads) +* Add GC_WIN32_PTHREADS target in configure +* Add GC_is_disabled new function to GC API +* Add info that getcontext() resets FPE mask no longer on Linux/x86_64 +* Add public GC_set_handle_fork to control forked child handling support +* Add realloc_test.c test +* Add support for Hexagon target +* Add thread-safe GC_get_heap_usage_safe to GC API +* Change GC_check_fl_marks prototype and implementation +* Check pthread_create/join result in test +* Define GC_DLL (in configure) if building only dynamic libraries +* Define NO_DEBUGGING (in configure) if "--disable-gc-debug" is set +* Disable incremental mode on Darwin if fork handling requested +* Enable parallel marker in configure for Solaris +* Fix "comparison of signed and unsigned values" compiler warnings +* Fix 'volatile' keyword placement in GC_SysVGetDataStart +* Fix ALIGNMENT, CPP_WORDSZ, GC_GRANULE_BYTES/WORDS for x32 target +* Fix GC_READ_ENV_FILE code for Cygwin +* Fix GC_add_roots_inner for Mac OS X (align segment start) +* Fix GC_check_fl_marks regarding concurrent access +* Fix GC_finalizer_nested size to workaround alignment problem in Watcom +* Fix GC_find_limit_with_bound to always reset fault handler on return +* Fix GC_init static assertion for clang/x64 (Darwin) +* Fix GC_init[_lib_bounds] and GC_get_main_stack_base for malloc redirection +* Fix GC_push_all/selected boundaries check +* Fix GC_register_my_thread marking thread as detached (Cygwin/pthreads-w32) +* Fix GC_remove_all_threads_but_me to cleanup thread-specific data storage +* Fix GC_restart_handler to preserve errno if needed +* Fix GC_root_size update in GC_add_roots_inner (Win32) +* Fix GC_unregister_my_thread to ensure no ongoing incremental GC (Win32) +* Fix GC_with_callee_saves_pushed for clang (disable __builtin_unwind_init) +* Fix calloc, GC_generic_malloc to check for allocation size overflows +* Fix compiler warning in GC_dyld_image_add/remove (Darwin) +* Fix configure --enable-cplusplus make install +* Fix configure to disable GCC aliasing optimization unless forced to +* Fix duplicate definitions in gcconfig.h for NetBSD +* Fix fork() support on Cygwin and Darwin targets +* Fix gc.h compatibility regression regarding GC_PTR, GC_I_HIDE_POINTERS +* Fix gc_cpp.cc for Cygwin (remove duplicate function definition) +* Fix gcconfig.h to define USE_GET_STACKBASE_FOR_MAIN for Android +* Fix gcconfig.h to handle mips64-linux target +* Fix gctest (for Win32) to avoid GC_print_stats internal variable usage +* Fix mach_dep.c to include sys/ucontext.h on Mac OS X 10.6 +* Fix tests to check GC_malloc result for NULL (out-of-memory) +* Fix thread model in configure for MinGW ("win32" instead of "posix") +* Fix various warnings reported by LINT-like tools +* Fix visibility of some GC internal symbols used by GNU GCJ currently +* Port some thread tests to Win32 +* Refine API GC setters and getter comments regarding locking +* Refine GC_stackbottom description in gc.h +* Remove duplicate calls in GC_register_dynamic_libraries +* Remove locking in API GC_get_bytes_since_gc and friends +* Remove newly-added GC_get_heap_size/free_bytes_inner from API +* Remove some local variables that are unused +* Support multi-threading for RTEMS target +* Use global GC_noop_sink variable in GC_noop1 to suppress compiler warning +* Use pkg-config to pick up libatomic_ops, etc +* Workaround some Linux/arm kernels bug to get correct GC_nprocs value == [7.2alpha6] 2011-06-14 == @@ -1009,8 +1823,8 @@ K&R-style function definition with the ANSI C one. * extra/setjmp_t.c (nested_sp): Implement in the same way as GC_approx_sp. -* dyn_load.c (GC_dyld_sections): Add more sctions. -* dyn_load.c (GC_dyld_add_sect_fmts): New static varaible. +* dyn_load.c (GC_dyld_sections): Add more sections. +* dyn_load.c (GC_dyld_add_sect_fmts): New static variable. * dyn_load.c (L2_MAX_OFILE_ALIGNMENT): New macro. * dyn_load.c (GC_dyld_image_add, GC_dyld_image_remove): Improve logging; add support for on-demand sections. @@ -2348,7 +3162,7 @@ GC_enable_incremental() if MAKE_BACKGRAPH is defined, but do invoke it even if parallel marking is enabled. * tests/test.c (reverse_test): Comment out a check for MSWIN32 -(when determing BIG value) assuming outdated win32S. +(when determining BIG value) assuming outdated win32S. * tests/test.c (reverse_test): Rename to reverse_test_inner; change the declaration (to be of GC_fn_type); call itself thru GC_call_with_gc_active() if the argument is zero. @@ -3889,7 +4703,7 @@ GC_init_win32) if USE_MUNMAP. * os_dep.c (GC_init_win32): Turn off memory unmapping if GlobalAlloc() is used. * os_dep.c (GC_win32_get_mem): Define and use new -VIRTUAL_ALLOC_PAD macro; don't waste a extra memory page unless +VIRTUAL_ALLOC_PAD macro; don't waste an extra memory page unless MPROTECT_VDB is in use. * Makefile: Replace "version.h" with "include/gc_version.h". @@ -4623,7 +5437,7 @@ anymore and GCC produces a warning for it). * alloc.c (GC_stopped_mark): Adjust printf argument type specifier. * backgraph.c: Include dbg_mlc.h before ifdef MAKE_BACK_GRAPH (for -the case when the configuration information comes from aconfig +the case when the configuration information comes from a config.h file). * checksums.c: Likewise. * include/gc_allocator.h (GC_ATTR_UNUSED): Use "__unused__" @@ -5171,7 +5985,7 @@ structure. * include/private/gc_pmark.h (PUSH_CONTENTS_HDR for MARK_BIT_PER_OBJ): Add missing backslash before eoln. -* misc.c (GC_set_warn_proc): Implicitly intialize GC on +* misc.c (GC_set_warn_proc): Implicitly initialize GC on non-Cygwin win32. * configure.ac: Enable thread-local allocation for sparc-linux. @@ -5555,7 +6369,7 @@ value, would be negative. * mark.c (GC_push_next_marked): correct comment. * Makefile.direct: document NO_PROC_STAT. -* include/private/gcconfig.h: Accomodate NO_PROC_STAT. +* include/private/gcconfig.h: Accommodate NO_PROC_STAT. == [7.1alpha2] 2008-01-10 == @@ -5647,7 +6461,7 @@ for HURD. * dbg_mlc.c: Use random() on all glibc systems. * mach_dep.c (GC_with_callee_saves_pushed): Don't use getcontext() on HURD. Add comment. -* pthread_stop_world.c (GC_suspend_handler, GC_stop_init): Accomodate +* pthread_stop_world.c (GC_suspend_handler, GC_stop_init): Accommodate systems without SA_SIGINFO. * include/gc.h (GC_PTR_STORE): Fix non-DEBUG parentheses. @@ -5783,7 +6597,7 @@ GC_WIN32_PTHREADS. Define USE_PTHREAD_LOCKS only if we have pthreads. * gc_dlopen.c, thread_local_alloc.c, threadlibs.c, win32_threads.c, -tests/test.c: Accomodate GC_WIN32_PTHREADS. +tests/test.c: Accommodate GC_WIN32_PTHREADS. * include/gc.h: Don't include windows.h for GC_WIN32_PTHREADS. * include/gc_config_macros.h: Define both PTHREADS and GC_WIN32_THREADS. @@ -6740,7 +7554,7 @@ This should enable support of dynamic libraries under win32 with gcc-compiled code. (Thanks to Ranjit Mathew for the patch.) Turned on dynamic library scanning for win32/gcc. * Removed some remnants of read wrapping (thanks to Kenneth Schalk). -GC_USE_LD_WRAP ws probably broken in recent versions. +GC_USE_LD_WRAP was probably broken in recent versions. * The build could fail on some platforms since gcconfig.h could include declarations mentioning ptr_t, which was not defined, e.g. when if_mach was built (thanks to Yann Dirson for pointing this out). Also @@ -7012,7 +7826,7 @@ This is really a purely generational mode, and we can afford to postpone the collection until the heap is (nearly) full. * Remove read() wrapper for MPROTECT_VDB. It was causing more harm than good. It is often no longer needed if system calls avoid writing to -pointerfull heap objects. +pointerful heap objects. * Fix MACOSX test in gcconfig.h (thanks to John Clements). * Change GC_test_and_set so that it consistently has one argument. Add spaces to ::: in powerpc assembly code in gc_locks.h (thanks to @@ -7031,7 +7845,7 @@ Wink Saville for pointing this out). * Added a bit more assertion checking to make sure that gcj objects on free lists never have a nonzero second word. * Replaced BCC_MAKEFILE with an up-to-date one (thanks to Andre Leiradella). -* Upgraded libtool, cinfigure.in and some related files to hopefully +* Upgraded libtool, configure.in and some related files to hopefully support NetBSD/SPARC (thanks to Adrian Bunk). Unfortunately, libtool 1.4.2 seemed to be buggy due to missing quotes in several "test" invocations. Fixed those in the ltmain.sh script. @@ -7373,7 +8187,7 @@ Toshio Endo for pointing out the problem.) irix_threads.c and now unnecessary. Some comments were obviously wrong. * (Mostly) fixed a longstanding problem with setting of dirty bits from a signal handler. In the presence of threads, dirty bits could get lost, -since the etting of a bit in the bit vector was not atomic with respect +since the getting of a bit in the bit vector was not atomic with respect to other updates. The fix is 100% correct only for platforms for which GC_test_and_set is defined. The goal is to make that all platforms with thread support. Matters only if incremental GC and threads are both diff --git a/src/bdwgc/Makefile.am b/src/bdwgc/Makefile.am index 1688be212..c487b0a3c 100644 --- a/src/bdwgc/Makefile.am +++ b/src/bdwgc/Makefile.am @@ -11,6 +11,12 @@ ## Process this file with automake to produce Makefile.in. +# Info (current:revision:age) for the Libtool versioning system. +# These numbers should be updated at most once just before the release, +# and, optionally, at most once during the development (after the release). +LIBGC_VER_INFO = 4:4:3 +LIBGCCPP_VER_INFO = 4:2:3 + ## FIXME: `make distcheck' in this directory will not currently work. ## This is most likely to the explicit flags passed to submakes. @@ -18,7 +24,7 @@ # use the internal version. This is done since libatomic_ops doesn't # use libtool, since it has no real use for it. But that seems to make # it hard to use either the resulting object files or libraries. -# Thus there seems too be no real reason to recursively build in the +# Thus there seems to be no real reason to recursively build in the # libatomic_ops directory. # if USE_INTERNAL_LIBATOMICS_OPS # SUBDIRS = @maybe_libatomic_ops@ @@ -32,7 +38,7 @@ AM_CPPFLAGS = \ -I$(top_builddir)/include -I$(top_srcdir)/include \ $(ATOMIC_OPS_CFLAGS) -# Initialize variables so that we can declare files locally. +## Initialize variables so that we can declare files locally. EXTRA_DIST = lib_LTLIBRARIES = include_HEADERS = @@ -49,25 +55,35 @@ pkgconfig_DATA = bdw-gc.pc # --------- lib_LTLIBRARIES += libgc.la + if SINGLE_GC_OBJ + libgc_la_SOURCES = extra/gc.c + +if PTHREAD_START_STANDALONE +AM_CPPFLAGS += -DGC_PTHREAD_START_STANDALONE +libgc_la_SOURCES += pthread_start.c +endif + else + EXTRA_DIST += extra/gc.c libgc_la_SOURCES = \ allchblk.c alloc.c blacklst.c checksums.c dbg_mlc.c \ dyn_load.c finalize.c gc_dlopen.c gcj_mlc.c headers.c \ mach_dep.c malloc.c mallocx.c mark.c mark_rts.c misc.c new_hblk.c \ obj_map.c os_dep.c pcr_interface.c ptr_chck.c real_malloc.c reclaim.c \ - specific.c stubborn.c thread_local_alloc.c typd_mlc.c + specific.c stubborn.c typd_mlc.c # C Library: Architecture Dependent # --------------------------------- if WIN32_THREADS -libgc_la_SOURCES += win32_threads.c +libgc_la_SOURCES += thread_local_alloc.c win32_threads.c else if PTHREADS -libgc_la_SOURCES += pthread_start.c pthread_support.c +# Not Cygwin or MinGW. +libgc_la_SOURCES += pthread_start.c pthread_support.c thread_local_alloc.c if DARWIN_THREADS libgc_la_SOURCES += darwin_stop_world.c else @@ -84,6 +100,7 @@ if ENABLE_DISCLAIM libgc_la_SOURCES += fnlz_mlc.c endif +## End of !SINGLE_GC_OBJ endif if USE_INTERNAL_LIBATOMIC_OPS @@ -98,27 +115,26 @@ endif # linuxthread semaphore functions get linked: libgc_la_LIBADD = @addobjs@ $(THREADDLLIBS) $(UNWINDLIBS) $(ATOMIC_OPS_LIBS) libgc_la_DEPENDENCIES = @addobjs@ -libgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info 1:3:0 -no-undefined +libgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info $(LIBGC_VER_INFO) \ + -no-undefined EXTRA_libgc_la_SOURCES = ia64_save_regs_in_stack.s sparc_mach_dep.S \ sparc_netbsd_mach_dep.s sparc_sunos4_mach_dep.s - +if CPLUSPLUS # C++ Interface # ------------- - -if CPLUSPLUS lib_LTLIBRARIES += libgccpp.la pkginclude_HEADERS += include/gc_cpp.h include_HEADERS += include/extra/gc_cpp.h libgccpp_la_SOURCES = gc_cpp.cc libgccpp_la_LIBADD = ./libgc.la -libgccpp_la_LDFLAGS = -version-info 1:3:0 -no-undefined +libgccpp_la_LDFLAGS = -version-info $(LIBGCCPP_VER_INFO) -no-undefined endif -# FIXME: If Visual C++ users use Makefile.am, this should go into -# pkginclude_HEADERS with proper AM_CONDITIONALization. Otherwise -# delete this comment. +## FIXME: If Visual C++ users use Makefile.am, this should go into +## pkginclude_HEADERS with proper AM_CONDITIONALization. Otherwise +## delete this comment. EXTRA_DIST += gc_cpp.cpp @@ -126,7 +142,10 @@ EXTRA_DIST += gc_cpp.cpp # ---- AM_CXXFLAGS = @GC_CFLAGS@ -AM_CFLAGS = @GC_CFLAGS@ +AM_CFLAGS = $(WERROR_CFLAGS) @GC_CFLAGS@ + +CFLAGS += $(CFLAGS_EXTRA) +CXXFLAGS += $(CFLAGS_EXTRA) ## FIXME: relies on internal code generated by automake. ## FIXME: ./configure --enable-dependency-tracking should be used @@ -165,15 +184,14 @@ CCASFLAGS += $(DEFS) # documentation which is not installed # -EXTRA_DIST += README.QUICK TODO +EXTRA_DIST += README.QUICK # other makefiles # :GOTCHA: deliberately we do not include 'Makefile' EXTRA_DIST += BCC_MAKEFILE NT_MAKEFILE \ OS2_MAKEFILE PCR-Makefile digimars.mak EMX_MAKEFILE \ Makefile.direct SMakefile.amiga WCC_MAKEFILE autogen.sh \ - NT_STATIC_THREADS_MAKEFILE NT_X64_STATIC_THREADS_MAKEFILE \ - NT_X64_THREADS_MAKEFILE CMakeLists.txt tests/CMakeLists.txt + CMakeLists.txt tests/CMakeLists.txt # files used by makefiles other than Makefile.am # @@ -197,5 +215,5 @@ include include/include.am include cord/cord.am include tests/tests.am include doc/doc.am -# Putting these at the top causes cord to be built first, and not find libgc.a -# on HP/UX. There may be a better fix. +## Putting these at the top causes cord to be built first, and not find +## libgc.a on HP/UX. There may be a better fix. diff --git a/src/bdwgc/Makefile.direct b/src/bdwgc/Makefile.direct index 8ab80e8b5..f661cf099 100644 --- a/src/bdwgc/Makefile.direct +++ b/src/bdwgc/Makefile.direct @@ -5,9 +5,10 @@ # gc.a - builds basic library # c++ - adds C++ interface to library # cords - adds cords (heavyweight strings) to library -# test - prints porting information, then builds basic version of gc.a, -# and runs some tests of collector and cords. Does not add cords or -# c++ interface to gc.a +# check - prints porting information, then builds basic version of gc.a, +# and runs some tests of collector and cords. Does not add cords or +# c++ interface to gc.a +# check-cpp - runs C++ test without adding C++ (and cords) interface to gc.a # cord/de - builds dumb editor based on cords. ABI_FLAG= @@ -21,10 +22,17 @@ AS_ABI_FLAG=$(ABI_FLAG) # executables. CC=cc $(ABI_FLAG) + CXX=g++ $(ABI_FLAG) +# Needed only for "make c++", which adds the c++ interface. + AS=as $(AS_ABI_FLAG) -# The above doesn't work with gas, which doesn't run cpp. -# Define AS as `gcc -c -x assembler-with-cpp' instead. +# The above doesn't work with gas, which doesn't run cpp. +# Define AS as `gcc -c -x assembler-with-cpp' instead. +# Under Irix 6, you have to specify the ABI (-o32, -n32, or -64) +# if you use something other than the default ABI on your machine. + +LD=ld # Redefining srcdir allows object code for the nonPCR version of the collector # to be generated in different directories. @@ -36,17 +44,20 @@ AO_SRC_DIR=$(srcdir)/libatomic_ops CFLAGS_EXTRA= CFLAGS= -O -I$(srcdir)/include -I$(AO_SRC_DIR)/src \ - -DATOMIC_UNCOLLECTABLE -DNO_EXECUTE_PERMISSION -DALL_INTERIOR_POINTERS \ + -DGC_ATOMIC_UNCOLLECTABLE -DNO_EXECUTE_PERMISSION -DALL_INTERIOR_POINTERS \ $(CFLAGS_EXTRA) -# To build the parallel collector on Linux, add to the above: -# -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC +# To build the collector with threads support, add to the above: +# -DGC_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC +# # To build the thread-capable preload library that intercepts # malloc, add -DGC_USE_DLOPEN_WRAP -DREDIRECT_MALLOC=GC_malloc -fpic +# # To build the parallel collector in a static library on HP/UX, # add to the above: # -DGC_HPUX_THREADS -DTHREAD_LOCAL_ALLOC -D_POSIX_C_SOURCE=199506L -mt # FIXME: PARALLEL_MARK currently broken on HP/UX. +# # To build the thread-safe collector on Tru64, add to the above: # -pthread -DGC_OSF1_THREADS @@ -111,7 +122,7 @@ SRCS= $(CSRCS) \ ia64_save_regs_in_stack.s sparc_mach_dep.S \ sparc_netbsd_mach_dep.s sparc_sunos4_mach_dep.s $(CORD_SRCS) -DOC_FILES= README.QUICK TODO doc/README.Mac doc/README.OS2 \ +DOC_FILES= doc/README.Mac doc/README.OS2 \ doc/README.amiga doc/README.cords doc/debugging.html \ doc/finalization.html doc/porting.html doc/overview.html \ doc/README.hp doc/README.linux doc/README.rs6000 \ @@ -136,11 +147,10 @@ GNU_BUILD_FILES= configure.ac Makefile.am configure install-sh Makefile.in \ OTHER_MAKEFILES= OS2_MAKEFILE NT_MAKEFILE gc.mak \ BCC_MAKEFILE EMX_MAKEFILE WCC_MAKEFILE PCR-Makefile SMakefile.amiga \ - digimars.mak Makefile.direct NT_STATIC_THREADS_MAKEFILE \ - NT_X64_STATIC_THREADS_MAKEFILE NT_X64_THREADS_MAKEFILE + digimars.mak Makefile.direct -OTHER_FILES= tools/setjmp_t.c tools/callprocs.sh extra/MacOS.c \ - extra/Mac_files/datastart.c extra/Mac_files/dataend.c \ +OTHER_FILES= README.QUICK tools/setjmp_t.c tools/callprocs.sh \ + extra/MacOS.c extra/Mac_files/datastart.c extra/Mac_files/dataend.c \ extra/Mac_files/MacOS_config.h tools/add_gc_prefix.c gc_cpp.cpp \ extra/symbian/global_end.cpp extra/symbian/global_start.cpp \ extra/symbian/init_global_static_roots.cpp extra/symbian.cpp \ @@ -154,33 +164,35 @@ CORD_INCLUDE_FILES= $(srcdir)/include/gc.h $(srcdir)/include/cord.h \ UTILS= if_mach if_not_there threadlibs # Libraries needed for curses applications. Only needed for de. -CURSES= -lcurses -ltermlib +# It might also require -ltermlib on some targets. +CURSES= -lcurses # The following is irrelevant on most systems. But a few # versions of make otherwise fork the shell specified in # the SHELL environment variable. SHELL= /bin/sh -SPECIALCFLAGS = -I$(srcdir)/include -I$(AO_SRC_DIR)/src +SPECIALCFLAGS= -I$(srcdir)/include -I$(AO_SRC_DIR)/src # Alternative flags to the C compiler for mach_dep.c. # Mach_dep.c often doesn't like optimization, and it's # not time-critical anyway. # Set SPECIALCFLAGS to -q nodirect_code on Encore. -all: gc.a gctest +all: base_lib gctest atomic_ops.o: $(AO_SRC_DIR)/src/atomic_ops.c - $(CC) $(CFLAGS) -c -o $@ $< + $(CC) $(CFLAGS) -c -o $@ $(AO_SRC_DIR)/src/atomic_ops.c +# For some reason, Solaris make does not handle "$<" properly. atomic_ops_sysdeps.o: $(AO_SRC_DIR)/src/atomic_ops_sysdeps.S - $(CC) $(CFLAGS) -c -o $@ $< + $(CC) $(CFLAGS) -c -o $@ $(AO_SRC_DIR)/src/atomic_ops_sysdeps.S -LEAKFLAGS=$(CFLAGS) -DFIND_LEAK +LEAKFLAGS= $(CFLAGS) -DFIND_LEAK BSD-pkg-all: bsd-libgc.a bsd-libleak.a bsd-libgc.a: - $(MAKE) CFLAGS="$(CFLAGS)" clean c++-t + $(MAKE) -f Makefile.direct CFLAGS="$(CFLAGS)" clean c++-t mv gc.a bsd-libgc.a bsd-libleak.a: @@ -200,18 +212,18 @@ mach_dep.o $(SRCS) $(MAKE) -f PCR-Makefile $(OBJS) tests/test.o dyn_load.o dyn_load_sunos53.o: \ - $(srcdir)/include/private/gc_priv.h \ - $(srcdir)/include/private/gc_hdrs.h $(srcdir)/include/private/gc_locks.h \ - $(srcdir)/include/gc.h $(srcdir)/include/gc_pthread_redirects.h \ - $(srcdir)/include/private/gcconfig.h $(srcdir)/include/gc_typed.h \ - $(srcdir)/include/gc_config_macros.h + $(srcdir)/include/private/gc_priv.h \ + $(srcdir)/include/private/gc_hdrs.h $(srcdir)/include/private/gc_locks.h \ + $(srcdir)/include/gc.h $(srcdir)/include/gc_pthread_redirects.h \ + $(srcdir)/include/private/gcconfig.h $(srcdir)/include/gc_typed.h \ + $(srcdir)/include/gc_config_macros.h mark.o typd_mlc.o finalize.o ptr_chck.o: $(srcdir)/include/gc_mark.h \ $(srcdir)/include/private/gc_pmark.h specific.o pthread_support.o thread_local_alloc.o win32_threads.o: \ - $(srcdir)/include/private/specific.h $(srcdir)/include/gc_inline.h \ - $(srcdir)/include/private/thread_local_alloc.h + $(srcdir)/include/private/specific.h $(srcdir)/include/gc_inline.h \ + $(srcdir)/include/private/thread_local_alloc.h dbg_mlc.o gcj_mlc.o: $(srcdir)/include/private/dbg_mlc.h @@ -223,7 +235,6 @@ tests: mkdir tests base_lib gc.a: $(OBJS) dyn_load.o $(UTILS) - echo > base_lib rm -f dont_ar_1 ./if_mach SPARC SOLARIS touch dont_ar_1 ./if_mach SPARC SOLARIS $(AR) rus gc.a $(OBJS) dyn_load.o @@ -231,9 +242,11 @@ base_lib gc.a: $(OBJS) dyn_load.o $(UTILS) ./if_mach M68K AMIGA $(AR) -vrus gc.a $(OBJS) dyn_load.o ./if_not_there dont_ar_1 $(AR) ru gc.a $(OBJS) dyn_load.o ./if_not_there dont_ar_1 $(RANLIB) gc.a || cat /dev/null -# ignore ranlib failure; that usually means it doesn't exist, and isn't needed + echo > base_lib +# Ignore ranlib failure; that usually means it doesn't exist, and +# isn't needed. -cords: $(CORD_OBJS) cord/cordtest $(UTILS) +cords: $(CORD_OBJS) cord/cordtest $(UTILS) base_lib rm -f dont_ar_3 ./if_mach SPARC SOLARIS touch dont_ar_3 ./if_mach SPARC SOLARIS $(AR) rus gc.a $(CORD_OBJS) @@ -241,23 +254,27 @@ cords: $(CORD_OBJS) cord/cordtest $(UTILS) ./if_mach M68K AMIGA $(AR) -vrus gc.a $(CORD_OBJS) ./if_not_there dont_ar_3 $(AR) ru gc.a $(CORD_OBJS) ./if_not_there dont_ar_3 $(RANLIB) gc.a || cat /dev/null + echo > cords gc_cpp.o: $(srcdir)/gc_cpp.cc $(srcdir)/include/gc_cpp.h $(srcdir)/include/gc.h $(CXX) -c $(CXXFLAGS) $(srcdir)/gc_cpp.cc -test_cpp: $(srcdir)/tests/test_cpp.cc $(srcdir)/include/gc_cpp.h gc_cpp.o $(srcdir)/include/gc.h \ - base_lib $(UTILS) +test_cpp: $(srcdir)/tests/test_cpp.cc $(srcdir)/include/gc_cpp.h $(srcdir)/include/gc.h \ + gc_cpp.o base_lib $(UTILS) rm -f test_cpp ./if_mach HP_PA HPUX $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/tests/test_cpp.cc gc_cpp.o gc.a -ldld `./threadlibs` ./if_not_there test_cpp $(CXX) $(CXXFLAGS) -o test_cpp $(srcdir)/tests/test_cpp.cc gc_cpp.o gc.a `./threadlibs` -c++-t: c++ +check-cpp: test_cpp + ./test_cpp + +c++-t: c++ test_cpp ./test_cpp 1 c++-nt: c++ @echo "Use ./test_cpp 1 to test the leak library" -c++: gc_cpp.o $(srcdir)/include/gc_cpp.h test_cpp +c++: gc_cpp.o $(srcdir)/include/gc_cpp.h base_lib rm -f dont_ar_4 ./if_mach SPARC SOLARIS touch dont_ar_4 ./if_mach SPARC SOLARIS $(AR) rus gc.a gc_cpp.o @@ -265,7 +282,6 @@ c++: gc_cpp.o $(srcdir)/include/gc_cpp.h test_cpp ./if_mach M68K AMIGA $(AR) -vrus gc.a gc_cpp.o ./if_not_there dont_ar_4 $(AR) ru gc.a gc_cpp.o ./if_not_there dont_ar_4 $(RANLIB) gc.a || cat /dev/null - ./test_cpp 1 echo > c++ dyn_load_sunos53.o: dyn_load.c @@ -278,12 +294,12 @@ sunos5gc.so: $(OBJS) dyn_load_sunos53.o # Alpha/OSF shared library version of the collector libalphagc.so: $(OBJS) - ld -shared -o libalphagc.so $(OBJS) dyn_load.o -lc + $(LD) -shared -o libalphagc.so $(OBJS) dyn_load.o -lc ln libalphagc.so libgc.so # IRIX shared library version of the collector libirixgc.so: $(OBJS) dyn_load.o - ld -shared $(ABI_FLAG) -o libirixgc.so $(OBJS) dyn_load.o -lc + $(LD) -shared $(ABI_FLAG) -o libirixgc.so $(OBJS) dyn_load.o -lc ln libirixgc.so libgc.so # Linux shared library version of the collector @@ -303,33 +319,37 @@ dyn_test: #.SUFFIXES: .lo $(SUFFIXES) # #.c.lo: -# $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c $< -o $@ +# $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c $< -o $@ # # liblinuxgc.so: $(LIBOBJS) dyn_load.lo # gcc -shared -Wl,-soname=libgc.so.0 -o libgc.so.0 $(LIBOBJS) dyn_load.lo # touch liblinuxgc.so mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/sparc_mach_dep.S \ - $(srcdir)/sparc_sunos4_mach_dep.s \ - $(srcdir)/ia64_save_regs_in_stack.s \ - $(srcdir)/sparc_netbsd_mach_dep.s $(UTILS) + $(srcdir)/sparc_sunos4_mach_dep.s \ + $(srcdir)/ia64_save_regs_in_stack.s \ + $(srcdir)/sparc_netbsd_mach_dep.s $(UTILS) rm -f mach_dep.o ./if_mach SPARC SOLARIS $(CC) -c -o mach_dep2.o $(srcdir)/sparc_mach_dep.S ./if_mach SPARC OPENBSD $(AS) -o mach_dep2.o $(srcdir)/sparc_sunos4_mach_dep.s ./if_mach SPARC NETBSD $(AS) -o mach_dep2.o $(srcdir)/sparc_netbsd_mach_dep.s ./if_mach SPARC "" $(CC) -c -o mach_dep1.o $(SPECIALCFLAGS) $(srcdir)/mach_dep.c - ./if_mach SPARC "" ld -r -o mach_dep.o mach_dep1.o mach_dep2.o - ./if_mach IA64 "" as $(AS_ABI_FLAG) -o ia64_save_regs_in_stack.o $(srcdir)/ia64_save_regs_in_stack.s + ./if_mach SPARC "" $(LD) -r -o mach_dep.o mach_dep1.o mach_dep2.o + ./if_mach IA64 "" $(AS) -o ia64_save_regs_in_stack.o $(srcdir)/ia64_save_regs_in_stack.s ./if_mach IA64 "" $(CC) -c -o mach_dep1.o $(SPECIALCFLAGS) $(srcdir)/mach_dep.c - ./if_mach IA64 "" ld -r -o mach_dep.o mach_dep1.o ia64_save_regs_in_stack.o - ./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c + ./if_mach IA64 "" $(LD) -r -o mach_dep.o mach_dep1.o ia64_save_regs_in_stack.o + -./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c + -./if_not_there mach_dep.o `cygpath -w /bin/sh` $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c + -./if_not_there mach_dep.o /bin/sh $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c mark_rts.o: $(srcdir)/mark_rts.c $(UTILS) rm -f mark_rts.o -./if_mach ALPHA OSF1 $(CC) -c $(CFLAGS) -Wo,-notail $(srcdir)/mark_rts.c - ./if_not_there mark_rts.o $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c -# Work-around for DEC optimizer tail recursion elimination bug. -# The ALPHA-specific line should be removed if gcc is used. + -./if_not_there mark_rts.o $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c + -./if_not_there mark_rts.o `cygpath -w /bin/sh` $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c + -./if_not_there mark_rts.o /bin/sh $(CC) -c $(CFLAGS) $(srcdir)/mark_rts.c +# Work-around for DEC optimizer tail recursion elimination bug. +# The ALPHA-specific line should be removed if gcc is used. alloc.o: include/gc_version.h @@ -349,17 +369,18 @@ cord/cordprnt.o: cord $(srcdir)/cord/cordprnt.c $(CORD_INCLUDE_FILES) $(CC) $(CFLAGS) -c -I$(srcdir) $(srcdir)/cord/cordprnt.c mv cordprnt.o cord/cordprnt.o -cord/cordtest: $(srcdir)/cord/tests/cordtest.c $(CORD_OBJS) gc.a $(UTILS) +cord/cordtest: $(srcdir)/cord/tests/cordtest.c $(CORD_OBJS) base_lib $(UTILS) rm -f cord/cordtest ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/tests/cordtest.c $(CORD_OBJS) gc.a -lucb ./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/tests/cordtest.c $(CORD_OBJS) gc.a -ldld `./threadlibs` ./if_mach M68K AMIGA $(CC) $(CFLAGS) -UGC_AMIGA_MAKINGLIB -o cord/cordtest $(srcdir)/cord/tests/cordtest.c $(CORD_OBJS) gc.a `./threadlibs` ./if_not_there cord/cordtest $(CC) $(CFLAGS) -o cord/cordtest $(srcdir)/cord/tests/cordtest.c $(CORD_OBJS) gc.a `./threadlibs` -cord/de: $(srcdir)/cord/tests/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(UTILS) +cord/de: $(srcdir)/cord/tests/de.c cord/cordbscs.o cord/cordxtra.o base_lib \ + $(UTILS) rm -f cord/de - ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/tests/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -lucb `./threadlibs` - ./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/tests/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -ldld `./threadlibs` + ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/tests/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses -ltermlib -lucb `./threadlibs` + ./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/tests/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses -ltermlib -ldld `./threadlibs` ./if_mach POWERPC AIX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/tests/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses ./if_mach POWERPC DARWIN $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/tests/de.c cord/cordbscs.o cord/cordxtra.o gc.a ./if_mach I386 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/tests/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs` @@ -378,12 +399,13 @@ if_not_there: $(srcdir)/tools/if_not_there.c $(HOSTCC) $(HOSTCFLAGS) -o if_not_there $(srcdir)/tools/if_not_there.c clean: - rm -f gc.a *.o *.exe tests/*.o gctest gctest_dyn_link test_cpp \ - setjmp_test mon.out gmon.out a.out core if_not_there if_mach \ - base_lib c++ threadlibs $(CORD_OBJS) cord/cordtest cord/de + rm -f gc.a *.i *.o *.exe tests/*.o gctest gctest_dyn_link test_cpp \ + setjmp_test mon.out gmon.out a.out core if_not_there if_mach \ + base_lib c++ $(CORD_OBJS) cord/cordtest cord/de cords \ + dont_ar_* threadlibs -rm -f *~ -gctest: tests/test.o gc.a $(UTILS) +gctest: tests/test.o base_lib $(UTILS) rm -f gctest ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o gctest tests/test.o gc.a -lucb ./if_mach HP_PA HPUX $(CC) $(CFLAGS) -o gctest tests/test.o gc.a -ldld `./threadlibs` @@ -396,7 +418,7 @@ gctest: tests/test.o gc.a $(UTILS) setjmp_test: $(srcdir)/tools/setjmp_t.c $(srcdir)/include/gc.h $(UTILS) $(CC) $(CFLAGS) -o setjmp_test $(srcdir)/tools/setjmp_t.c -test: KandRtest cord/cordtest +check: KandRtest cord/cordtest cord/cordtest # Those tests that work even with a K&R C compiler: @@ -404,13 +426,16 @@ KandRtest: setjmp_test gctest ./setjmp_test ./gctest +# A synonym to "check" (for compatibility with older GC versions). +test: check + add_gc_prefix: $(srcdir)/tools/add_gc_prefix.c $(srcdir)/include/gc_version.h $(CC) -o add_gc_prefix $(srcdir)/tools/add_gc_prefix.c gcname: $(srcdir)/tools/gcname.c $(srcdir)/include/gc_version.h $(CC) -o gcname $(srcdir)/tools/gcname.c -#We assume this is being done from source directory. +# We assume this is being done from source directory. dist gc.tar: $(SRCS) $(DOC_FILES) $(OTHER_FILES) add_gc_prefix gcname rm -f `./gcname` ln -s . `./gcname` @@ -432,7 +457,7 @@ lint: $(CSRCS) tests/test.c # BTL: added to test shared library version of collector. # Currently works only under SunOS5. Requires GC_INIT call from statically # loaded client code. -ABSDIR = `pwd` +ABSDIR= `pwd` gctest_dyn_link: tests/test.o libgc.so $(CC) -L$(ABSDIR) -R$(ABSDIR) -o gctest_dyn_link tests/test.o -lgc -ldl -lthread diff --git a/src/bdwgc/Makefile.in b/src/bdwgc/Makefile.in index b6bc03906..64fffdc77 100644 --- a/src/bdwgc/Makefile.in +++ b/src/bdwgc/Makefile.in @@ -136,51 +136,50 @@ check_PROGRAMS = cordtest$(EXEEXT) gctest$(EXEEXT) leaktest$(EXEEXT) \ middletest$(EXEEXT) smashtest$(EXEEXT) hugetest$(EXEEXT) \ realloc_test$(EXEEXT) staticrootstest$(EXEEXT) $(am__EXEEXT_1) \ $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) -TESTS = cordtest$(EXEEXT) gctest$(EXEEXT) leaktest$(EXEEXT) \ - middletest$(EXEEXT) smashtest$(EXEEXT) hugetest$(EXEEXT) \ - realloc_test$(EXEEXT) staticrootstest$(EXEEXT) \ - $(am__append_12) $(am__append_14) $(am__append_16) \ - $(am__EXEEXT_4) -@SINGLE_GC_OBJ_FALSE@am__append_1 = extra/gc.c +@PTHREAD_START_STANDALONE_TRUE@@SINGLE_GC_OBJ_TRUE@am__append_1 = -DGC_PTHREAD_START_STANDALONE +@PTHREAD_START_STANDALONE_TRUE@@SINGLE_GC_OBJ_TRUE@am__append_2 = pthread_start.c +@SINGLE_GC_OBJ_FALSE@am__append_3 = extra/gc.c # C Library: Architecture Dependent # --------------------------------- -@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_TRUE@am__append_2 = win32_threads.c -@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@am__append_3 = pthread_start.c pthread_support.c -@DARWIN_THREADS_TRUE@@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@am__append_4 = darwin_stop_world.c -@DARWIN_THREADS_FALSE@@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@am__append_5 = pthread_stop_world.c -@MAKE_BACK_GRAPH_TRUE@@SINGLE_GC_OBJ_FALSE@am__append_6 = backgraph.c -@ENABLE_DISCLAIM_TRUE@@SINGLE_GC_OBJ_FALSE@am__append_7 = fnlz_mlc.c +@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_TRUE@am__append_4 = thread_local_alloc.c win32_threads.c +# Not Cygwin or MinGW. +@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@am__append_5 = pthread_start.c pthread_support.c thread_local_alloc.c +@DARWIN_THREADS_TRUE@@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@am__append_6 = darwin_stop_world.c +@DARWIN_THREADS_FALSE@@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@am__append_7 = pthread_stop_world.c +@MAKE_BACK_GRAPH_TRUE@@SINGLE_GC_OBJ_FALSE@am__append_8 = backgraph.c +@ENABLE_DISCLAIM_TRUE@@SINGLE_GC_OBJ_FALSE@am__append_9 = fnlz_mlc.c # C++ Interface # ------------- -@CPLUSPLUS_TRUE@am__append_8 = libgccpp.la -@CPLUSPLUS_TRUE@am__append_9 = include/gc_cpp.h -@CPLUSPLUS_TRUE@am__append_10 = include/extra/gc_cpp.h -@THREADS_TRUE@am__append_11 = $(THREADDLLIBS) -@KEEP_BACK_PTRS_TRUE@am__append_12 = tracetest$(EXEEXT) -@KEEP_BACK_PTRS_TRUE@am__append_13 = tracetest -@THREADS_TRUE@am__append_14 = threadleaktest$(EXEEXT) \ +@CPLUSPLUS_TRUE@am__append_10 = libgccpp.la +@CPLUSPLUS_TRUE@am__append_11 = include/gc_cpp.h +@CPLUSPLUS_TRUE@am__append_12 = include/extra/gc_cpp.h +@THREADS_TRUE@am__append_13 = $(THREADDLLIBS) +@KEEP_BACK_PTRS_TRUE@am__append_14 = tracetest$(EXEEXT) +@KEEP_BACK_PTRS_TRUE@am__append_15 = tracetest +@THREADS_TRUE@am__append_16 = threadleaktest$(EXEEXT) \ @THREADS_TRUE@ threadkey_test$(EXEEXT) \ @THREADS_TRUE@ subthreadcreate_test$(EXEEXT) \ @THREADS_TRUE@ initsecondarythread_test$(EXEEXT) -@THREADS_TRUE@am__append_15 = threadleaktest threadkey_test \ +@THREADS_TRUE@am__append_17 = threadleaktest threadkey_test \ @THREADS_TRUE@ subthreadcreate_test initsecondarythread_test -@CPLUSPLUS_TRUE@am__append_16 = test_cpp$(EXEEXT) -@CPLUSPLUS_TRUE@am__append_17 = test_cpp -@ENABLE_DISCLAIM_TRUE@am__append_18 = disclaim_test disclaim_bench -@ENABLE_DISCLAIM_TRUE@am__append_19 = disclaim_test disclaim_bench -@ENABLE_DISCLAIM_TRUE@@THREADS_TRUE@am__append_20 = $(THREADDLLIBS) +@CPLUSPLUS_TRUE@am__append_18 = test_cpp$(EXEEXT) +@CPLUSPLUS_TRUE@am__append_19 = test_cpp +@ENABLE_DISCLAIM_TRUE@am__append_20 = disclaim_test$(EXEEXT) \ +@ENABLE_DISCLAIM_TRUE@ disclaim_bench$(EXEEXT) +@ENABLE_DISCLAIM_TRUE@am__append_21 = disclaim_test disclaim_bench +@ENABLE_DISCLAIM_TRUE@@THREADS_TRUE@am__append_22 = $(THREADDLLIBS) subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/m4/gc_set_version.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ - $(am__configure_deps) $(dist_pkgdata_DATA) \ + $(am__configure_deps) $(am__dist_doc_DATA_DIST) \ $(dist_noinst_HEADERS) $(am__include_HEADERS_DIST) \ $(am__pkginclude_HEADERS_DIST) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ @@ -216,9 +215,9 @@ am__uninstall_files_from_dir = { \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } -am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgdatadir)" \ - "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)" \ - "$(DESTDIR)$(pkgincludedir)" +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)" \ + "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(includedir)" "$(DESTDIR)$(pkgincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libcord_la_DEPENDENCIES = $(top_builddir)/libgc.la am__dirstamp = $(am__leading_dot)dirstamp @@ -238,19 +237,21 @@ am__libgc_la_SOURCES_DIST = allchblk.c alloc.c blacklst.c checksums.c \ headers.c mach_dep.c malloc.c mallocx.c mark.c mark_rts.c \ misc.c new_hblk.c obj_map.c os_dep.c pcr_interface.c \ ptr_chck.c real_malloc.c reclaim.c specific.c stubborn.c \ - thread_local_alloc.c typd_mlc.c win32_threads.c \ + typd_mlc.c thread_local_alloc.c win32_threads.c \ pthread_start.c pthread_support.c darwin_stop_world.c \ pthread_stop_world.c backgraph.c fnlz_mlc.c extra/gc.c -@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_TRUE@am__objects_1 = \ +@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_TRUE@am__objects_1 = thread_local_alloc.lo \ @SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_TRUE@ win32_threads.lo @PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@am__objects_2 = pthread_start.lo \ -@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@ pthread_support.lo +@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@ pthread_support.lo \ +@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@ thread_local_alloc.lo @DARWIN_THREADS_TRUE@@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@am__objects_3 = darwin_stop_world.lo @DARWIN_THREADS_FALSE@@PTHREADS_TRUE@@SINGLE_GC_OBJ_FALSE@@WIN32_THREADS_FALSE@am__objects_4 = pthread_stop_world.lo @MAKE_BACK_GRAPH_TRUE@@SINGLE_GC_OBJ_FALSE@am__objects_5 = \ @MAKE_BACK_GRAPH_TRUE@@SINGLE_GC_OBJ_FALSE@ backgraph.lo @ENABLE_DISCLAIM_TRUE@@SINGLE_GC_OBJ_FALSE@am__objects_6 = \ @ENABLE_DISCLAIM_TRUE@@SINGLE_GC_OBJ_FALSE@ fnlz_mlc.lo +@PTHREAD_START_STANDALONE_TRUE@@SINGLE_GC_OBJ_TRUE@am__objects_7 = pthread_start.lo @SINGLE_GC_OBJ_FALSE@am_libgc_la_OBJECTS = allchblk.lo alloc.lo \ @SINGLE_GC_OBJ_FALSE@ blacklst.lo checksums.lo dbg_mlc.lo \ @SINGLE_GC_OBJ_FALSE@ dyn_load.lo finalize.lo gc_dlopen.lo \ @@ -259,15 +260,14 @@ am__libgc_la_SOURCES_DIST = allchblk.c alloc.c blacklst.c checksums.c \ @SINGLE_GC_OBJ_FALSE@ misc.lo new_hblk.lo obj_map.lo os_dep.lo \ @SINGLE_GC_OBJ_FALSE@ pcr_interface.lo ptr_chck.lo \ @SINGLE_GC_OBJ_FALSE@ real_malloc.lo reclaim.lo specific.lo \ -@SINGLE_GC_OBJ_FALSE@ stubborn.lo thread_local_alloc.lo \ -@SINGLE_GC_OBJ_FALSE@ typd_mlc.lo $(am__objects_1) \ +@SINGLE_GC_OBJ_FALSE@ stubborn.lo typd_mlc.lo $(am__objects_1) \ @SINGLE_GC_OBJ_FALSE@ $(am__objects_2) $(am__objects_3) \ @SINGLE_GC_OBJ_FALSE@ $(am__objects_4) $(am__objects_5) \ @SINGLE_GC_OBJ_FALSE@ $(am__objects_6) -@SINGLE_GC_OBJ_TRUE@am_libgc_la_OBJECTS = extra/gc.lo $(am__objects_1) \ -@SINGLE_GC_OBJ_TRUE@ $(am__objects_2) $(am__objects_3) \ -@SINGLE_GC_OBJ_TRUE@ $(am__objects_4) $(am__objects_5) \ -@SINGLE_GC_OBJ_TRUE@ $(am__objects_6) +@SINGLE_GC_OBJ_TRUE@am_libgc_la_OBJECTS = extra/gc.lo $(am__objects_7) \ +@SINGLE_GC_OBJ_TRUE@ $(am__objects_1) $(am__objects_2) \ +@SINGLE_GC_OBJ_TRUE@ $(am__objects_3) $(am__objects_4) \ +@SINGLE_GC_OBJ_TRUE@ $(am__objects_5) $(am__objects_6) @NEED_ATOMIC_OPS_ASM_FALSE@@USE_INTERNAL_LIBATOMIC_OPS_TRUE@nodist_libgc_la_OBJECTS = libatomic_ops/src/atomic_ops.lo @NEED_ATOMIC_OPS_ASM_TRUE@nodist_libgc_la_OBJECTS = libatomic_ops/src/atomic_ops_sysdeps.lo libgc_la_OBJECTS = $(am_libgc_la_OBJECTS) $(nodist_libgc_la_OBJECTS) @@ -505,7 +505,21 @@ am__can_run_installinfo = \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac -DATA = $(dist_pkgdata_DATA) $(pkgconfig_DATA) +man3dir = $(mandir)/man3 +NROFF = nroff +MANS = $(dist_man3_MANS) +am__dist_doc_DATA_DIST = AUTHORS README.md doc/README.DGUX386 \ + doc/README.Mac doc/README.OS2 doc/README.amiga \ + doc/README.arm.cross doc/README.autoconf doc/README.cmake \ + doc/README.cords doc/README.darwin doc/README.environment \ + doc/README.ews4800 doc/README.hp doc/README.linux \ + doc/README.macros doc/README.rs6000 doc/README.sgi \ + doc/README.solaris2 doc/README.symbian doc/README.uts \ + doc/README.win32 doc/README.win64 doc/debugging.html \ + doc/finalization.html doc/gcdescr.html doc/gcinterface.html \ + doc/leak.html doc/overview.html doc/porting.html \ + doc/scale.html doc/simple_example.html doc/tree.html +DATA = $(dist_doc_DATA) $(pkgconfig_DATA) am__include_HEADERS_DIST = include/extra/gc_cpp.h include/extra/gc.h am__pkginclude_HEADERS_DIST = include/gc_cpp.h include/gc.h \ include/gc_allocator.h include/gc_backptr.h \ @@ -722,12 +736,12 @@ TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DIST_SUBDIRS = $(SUBDIRS) -am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/bdw-gc.pc.in \ - $(srcdir)/cord/cord.am $(srcdir)/doc/doc.am \ - $(srcdir)/include/include.am $(srcdir)/tests/tests.am \ - $(top_srcdir)/include/config.h.in AUTHORS ChangeLog TODO \ - compile config.guess config.sub depcomp install-sh ltmain.sh \ - missing test-driver +am__DIST_COMMON = $(dist_man3_MANS) $(srcdir)/Makefile.in \ + $(srcdir)/bdw-gc.pc.in $(srcdir)/cord/cord.am \ + $(srcdir)/doc/doc.am $(srcdir)/include/include.am \ + $(srcdir)/tests/tests.am $(top_srcdir)/include/config.h.in \ + AUTHORS ChangeLog compile config.guess config.sub depcomp \ + install-sh ltmain.sh missing test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -763,20 +777,18 @@ am__relativize = \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" -DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 +DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best -DIST_TARGETS = dist-bzip2 dist-gzip +DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ -AM_CFLAGS = @GC_CFLAGS@ -AM_CPPFLAGS = \ - -I$(top_builddir)/include -I$(top_srcdir)/include \ - $(ATOMIC_OPS_CFLAGS) - +AM_CFLAGS = $(WERROR_CFLAGS) @GC_CFLAGS@ +AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include \ + $(ATOMIC_OPS_CFLAGS) $(am__append_1) AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ ATOMIC_OPS_CFLAGS = @ATOMIC_OPS_CFLAGS@ @@ -790,13 +802,14 @@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ $(DEFS) CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ $(CFLAGS_EXTRA) +CFLAGS_EXTRA = @CFLAGS_EXTRA@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ +CXXFLAGS = @CXXFLAGS@ $(CFLAGS_EXTRA) CXXLIBS = @CXXLIBS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ @@ -857,6 +870,7 @@ STRIP = @STRIP@ THREADDLLIBS = @THREADDLLIBS@ UNWINDLIBS = @UNWINDLIBS@ VERSION = @VERSION@ +WERROR_CFLAGS = @WERROR_CFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -920,11 +934,17 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +# Info (current:revision:age) for the Libtool versioning system. +# These numbers should be updated at most once just before the release, +# and, optionally, at most once during the development (after the release). +LIBGC_VER_INFO = 4:4:3 +LIBGCCPP_VER_INFO = 4:2:3 + # We currently use the source files directly from libatomic_ops, if we # use the internal version. This is done since libatomic_ops doesn't # use libtool, since it has no real use for it. But that seems to make # it hard to use either the resulting object files or libraries. -# Thus there seems too be no real reason to recursively build in the +# Thus there seems to be no real reason to recursively build in the # libatomic_ops directory. # if USE_INTERNAL_LIBATOMICS_OPS # SUBDIRS = @maybe_libatomic_ops@ @@ -934,12 +954,6 @@ top_srcdir = @top_srcdir@ SUBDIRS = ACLOCAL_AMFLAGS = -I m4 -# Initialize variables so that we can declare files locally. - -# FIXME: If Visual C++ users use Makefile.am, this should go into -# pkginclude_HEADERS with proper AM_CONDITIONALization. Otherwise -# delete this comment. - # headers which are not installed # (see include/include.am for more) # @@ -952,16 +966,14 @@ ACLOCAL_AMFLAGS = -I m4 # files used by makefiles other than Makefile.am # -EXTRA_DIST = $(am__append_1) gc_cpp.cpp README.QUICK TODO BCC_MAKEFILE \ +EXTRA_DIST = $(am__append_3) gc_cpp.cpp README.QUICK BCC_MAKEFILE \ NT_MAKEFILE OS2_MAKEFILE PCR-Makefile digimars.mak \ EMX_MAKEFILE Makefile.direct SMakefile.amiga WCC_MAKEFILE \ - autogen.sh NT_STATIC_THREADS_MAKEFILE \ - NT_X64_STATIC_THREADS_MAKEFILE NT_X64_THREADS_MAKEFILE \ - CMakeLists.txt tests/CMakeLists.txt tools/add_gc_prefix.c \ - tools/gcname.c tools/if_mach.c tools/if_not_there.c \ - tools/setjmp_t.c tools/threadlibs.c gc.mak extra/MacOS.c \ - extra/AmigaOS.c extra/symbian/global_end.cpp \ - extra/symbian/global_start.cpp \ + autogen.sh CMakeLists.txt tests/CMakeLists.txt \ + tools/add_gc_prefix.c tools/gcname.c tools/if_mach.c \ + tools/if_not_there.c tools/setjmp_t.c tools/threadlibs.c \ + gc.mak extra/MacOS.c extra/AmigaOS.c \ + extra/symbian/global_end.cpp extra/symbian/global_start.cpp \ extra/symbian/init_global_static_roots.cpp extra/symbian.cpp \ build/s60v3/bld.inf build/s60v3/libgc.mmp \ extra/Mac_files/datastart.c extra/Mac_files/dataend.c \ @@ -972,14 +984,14 @@ EXTRA_DIST = $(am__append_1) gc_cpp.cpp README.QUICK TODO BCC_MAKEFILE \ # C Library # --------- -lib_LTLIBRARIES = libgc.la $(am__append_8) libcord.la +lib_LTLIBRARIES = libgc.la $(am__append_10) libcord.la # unprefixed header -include_HEADERS = $(am__append_10) include/extra/gc.h +include_HEADERS = $(am__append_12) include/extra/gc.h # installed headers # -pkginclude_HEADERS = $(am__append_9) include/gc.h \ +pkginclude_HEADERS = $(am__append_11) include/gc.h \ include/gc_allocator.h include/gc_backptr.h \ include/gc_config_macros.h include/gc_disclaim.h \ include/gc_gcj.h include/gc_inline.h include/gc_mark.h \ @@ -1001,6 +1013,11 @@ dist_noinst_HEADERS = include/cord.h include/cord_pos.h include/ec.h \ include/private/thread_local_alloc.h check_LTLIBRARIES = libstaticrootslib_test.la \ libstaticrootslib2_test.la +TESTS = cordtest$(EXEEXT) gctest$(EXEEXT) leaktest$(EXEEXT) \ + middletest$(EXEEXT) smashtest$(EXEEXT) hugetest$(EXEEXT) \ + realloc_test$(EXEEXT) staticrootstest$(EXEEXT) \ + $(am__append_14) $(am__append_16) $(am__append_18) \ + $(am__append_20) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = bdw-gc.pc @SINGLE_GC_OBJ_FALSE@libgc_la_SOURCES = allchblk.c alloc.c blacklst.c \ @@ -1010,15 +1027,14 @@ pkgconfig_DATA = bdw-gc.pc @SINGLE_GC_OBJ_FALSE@ mark.c mark_rts.c misc.c new_hblk.c \ @SINGLE_GC_OBJ_FALSE@ obj_map.c os_dep.c pcr_interface.c \ @SINGLE_GC_OBJ_FALSE@ ptr_chck.c real_malloc.c reclaim.c \ -@SINGLE_GC_OBJ_FALSE@ specific.c stubborn.c \ -@SINGLE_GC_OBJ_FALSE@ thread_local_alloc.c typd_mlc.c \ -@SINGLE_GC_OBJ_FALSE@ $(am__append_2) $(am__append_3) \ +@SINGLE_GC_OBJ_FALSE@ specific.c stubborn.c typd_mlc.c \ @SINGLE_GC_OBJ_FALSE@ $(am__append_4) $(am__append_5) \ -@SINGLE_GC_OBJ_FALSE@ $(am__append_6) $(am__append_7) +@SINGLE_GC_OBJ_FALSE@ $(am__append_6) $(am__append_7) \ +@SINGLE_GC_OBJ_FALSE@ $(am__append_8) $(am__append_9) @SINGLE_GC_OBJ_TRUE@libgc_la_SOURCES = extra/gc.c $(am__append_2) \ -@SINGLE_GC_OBJ_TRUE@ $(am__append_3) $(am__append_4) \ -@SINGLE_GC_OBJ_TRUE@ $(am__append_5) $(am__append_6) \ -@SINGLE_GC_OBJ_TRUE@ $(am__append_7) +@SINGLE_GC_OBJ_TRUE@ $(am__append_4) $(am__append_5) \ +@SINGLE_GC_OBJ_TRUE@ $(am__append_6) $(am__append_7) \ +@SINGLE_GC_OBJ_TRUE@ $(am__append_8) $(am__append_9) @NEED_ATOMIC_OPS_ASM_TRUE@nodist_libgc_la_SOURCES = libatomic_ops/src/atomic_ops_sysdeps.S @USE_INTERNAL_LIBATOMIC_OPS_TRUE@nodist_libgc_la_SOURCES = libatomic_ops/src/atomic_ops.c @@ -1026,13 +1042,15 @@ pkgconfig_DATA = bdw-gc.pc # linuxthread semaphore functions get linked: libgc_la_LIBADD = @addobjs@ $(THREADDLLIBS) $(UNWINDLIBS) $(ATOMIC_OPS_LIBS) libgc_la_DEPENDENCIES = @addobjs@ -libgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info 1:3:0 -no-undefined +libgc_la_LDFLAGS = $(extra_ldflags_libgc) -version-info $(LIBGC_VER_INFO) \ + -no-undefined + EXTRA_libgc_la_SOURCES = ia64_save_regs_in_stack.s sparc_mach_dep.S \ sparc_netbsd_mach_dep.s sparc_sunos4_mach_dep.s @CPLUSPLUS_TRUE@libgccpp_la_SOURCES = gc_cpp.cc @CPLUSPLUS_TRUE@libgccpp_la_LIBADD = ./libgc.la -@CPLUSPLUS_TRUE@libgccpp_la_LDFLAGS = -version-info 1:3:0 -no-undefined +@CPLUSPLUS_TRUE@libgccpp_la_LDFLAGS = -version-info $(LIBGCCPP_VER_INFO) -no-undefined # Misc # ---- @@ -1047,8 +1065,13 @@ AM_CXXFLAGS = @GC_CFLAGS@ #include/private/pthread_stop_world.h \ #include/gc_mark.h @addincludes@ @ASM_WITH_CPP_UNSUPPORTED_TRUE@ASM_CPP_OPTIONS = + +# Info (current:revision:age) for the Libtool versioning system. +# These numbers should be updated at most once just before the release, +# and, optionally, at most once during the development (after the release). +LIBCORD_VER_INFO = 4:1:3 libcord_la_LIBADD = $(top_builddir)/libgc.la -libcord_la_LDFLAGS = -version-info 1:3:0 -no-undefined +libcord_la_LDFLAGS = -version-info $(LIBCORD_VER_INFO) -no-undefined libcord_la_CPPFLAGS = $(AM_CPPFLAGS) libcord_la_SOURCES = \ cord/cordbscs.c \ @@ -1061,7 +1084,7 @@ cordtest_LDADD = $(top_builddir)/libgc.la $(top_builddir)/libcord.la # Common libs to _LDADD for all tests. test_ldadd = $(top_builddir)/libgc.la $(EXTRA_TEST_LIBS) gctest_SOURCES = tests/test.c -gctest_LDADD = $(test_ldadd) $(am__append_11) +gctest_LDADD = $(test_ldadd) $(am__append_13) gctest_DEPENDENCIES = $(top_builddir)/libgc.la leaktest_SOURCES = tests/leak_test.c leaktest_LDADD = $(test_ldadd) @@ -1105,48 +1128,47 @@ libstaticrootslib2_test_la_LDFLAGS = -version-info 1:3:0 -no-undefined \ @AVOID_CPP_LIB_TRUE@@CPLUSPLUS_TRUE@test_cpp_LDADD = gc_cpp.o $(test_ldadd) $(CXXLIBS) @ENABLE_DISCLAIM_TRUE@disclaim_test_SOURCES = tests/disclaim_test.c @ENABLE_DISCLAIM_TRUE@disclaim_test_LDADD = $(test_ldadd) \ -@ENABLE_DISCLAIM_TRUE@ $(am__append_20) +@ENABLE_DISCLAIM_TRUE@ $(am__append_22) @ENABLE_DISCLAIM_TRUE@disclaim_bench_SOURCES = tests/disclaim_bench.c @ENABLE_DISCLAIM_TRUE@disclaim_bench_LDADD = $(test_ldadd) # installed documentation -# -dist_pkgdata_DATA = \ - AUTHORS \ - README.md \ - doc/README.DGUX386 \ - doc/README.Mac \ - doc/README.OS2 \ - doc/README.amiga \ - doc/README.arm.cross \ - doc/README.autoconf \ - doc/README.cmake \ - doc/README.cords \ - doc/README.darwin \ - doc/README.environment \ - doc/README.ews4800 \ - doc/README.hp \ - doc/README.linux \ - doc/README.macros \ - doc/README.rs6000 \ - doc/README.sgi \ - doc/README.solaris2 \ - doc/README.symbian \ - doc/README.uts \ - doc/README.win32 \ - doc/README.win64 \ - doc/debugging.html \ - doc/finalization.html \ - doc/gc.man \ - doc/gcdescr.html \ - doc/gcinterface.html \ - doc/leak.html \ - doc/overview.html \ - doc/porting.html \ - doc/scale.html \ - doc/simple_example.html \ - doc/tree.html +@ENABLE_DOCS_TRUE@dist_doc_DATA = \ +@ENABLE_DOCS_TRUE@ AUTHORS \ +@ENABLE_DOCS_TRUE@ README.md \ +@ENABLE_DOCS_TRUE@ doc/README.DGUX386 \ +@ENABLE_DOCS_TRUE@ doc/README.Mac \ +@ENABLE_DOCS_TRUE@ doc/README.OS2 \ +@ENABLE_DOCS_TRUE@ doc/README.amiga \ +@ENABLE_DOCS_TRUE@ doc/README.arm.cross \ +@ENABLE_DOCS_TRUE@ doc/README.autoconf \ +@ENABLE_DOCS_TRUE@ doc/README.cmake \ +@ENABLE_DOCS_TRUE@ doc/README.cords \ +@ENABLE_DOCS_TRUE@ doc/README.darwin \ +@ENABLE_DOCS_TRUE@ doc/README.environment \ +@ENABLE_DOCS_TRUE@ doc/README.ews4800 \ +@ENABLE_DOCS_TRUE@ doc/README.hp \ +@ENABLE_DOCS_TRUE@ doc/README.linux \ +@ENABLE_DOCS_TRUE@ doc/README.macros \ +@ENABLE_DOCS_TRUE@ doc/README.rs6000 \ +@ENABLE_DOCS_TRUE@ doc/README.sgi \ +@ENABLE_DOCS_TRUE@ doc/README.solaris2 \ +@ENABLE_DOCS_TRUE@ doc/README.symbian \ +@ENABLE_DOCS_TRUE@ doc/README.uts \ +@ENABLE_DOCS_TRUE@ doc/README.win32 \ +@ENABLE_DOCS_TRUE@ doc/README.win64 \ +@ENABLE_DOCS_TRUE@ doc/debugging.html \ +@ENABLE_DOCS_TRUE@ doc/finalization.html \ +@ENABLE_DOCS_TRUE@ doc/gcdescr.html \ +@ENABLE_DOCS_TRUE@ doc/gcinterface.html \ +@ENABLE_DOCS_TRUE@ doc/leak.html \ +@ENABLE_DOCS_TRUE@ doc/overview.html \ +@ENABLE_DOCS_TRUE@ doc/porting.html \ +@ENABLE_DOCS_TRUE@ doc/scale.html \ +@ENABLE_DOCS_TRUE@ doc/simple_example.html \ +@ENABLE_DOCS_TRUE@ doc/tree.html +@ENABLE_DOCS_TRUE@dist_man3_MANS = doc/gc.man all: all-recursive .SUFFIXES: @@ -1615,27 +1637,68 @@ clean-libtool: distclean-libtool: -rm -f libtool config.lt -install-dist_pkgdataDATA: $(dist_pkgdata_DATA) +install-man3: $(dist_man3_MANS) @$(NORMAL_INSTALL) - @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + @list1='$(dist_man3_MANS)'; \ + list2=''; \ + test -n "$(man3dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man3dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.3[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ + done; } + +uninstall-man3: + @$(NORMAL_UNINSTALL) + @list='$(dist_man3_MANS)'; test -n "$(man3dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir) +install-dist_docDATA: $(dist_doc_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done -uninstall-dist_pkgdataDATA: +uninstall-dist_docDATA: @$(NORMAL_UNINSTALL) - @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ @@ -2141,6 +2204,7 @@ distdir: $(DISTFILES) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) + dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) @@ -2265,10 +2329,10 @@ check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-recursive -all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +all-am: Makefile $(LTLIBRARIES) $(MANS) $(DATA) $(HEADERS) installdirs: installdirs-recursive installdirs-am: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(pkgincludedir)"; do \ + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(pkgincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive @@ -2338,8 +2402,8 @@ info: info-recursive info-am: -install-data-am: install-dist_pkgdataDATA install-includeHEADERS \ - install-pkgconfigDATA install-pkgincludeHEADERS +install-data-am: install-dist_docDATA install-includeHEADERS \ + install-man install-pkgconfigDATA install-pkgincludeHEADERS install-dvi: install-dvi-recursive @@ -2355,7 +2419,7 @@ install-info: install-info-recursive install-info-am: -install-man: +install-man: install-man3 install-pdf: install-pdf-recursive @@ -2387,10 +2451,12 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-dist_pkgdataDATA uninstall-includeHEADERS \ - uninstall-libLTLIBRARIES uninstall-pkgconfigDATA \ +uninstall-am: uninstall-dist_docDATA uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES uninstall-man uninstall-pkgconfigDATA \ uninstall-pkgincludeHEADERS +uninstall-man: uninstall-man3 + .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ @@ -2403,19 +2469,19 @@ uninstall-am: uninstall-dist_pkgdataDATA uninstall-includeHEADERS \ distclean-hdr distclean-libtool distclean-tags distcleancheck \ distdir distuninstallcheck dvi dvi-am html html-am info \ info-am install install-am install-data install-data-am \ - install-dist_pkgdataDATA install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ + install-dist_docDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am \ install-includeHEADERS install-info install-info-am \ - install-libLTLIBRARIES install-man install-pdf install-pdf-am \ - install-pkgconfigDATA install-pkgincludeHEADERS install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs installdirs-am maintainer-clean \ + install-libLTLIBRARIES install-man install-man3 install-pdf \ + install-pdf-am install-pkgconfigDATA install-pkgincludeHEADERS \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ - uninstall-dist_pkgdataDATA uninstall-includeHEADERS \ - uninstall-libLTLIBRARIES uninstall-pkgconfigDATA \ - uninstall-pkgincludeHEADERS + uninstall-dist_docDATA uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES uninstall-man uninstall-man3 \ + uninstall-pkgconfigDATA uninstall-pkgincludeHEADERS .PRECIOUS: Makefile @@ -2432,9 +2498,6 @@ uninstall-am: uninstall-dist_pkgdataDATA uninstall-includeHEADERS \ .S.s: if $(CPP) $< >$@ ; then :; else rm -f $@; fi -# Putting these at the top causes cord to be built first, and not find libgc.a -# on HP/UX. There may be a better fix. - # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/src/bdwgc/NT_MAKEFILE b/src/bdwgc/NT_MAKEFILE index 3cf3be985..a1055b7a9 100644 --- a/src/bdwgc/NT_MAKEFILE +++ b/src/bdwgc/NT_MAKEFILE @@ -1,61 +1,135 @@ -# Makefile for Windows NT. Assumes Microsoft compiler, and a single thread. -# Use "nmake nodebug=1 all" for optimized versions of library, gctest and editor. +# Makefile for Windows NT. Assumes Microsoft compiler. +# Should be invoked as "nmake -f NT_MAKEFILE []"; the optional arguments +# are: "cpu=AMD64" - to target x64, "cpu=i386" - to target x86, +# "make_as_lib=1" - to build it as a static library, "nodebug=1" - to produce +# the release variant of the library, "nothreads=1" - to build the library and +# the tests without threads support. -MY_CPU=X86 -CPU=$(MY_CPU) -!include +cc = cl +link = link +rc = rc + +!IF !DEFINED(CPU) || "$(CPU)" == "" +CPU = $(PROCESSOR_ARCHITECTURE) +!ENDIF +!IF "$(CPU)" == "I386" || "$(CPU)" == "X86" || "$(CPU)" == "x86" +CPU = i386 +!ELSEIF "$(CPU)" == "X64" || "$(CPU)" == "x64" || "$(CPU)" == "amd64" +CPU = AMD64 +!ENDIF + +!IF !DEFINED(NMAKE_WINVER) +NMAKE_WINVER = 0x0600 +!ENDIF + +cflags = $(cflags) -c -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -GS -D_WINNT -W4 +!IF "$(CPU)" == "i386" +cflags = $(cflags) -D_X86_=1 -DWIN32 -D_WIN32 +!ELSEIF "$(CPU)" == "AMD64" +cflags = $(cflags) -D_AMD64_=1 -DWIN64 -D_WIN64 -DWIN32 -D_WIN32 +!ENDIF +cflags = $(cflags) -D_WIN32_WINNT=$(NMAKE_WINVER) -DWINVER=$(NMAKE_WINVER) + +!IFDEF NODEBUG +cvarsmt = -D_MT -MT +cdebug = -Ox -DNDEBUG +rcvars = -DWIN32 -D_WIN32 -DWINVER=$(NMAKE_WINVER) +ldebug = /RELEASE +!ELSE +cvarsmt = -D_MT -MTd +cdebug = -Zi -Od -DDEBUG +rcvars = -DWIN32 -D_WIN32 -DWINVER=$(NMAKE_WINVER) -DDEBUG -D_DEBUG +ldebug = /DEBUG /DEBUGTYPE:cv +!ENDIF + +!IF "$(CPU)" == "i386" +CVTRES_CPU=X86 +!ELSEIF "$(CPU)" == "AMD64" +CVTRES_CPU=X64 +!ENDIF + +!IFNDEF NOTHREADS +CFLAGS_MT=$(cvarsmt) -DGC_THREADS -DTHREAD_LOCAL_ALLOC -DPARALLEL_MARK +!ENDIF + +!IFDEF MAKE_AS_LIB +CFLAGS_GCDLL=-DGC_NOT_DLL +GC_LIB=gc.lib +LINK_GC=lib /out:$(GC_LIB) +!ELSE +CFLAGS_GCDLL=-DGC_DLL +!IF "$(CPU)" == "AMD64" +GC_DLL=gc64.dll +GC_LIB=gc64_dll.lib +!ELSE +GC_DLL=gc.dll +GC_LIB=gc_dll.lib +!ENDIF +LINK_DLL_FLAGS=kernel32.lib user32.lib /subsystem:windows /dll \ + /INCREMENTAL:NO /pdb:"gc.pdb" /out:$(GC_DLL) /implib:$(GC_LIB) +LINK_GC=$(link) $(ldebug) $(LINK_DLL_FLAGS) +!ENDIF + +CFLAGS_SPECIFIC=$(CFLAGS_GCDLL) $(CFLAGS_MT) # Make sure that .cc is not viewed as a suffix. It is for VC++2005, but # not earlier versions. We can deal with either, but not inconsistency. .SUFFIXES: .SUFFIXES: .obj .cpp .c -OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj fnlz_mlc.obj malloc.obj stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj extra\msvc_dbg.obj +# Atomic_ops installation directory. For win32, the source directory +# should do, since we only need the headers. +# We assume this was manually unpacked. +AO_SRC_DIR=libatomic_ops/src +AO_INCLUDE_DIR=$(AO_SRC_DIR) + +OBJS= misc.obj win32_threads.obj alloc.obj reclaim.obj allchblk.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj fnlz_mlc.obj malloc.obj stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj extra\msvc_dbg.obj thread_local_alloc.obj all: gctest.exe cord\de.exe test_cpp.exe .c.obj: - $(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -D_CRT_SECURE_NO_DEPRECATE $*.c /Fo$*.obj + $(cc) $(cdebug) $(cflags) $(CFLAGS_SPECIFIC) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DCORD_NOT_DLL -D_CRT_SECURE_NO_DEPRECATE $*.c /Fo$*.obj /wd4100 /wd4127 /wd4701 +# Disable crt security warnings, since unfortunately they warn about all sorts +# of safe uses of strncpy. It would be nice to leave the rest enabled. .cpp.obj: - $(cc) $(cdebug) $(cflags) $(cvars) -Iinclude -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj + $(cc) $(cdebug) $(cflags) $(CFLAGS_SPECIFIC) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj $(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\gc_disclaim.h include\private\msvc_dbg.h -gc.lib: $(OBJS) - lib /MACHINE:i386 /out:gc.lib $(OBJS) -# The original NT SDK used lib32 instead of lib +$(GC_LIB): $(OBJS) + $(LINK_GC) /MACHINE:$(CPU) $(OBJS) -gctest.exe: tests\test.obj gc.lib -# The following works for win32 debugging. For win32s debugging use debugtype:coff -# and add mapsympe line. -# This produces a "GUI" applications that opens no windows and writes to the log file -# "gctest.gc.log". This is done to make the result runnable under win32s. - $(link) -debug -debugtype:cv $(guiflags) -stack:131072 -out:$*.exe tests\test.obj $(guilibs) gc.lib +gctest.exe: $(GC_LIB) tests\test.obj + $(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) user32.lib -out:$*.exe tests\test.obj $(GC_LIB) # mapsympe -n -o gctest.sym gctest.exe +# This produces a GUI app that opens no window and writes to gctest.gc.log. -cord\de_win.rbj: cord\de_win.res - cvtres /MACHINE:$(MY_CPU) /OUT:cord\de_win.rbj cord\de_win.res +cord\tests\de_win.rbj: cord\tests\de_win.res + cvtres /MACHINE:$(CVTRES_CPU) /OUT:cord\tests\de_win.rbj cord\tests\de_win.res cord\tests\de.obj cord\tests\de_win.obj: include\cord.h include\cord_pos.h cord\tests\de_win.h cord\tests\de_cmds.h -cord\de_win.res: cord\tests\de_win.rc cord\tests\de_win.h cord\tests\de_cmds.h - $(rc) $(rcvars) -r -fo cord\de_win.res cord\tests\de_win.rc +cord\tests\de_win.res: cord\tests\de_win.rc cord\tests\de_win.h cord\tests\de_cmds.h + $(rc) $(rcvars) -r -fo cord\tests\de_win.res cord\tests\de_win.rc -# Cord/de is a real win32 gui application. -cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj cord\tests\de_win.obj cord\de_win.rbj gc.lib - $(link) -debug -debugtype:cv $(guiflags) -stack:16384 -out:cord\de.exe cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj cord\tests\de_win.obj cord\de_win.rbj gc.lib $(guilibs) +# Cord/de is a real win32 GUI app. +cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj cord\tests\de_win.obj cord\tests\de_win.rbj $(GC_LIB) + $(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) -out:cord\de.exe cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj cord\tests\de_win.obj cord\tests\de_win.rbj $(GC_LIB) gdi32.lib user32.lib -gc_cpp.obj: include\gc_cpp.h include\gc.h - -gc_cpp.cpp: gc_cpp.cc -# copy gc_cpp.cc gc_cpp.cpp +gc_cpp.obj: gc_cpp.cc include\gc_cpp.h include\gc.h test_cpp.cpp: tests\test_cpp.cc copy tests\test_cpp.cc test_cpp.cpp # This generates the C++ test executable. The executable expects # a single numeric argument, which is the number of iterations. -# The output appears in the file "test_cpp.gc.log". -test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib - $(link) -debug -debugtype:cv $(guiflags) -stack:16384 -out:test_cpp.exe test_cpp.obj gc.lib $(guilibs) +# The output appears in test_cpp.gc.log file. +test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h $(GC_LIB) + $(link) /MACHINE:$(CPU) /INCREMENTAL:NO $(ldebug) $(lflags) user32.lib -out:test_cpp.exe test_cpp.obj $(GC_LIB) + +$(AO_SRC_DIR): + tar xvfz $(AO_SRC_DIR).tar.gz + +clean: + del *.exe *.log *.obj *.pdb cord\*.exe cord\*.exp cord\*.lib cord\*.obj cord\*.pdb cord\tests\*.rbj cord\tests\*.res cord\tests\*.obj extra\*.obj gc*.lib gc*.dll gc*.exp test_cpp.cpp tests\*.obj 2> nul diff --git a/src/bdwgc/NT_STATIC_THREADS_MAKEFILE b/src/bdwgc/NT_STATIC_THREADS_MAKEFILE deleted file mode 100644 index 8774eab12..000000000 --- a/src/bdwgc/NT_STATIC_THREADS_MAKEFILE +++ /dev/null @@ -1,71 +0,0 @@ -# Makefile for Windows NT. Assumes Microsoft compiler. -# Use "nmake nodebug=1 all" for optimized versions of library, gctest and editor. - -MY_CPU=X86 -CPU=$(MY_CPU) -!include - -# Make sure that .cc is not viewed as a suffix. It is for VC++2005, but -# not earlier versions. We can deal with either, but not inconsistency. -.SUFFIXES: -.SUFFIXES: .obj .cpp .c - -# Atomic_ops installation directory. For win32, the source directory -# should do, since we only need the headers. -# We assume this was manually unpacked, since I'm not sure there is -# a Windows standard command line tool to do this. -AO_SRC_DIR=libatomic_ops/src -AO_INCLUDE_DIR=$(AO_SRC_DIR) - -OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj fnlz_mlc.obj malloc.obj stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj win32_threads.obj extra\msvc_dbg.obj thread_local_alloc.obj - -all: gctest.exe cord\de.exe test_cpp.exe - -.c.obj: - $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -DGC_THREADS -DTHREAD_LOCAL_ALLOC -DPARALLEL_MARK -D_CRT_SECURE_NO_DEPRECATE $*.c /Fo$*.obj - -.cpp.obj: - $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -DGC_THREADS -DTHREAD_LOCAL_ALLOC -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj - -$(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\gc_disclaim.h include\private\msvc_dbg.h - -gc.lib: $(OBJS) - lib /MACHINE:i386 /out:gc.lib $(OBJS) -# The original NT SDK used lib32 instead of lib - -gctest.exe: tests\test.obj gc.lib -# The following works for win32 debugging. For win32s debugging use debugtype:coff -# and add mapsympe line. -# This produces a "GUI" applications that opens no windows and writes to the log file -# "gctest.gc.log". This is done to make the result runnable under win32s. - $(link) -debug -debugtype:cv $(guiflags) -stack:262144 -out:$*.exe tests\test.obj $(guilibs) gc.lib -# mapsympe -n -o gctest.sym gctest.exe - -cord\de_win.rbj: cord\de_win.res - cvtres /MACHINE:$(MY_CPU) /OUT:cord\de_win.rbj cord\de_win.res - -cord\tests\de.obj cord\tests\de_win.obj: include\cord.h include\cord_pos.h cord\tests\de_win.h cord\tests\de_cmds.h - -cord\de_win.res: cord\tests\de_win.rc cord\tests\de_win.h cord\tests\de_cmds.h - $(rc) $(rcvars) -r -fo cord\de_win.res cord\tests\de_win.rc - -# Cord/de is a real win32 gui application. -cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj cord\tests\de_win.obj cord\de_win.rbj gc.lib - $(link) -debug -debugtype:cv $(guiflags) -stack:16384 -out:cord\de.exe cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj cord\tests\de_win.obj cord\de_win.rbj gc.lib $(guilibs) - -gc_cpp.obj: include\gc_cpp.h include\gc.h - -gc_cpp.cpp: gc_cpp.cc -# copy gc_cpp.cc gc_cpp.cpp - -test_cpp.cpp: tests\test_cpp.cc - copy tests\test_cpp.cc test_cpp.cpp - -# This generates the C++ test executable. The executable expects -# a single numeric argument, which is the number of iterations. -# The output appears in the file "test_cpp.gc.log". -test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib - $(link) -debug -debugtype:cv $(guiflags) -stack:16384 -out:test_cpp.exe test_cpp.obj gc.lib $(guilibs) - -AO_SCR_DIR: - tar xvfz $(AO_SRC_DIR).tar.gz; diff --git a/src/bdwgc/NT_X64_STATIC_THREADS_MAKEFILE b/src/bdwgc/NT_X64_STATIC_THREADS_MAKEFILE deleted file mode 100644 index 3ccb75d45..000000000 --- a/src/bdwgc/NT_X64_STATIC_THREADS_MAKEFILE +++ /dev/null @@ -1,70 +0,0 @@ -# Makefile for Windows NT. Assumes Microsoft compiler. -# Use "nmake nodebug=1 all" for optimized versions of library, gctest and editor. - -MY_CPU=AMD64 -CPU=$(MY_CPU) -!include - -# Make sure that .cc is not viewed as a suffix. It is for VC++2005, but -# not earlier versions. We can deal with either, but not inconsistency. -.SUFFIXES: -.SUFFIXES: .obj .cpp .c - -# Atomic_ops installation directory. For win32, the source directory -# should do, since we only need the headers. -# We assume this was manually unpacked, since I'm not sure there is -# a Windows standard command line tool to do this. -AO_SRC_DIR=libatomic_ops/src -AO_INCLUDE_DIR=$(AO_SRC_DIR) - -OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj fnlz_mlc.obj malloc.obj stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj win32_threads.obj extra\msvc_dbg.obj thread_local_alloc.obj - -all: gctest.exe cord\de.exe test_cpp.exe - -.c.obj: - $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -DGC_THREADS -DTHREAD_LOCAL_ALLOC -D_CRT_SECURE_NO_DEPRECATE $*.c /Fo$*.obj /wd4701 -# Disable "may not be initialized" warnings. They're too approximate. -# Disable crt security warnings, since unfortunately they warn about all sorts -# of safe uses of strncpy. It would be nice to leave the rest enabled. - -.cpp.obj: - $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_NOT_DLL -DGC_THREADS -DTHREAD_LOCAL_ALLOC -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj - -$(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\gc_disclaim.h include\private\msvc_dbg.h - -gc.lib: $(OBJS) - lib /MACHINE:X64 /out:gc.lib $(OBJS) - -gctest.exe: tests\test.obj gc.lib -# This produces a "GUI" applications that opens no windows and writes to -# the log file "gctest.gc.log". - $(link) $(ldebug) $(guiflags) -out:$*.exe tests\test.obj $(guilibs) gc.lib - -cord\de_win.rbj: cord\de_win.res - cvtres /MACHINE:$(MY_CPU) /OUT:cord\de_win.rbj cord\de_win.res - -cord\tests\de.obj cord\tests\de_win.obj: include\cord.h include\cord_pos.h cord\tests\de_win.h cord\tests\de_cmds.h - -cord\de_win.res: cord\tests\de_win.rc cord\tests\de_win.h cord\tests\de_cmds.h - $(rc) $(rcvars) -r -fo cord\de_win.res cord\tests\de_win.rc - -# Cord/de is a real win32 gui application. -cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj cord\tests\de_win.obj cord\de_win.rbj gc.lib - $(link) $(ldebug) $(guiflags) -stack:16384 -out:cord\de.exe cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj cord\tests\de_win.obj cord\de_win.rbj gc.lib $(guilibs) - -gc_cpp.obj: include\gc_cpp.h include\gc.h - -gc_cpp.cpp: gc_cpp.cc -# copy gc_cpp.cc gc_cpp.cpp - -test_cpp.cpp: tests\test_cpp.cc - copy tests\test_cpp.cc test_cpp.cpp - -# This generates the C++ test executable. The executable expects -# a single numeric argument, which is the number of iterations. -# The output appears in the file "test_cpp.gc.log". -test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib - $(link) $(ldebug) $(guiflags) -stack:16384 -out:test_cpp.exe test_cpp.obj gc.lib $(guilibs) - -AO_SCR_DIR: - tar xvfz $(AO_SRC_DIR).tar.gz; diff --git a/src/bdwgc/NT_X64_THREADS_MAKEFILE b/src/bdwgc/NT_X64_THREADS_MAKEFILE deleted file mode 100644 index b8495d087..000000000 --- a/src/bdwgc/NT_X64_THREADS_MAKEFILE +++ /dev/null @@ -1,87 +0,0 @@ -# Makefile for Windows NT. Assumes Microsoft compiler. -# modified 2007 August by Friedrich Dominicus: -# - copied from NT_X64_STATIC_THREADS_MAKEFILES -# - checked agaist gc.mak (NT_THREADS_MAKEFILE) -# - added changes to integrate the tools -# - currently just with debug information -# problems can be sent to -# frido at q-software-solutions.de -# -# or the mailing list - - -MY_CPU=AMD64 -CPU=$(MY_CPU) -!include - -# Make sure that .cc is not viewed as a suffix. It is for VC++2005, but # not earlier versions. We can deal with either, but not inconsistency. -.SUFFIXES: -.SUFFIXES: .obj .cpp .c - -# Atomic_ops installation directory. For win32, the source directory -# should do, since we only need the headers. -# We assume this was manually unpacked, since I'm not sure there is -# a Windows standard command line tool to do this. -AO_SRC_DIR=libatomic_ops/src -AO_INCLUDE_DIR=$(AO_SRC_DIR) - -OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj obj_map.obj blacklst.obj finalize.obj new_hblk.obj dbg_mlc.obj fnlz_mlc.obj malloc.obj stubborn.obj dyn_load.obj typd_mlc.obj ptr_chck.obj gc_cpp.obj mallocx.obj win32_threads.obj extra\msvc_dbg.obj thread_local_alloc.obj - -all: gc64.dll gctest.exe cord\de.exe test_cpp.exe - -.c.obj: - $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_DLL -DGC_THREADS -D_CRT_SECURE_NO_DEPRECATE $*.c /Fo$*.obj /wd4701 -# Disable "may not be initialized" warnings. They're too approximate. -# Disable crt security warnings, since unfortunately they warn about all sorts # of safe uses of strncpy. It would be nice to leave the rest enabled. - -.cpp.obj: - $(cc) $(cdebug) $(cflags) $(cvarsmt) -Iinclude -I$(AO_INCLUDE_DIR) -DALL_INTERIOR_POINTERS -DGC_DLL -DGC_THREADS -D_CRT_SECURE_NO_DEPRECATE $*.cpp /Fo$*.obj - -$(OBJS) tests\test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h include\private\gc_locks.h include\private\gc_pmark.h include\gc_mark.h include\gc_disclaim.h include\private\msvc_dbg.h - - -LINK64=link.exe -LINK64_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib \ -shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo \ -/subsystem:windows /dll /incremental:no /pdb:"gc.pdb" /machine:X64 /out:"gc64.dll" \ -/implib:"gc64_dll.lib" - -gc64.dll : $(OBJS) - $(LINK64) $(ldebug) $(LINK64_FLAGS) $(OBJS) - - -gctest.exe: tests\test.obj gc64_dll.lib -# This produces a "GUI" applications that opens no windows and writes to -# the log file "gctest.gc.log". - $(link) $(ldebug) $(guiflags) -out:$*.exe tests\test.obj $(guilibs) gc64_dll.lib - -cord\de_win.rbj: cord\de_win.res - cvtres /MACHINE:$(MY_CPU) /OUT:cord\de_win.rbj cord\de_win.res - -cord\tests\de.obj cord\tests\de_win.obj: include\cord.h include\cord_pos.h cord\tests\de_win.h cord\tests\de_cmds.h - -cord\de_win.res: cord\tests\de_win.rc cord\tests\de_win.h cord\tests\de_cmds.h - $(rc) $(rcvars) -r -fo cord\de_win.res cord\tests\de_win.rc - -# Cord/de is a real win32 gui application. -cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj cord\tests\de_win.obj cord\de_win.rbj gc64_dll.lib - $(link) $(ldebug) $(guiflags) -stack:16384 -out:cord\de.exe cord\cordbscs.obj cord\cordxtra.obj cord\tests\de.obj cord\tests\de_win.obj cord\de_win.rbj gc64_dll.lib $(guilibs) - -gc_cpp.obj: include\gc_cpp.h include\gc.h - -gc_cpp.cpp: gc_cpp.cc -# copy gc_cpp.cc gc_cpp.cpp - -test_cpp.cpp: tests\test_cpp.cc - copy tests\test_cpp.cc test_cpp.cpp - -# This generates the C++ test executable. The executable expects # a single numeric argument, which is the number of iterations. -# The output appears in the file "test_cpp.gc.log". -test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc64_dll.lib - $(link) $(ldebug) $(guiflags) -stack:16384 -out:test_cpp.exe test_cpp.obj gc64_dll.lib $(guilibs) - -AO_SCR_DIR: - tar xvfz $(AO_SRC_DIR).tar.gz; - -clean: - del *.obj gc64_dll.lib gc64.dll diff --git a/src/bdwgc/PCR-Makefile b/src/bdwgc/PCR-Makefile index ff0578085..32f6321d8 100644 --- a/src/bdwgc/PCR-Makefile +++ b/src/bdwgc/PCR-Makefile @@ -32,9 +32,9 @@ LDFLAGS = $(CONFIG_LDFLAGS) # Fix to point to local pcr installation directory. PCRDIR= .. -COBJ= alloc.o reclaim.o allchblk.o misc.o os_dep.o mark_rts.o headers.o mark.o obj_map.o pcr_interface.o blacklst.o finalize.o new_hblk.o real_malloc.o dyn_load.o dbg_mlc.o fnlz_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o typd_mlc.o ptr_chck.o mallocx.o +COBJ= alloc.o reclaim.o allchblk.o misc.o os_dep.o mark_rts.o headers.o mark.o obj_map.o pcr_interface.o blacklst.o finalize.o new_hblk.o real_malloc.o dyn_load.o dbg_mlc.o fnlz_mlc.o malloc.o stubborn.o checksums.o typd_mlc.o ptr_chck.o mallocx.o -CSRC= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c fnlz_mlc.c malloc.c stubborn.c checksums.c solaris_threads.c typd_mlc.c ptr_chck.c mallocx.c +CSRC= reclaim.c allchblk.c misc.c alloc.c mach_dep.c os_dep.c mark_rts.c headers.c mark.c obj_map.c pcr_interface.c blacklst.c finalize.c new_hblk.c real_malloc.c dyn_load.c dbg_mlc.c fnlz_mlc.c malloc.c stubborn.c checksums.c typd_mlc.c ptr_chck.c mallocx.c SHELL= /bin/sh diff --git a/src/bdwgc/README.QUICK b/src/bdwgc/README.QUICK index e33ec019d..0bb9c985f 100644 --- a/src/bdwgc/README.QUICK +++ b/src/bdwgc/README.QUICK @@ -2,6 +2,7 @@ Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. Copyright (c) 1999-2001 by Hewlett-Packard. All rights reserved. +Copyright (c) 2009-2018 Ivan Maidanski THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -26,10 +27,8 @@ For the version number, see README.md or include/gc_version.h files. INSTALLATION: Under UN*X, Linux: -Alternative 1 (the old way): type "make test" in this directory. - Link against gc.a. With the most recent GC distributions - you may have to type "make -f Makefile.direct test" or - copy Makefile.direct to Makefile first. +Alternative 1 (the old way): type "make -f Makefile.direct check". + Link against gc.a. Alternative 2 (the new way): type "./configure --prefix=; make; make check; make install". @@ -48,7 +47,7 @@ as described in doc/README.macros, or possibly use --enable-threads=posix when running the configure script. If you wish to use the cord (structured string) library with the stand-alone -Makefile.direct, type "make cords", after copying to "Makefile". +Makefile.direct, type "make -f Makefile.direct cords". (This requires an ANSI C compiler. You may need to redefine CC in the Makefile. The CORD_printf implementation in cordprnt.c is known to be less than perfectly portable. The rest of the diff --git a/src/bdwgc/README.md b/src/bdwgc/README.md index b2301c76e..c8e518354 100644 --- a/src/bdwgc/README.md +++ b/src/bdwgc/README.md @@ -1,11 +1,17 @@ # Boehm-Demers-Weiser Garbage Collector -This is version 7.5.0 (next release development) of a conservative garbage +This is version 7.6.8 of a conservative garbage collector for C and C++. -You might find a more recent version -[here](http://www.hboehm.info/gc/), or -[here](https://github.com/ivmai/bdwgc). + +## Download + +You might find a more recent/stable version on the +[Download](https://github.com/ivmai/bdwgc/wiki/Download) page, or +[BDWGC site](http://www.hboehm.info/gc/). + +Also, the latest bug fixes and new features are available in the +[development repository](https://github.com/ivmai/bdwgc). ## Overview @@ -63,7 +69,7 @@ collector. (See doc/README.cords and H.-J. Boehm, R. Atkinson, and M. Plass, in Xerox Cedar, or the "rope" package in the SGI STL or the g++ distribution.) Further collector documentation can be found -[here](http://www.hboehm.info/gc/). +in [overview.html](doc/overview.html). ## General Description @@ -174,14 +180,17 @@ libatomic_ops source repository as well) could look like: git clone git://github.com/ivmai/bdwgc.git cd bdwgc git clone git://github.com/ivmai/libatomic_ops.git - autoreconf -vif - automake --add-missing + ./autogen.sh ./configure - make + make -j make check +If you are getting "syntax error near unexpected token ATOMIC_OPS" during +configure execution, this means pkg.m4 cannot be found, most probably +you should run `pkg-config` once before running `./autogen.sh` (autoreconf). + Below we focus on the collector build using classic makefile. -For the Makefile.direct-based process, typing `make test` instead of `make` +For the Makefile.direct-based process, typing `make check` instead of `make` will automatically build the collector and then run `setjmp_test` and `gctest`. `Setjmp_test` will give you information about configuring the collector, which is useful primarily if you have a machine that's not already supported. Gctest is @@ -453,7 +462,7 @@ equivalents. (`GC_REGISTER_FINALIZER` is necessary, since pointers to objects with debugging information are really pointers to a displacement of 16 bytes form the object beginning, and some translation is necessary when finalization routines are invoked. For details, about what's stored -in the header, see the definition of the type oh in debug_malloc.c) +in the header, see the definition of the type oh in dbg_mlc.c file.) ## Incremental/Generational Collection @@ -534,9 +543,30 @@ per MB of accessible memory that needs to be scanned and processor. Your mileage may vary.) The incremental/generational collection facility may help in some cases. -Please address bug reports [here](mailto:bdwgc@lists.opendylan.org). -If you are contemplating a major addition, you might also send mail to ask -whether it's already been done (or whether we tried and discarded it). + +## Feedback, Contribution, Questions and Notifications + +Please address bug reports and new feature ideas to +[GitHub issues](https://github.com/ivmai/bdwgc/issues). Before the +submission please check that it has not been done yet by someone else. + +If you want to contribute, submit +a [pull request](https://github.com/ivmai/bdwgc/pulls) to GitHub. + +If you need help, use +[Stack Overflow](https://stackoverflow.com/questions/tagged/boehm-gc). +Older technical discussions are available in `bdwgc` mailing list archive - it +can be downloaded as a +[compressed file](https://github.com/ivmai/bdwgc/files/1038163/bdwgc-mailing-list-archive-2017_04.tar.gz) +or browsed at [Narkive](http://bdwgc.opendylan.narkive.com). + +To get new release announcements, subscribe to +[RSS feed](https://github.com/ivmai/bdwgc/releases.atom). +(To receive the notifications by email, a 3rd-party free service like +[IFTTT RSS Feed](https://ifttt.com/feed) can be setup.) +To be notified on all issues, please +[watch](https://github.com/ivmai/bdwgc/watchers) the project on +GitHub. ## Copyright & Warranty @@ -545,21 +575,31 @@ whether it's already been done (or whether we tried and discarded it). * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. * Copyright (c) 1999-2011 by Hewlett-Packard Development Company. + * Copyright (c) 2008-2018 Ivan Maidanski -The file linux_threads.c is also +The files pthread_stop_world.c, pthread_support.c and some others are also * Copyright (c) 1998 by Fergus Henderson. All rights reserved. -The files Makefile.am, and configure.in are +The file gc.h is also -* Copyright (c) 2001 by Red Hat Inc. All rights reserved. + * Copyright (c) 2007 Free Software Foundation, Inc + +The files Makefile.am and configure.ac are + + * Copyright (c) 2001 by Red Hat Inc. All rights reserved. + +The files msvc_dbg.c and msvc_dbg.h are + + * Copyright (c) 2004-2005 Andrei Polushin + +The file initsecondarythread.c is + + * Copyright (c) 2011 Ludovic Courtes Several files supporting GNU-style builds are copyrighted by the Free Software Foundation, and carry a different license from that given -below. The files included in the libatomic_ops distribution (included -here) use either the license below, or a similar MIT-style license, -or, for some files not actually used by the garbage-collector library, the -GPL. +below. THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -575,8 +615,3 @@ slightly different licenses, though they are all similar in spirit. A few are GPL'ed, but with an exception that should cover all uses in the collector. (If you are concerned about such things, I recommend you look at the notice in config.guess or ltmain.sh.) - -The atomic_ops library contains some code that is covered by the GNU General -Public License, but is not needed by, nor linked into the collector library. -It is included here only because the atomic_ops distribution is, for -simplicity, included in its entirety. diff --git a/src/bdwgc/SMakefile.amiga b/src/bdwgc/SMakefile.amiga index 229f184f7..6400a9928 100644 --- a/src/bdwgc/SMakefile.amiga +++ b/src/bdwgc/SMakefile.amiga @@ -1,6 +1,6 @@ # Rewritten smakefile for amiga / sas/c. -Kjetil M. -# Dont use the cord-package if you define parm=both or parm=reg. +# Don't use the cord-package if you define parm=both or parm=reg. #----------------TOOLS-------------------------------- @@ -32,7 +32,7 @@ DEFINE __USE_SYSBASE SOPT= $(OPT) $(IGNORE) \ DEFINE AMIGA_SKIP_SEG \ -DEFINE ATOMIC_UNCOLLECTABLE \ +DEFINE GC_ATOMIC_UNCOLLECTABLE \ DEFINE GC_AMIGA_FASTALLOC \ DEFINE GC_AMIGA_RETRY \ DEFINE GC_AMIGA_PRINTSTATS \ diff --git a/src/bdwgc/TODO b/src/bdwgc/TODO deleted file mode 100644 index aea7e3fef..000000000 --- a/src/bdwgc/TODO +++ /dev/null @@ -1,93 +0,0 @@ -== TODO tasks == - -tests/CMakeLists.txt: Add more executables (see tests.am). - -Use C++0x ATM (atomic memory operations) if available (either from the -compiler runtime, provided it is reliable, or from the future libatomic_ops). - -Add a test for libatomic_ops minimal version required (at compile time). - -windows-untested: Remove if CMake can generate MS Visual Studio 6.0, 7.0, 8.0 -project files. - -BCC_MAKEFILE: Remove if CMake can generate Makefile for this compiler. -(Same for WCC_MAKEFILE, OS2_MAKEFILE, NT_MAKEFILE, NT_STATIC_THREADS_MAKEFILE, -NT_X64_STATIC_THREADS_MAKEFILE, NT_X64_THREADS_MAKEFILE, digimars.mak, -gc.mak.) - -BCC_MAKEFILE, EMX_MAKEFILE, OS2_MAKEFILE, PCR-Makefile, WCC_MAKEFILE, -SMakefile.amiga, digimars.mak: move to "build" folder. - -Do type-punning via union (instead of pointer type cast) to enable safe -'-fstrict-aliasing' compiler optimization option. - -Support CAN_HANDLE_FORK if USE_WINALLOC for Cygwin. - -Use madvise() on Unix/Cygwin. - -Use Linux VM pressure notifications to force GC and unmapping. - -Filter overlaps in GC_add_roots for Unix (same as for Win32). - -Do not resume parallel markers if only 1 core is active at GC mark start. - -Enable GC_set_handle_fork(1) for Darwin with GC_dirty_maintained on (both -single and multi-threaded modes). - -Add more fields to GC_prof_stats_s (potential candidates are: -requested_heapsize, max_large_allocd_bytes, large_allocd_bytes, bytes_dropped, -bytes_finalized, bytes_freed, finalizer_bytes_freed, composite_in_use, -atomic_in_use, GC_n_heap_sects, GC_n_memory, GC_black_list_spacing, -GC_root_size, GC_max_root_size, n_root_sets, GC_total_stacksize, -GC_collect_at_heapsize, GC_fail_count, GC_mark_stack_size, last_fo_entries, -last_bytes_finalized, last_finalizer_notification_no, GC_dl_entries, -GC_old_dl_entries, GC_used_heap_size_after_full, GC_total_stack_black_listed, -signed_log_dl_table_size, GC_n_rescuing_pages, signed_log_fo_table_size, -GC_excl_table_entries, GC_stack_last_cleared, GC_bytes_allocd_at_reset, -GC_n_heap_bases, registered_threads_cnt, GC_max_thread_index, GC_block_count, -GC_unlocked_count, GC_hdr_cache_hits, GC_hdr_cache_misses, GC_spin_count). - -Support musl libc (on sabotage linux). - -== FIXME tasks == - -Solaris + GCC: make check fails with the message: -libc.so.1: gctest: fatal: libgcc_s.so.1: open failed: No such file or directory - -Solaris/x86[_64]: gctest fails if PROC_VDB. - -Sun C++ 5.11: test_cpp.cc:237: Error: Too few arguments in call to -"operator delete(void*, GCPlacement, extern "C" void(*)(void*,void*), void*)". - -Darwin/x86_64: deadlock might occur between: -dlclose() -> GC_dyld_image_remove() -> GC_lock() and -GC_inner_start_routine()+LOCK -> dyld_stub_binder_(). - -HP-UX 11.00 with the vendor cc fails: -Perhaps GC_push_regs was configured incorrectly? FAIL: gctest. - -Linux/mips64el (N32): threadleaktest crashes once every 3-4 runs (SIGSEGV in -GC_delete_gc_thread(t=0) called from GC_pthread_join) if configured with ---disable-shared. - -FreeBSD 9.0/x86_64 (gcc-4.2.1-20070831): gctest segfaults sometimes in -GC_typed_mark_proc if configured with --enable-threads=pthreads. - -OpenBSD 5.1/i386: leaktest fails rarely (unless logging redirected to file): -cannot write to stderr from GC_gcollect invoked from 'atexit' hook. - -NetBSD 5.1/x86: threadkey_test hangs sometimes. - -Cygwin: subthread_create: exception STATUS_ACCESS_VIOLATION. - -Cygwin: gctest: assertion failure at UNLOCK in GC_fork_parent_proc. - -Mingw-w32: gctest: "SuspendThread failed" sometimes occurs (if -GC_DLL+GC_THREADS+GC_ASSERTIONS). - -Mingw: gctest (compiled with PARALLEL_MARK): launched in gdb with breakpoint -at GC_mark_local, after several breakpoint hits, crashes with the messages -"Caught ACCESS_VIOLATION in marker; memory mapping disappeared" and -"Tried to start parallel mark in bad state", or enters deadlock. - -Mingw: test_cpp: crashes at some iteration if big argument (e.g., 1000) given. diff --git a/src/bdwgc/WCC_MAKEFILE b/src/bdwgc/WCC_MAKEFILE index 0257f7158..f5b6a620f 100644 --- a/src/bdwgc/WCC_MAKEFILE +++ b/src/bdwgc/WCC_MAKEFILE @@ -1,7 +1,7 @@ # Makefile for Watcom C/C++ 10.5, 10.6, 11.0 on NT, OS2 and DOS4GW. # May work with Watcom 10.0. -# Uncoment one of the lines below for cross compilation. +# Uncomment one of the lines below for cross compilation. SYSTEM=MSWIN32 #SYSTEM=DOS4GW #SYSTEM=OS2 @@ -25,7 +25,7 @@ CPU=5 OPTIM=-oneatx -s #OPTIM=-ohneatx -s -DEFS=-DALL_INTERIOR_POINTERS #-DSMALL_CONFIG #-DGC_DEBUG +DEFS=-DALL_INTERIOR_POINTERS #-DSMALL_CONFIG ##### @@ -66,11 +66,10 @@ TEST_DLLFLAG= CC=wcc386 CXX=wpp386 -# -DUSE_GENERIC is required ! -CFLAGS=-$(CPU)$(CALLING) $(OPTIM) -zp4 -zc $(SYSFLAG) $(DLLFLAG) -DUSE_GENERIC $(DEFS) -CXXFLAGS= $(CFLAGS) -TEST_CFLAGS=-$(CPU)$(CALLING) $(OPTIM) -zp4 -zc $(SYSFLAG) $(TEST_DLLFLAG) $(DEFS) -TEST_CXXFLAGS= $(TEST_CFLAGS) +CFLAGS=-$(CPU)$(CALLING) $(OPTIM) -iinclude -zp4 -zc $(SYSFLAG) $(DLLFLAG) $(DEFS) +CXXFLAGS= $(CFLAGS) -xs +TEST_CFLAGS=-$(CPU)$(CALLING) $(OPTIM) -iinclude -zp4 -zc $(SYSFLAG) $(TEST_DLLFLAG) $(DEFS) +TEST_CXXFLAGS= $(TEST_CFLAGS) -xs OBJS= alloc.obj reclaim.obj allchblk.obj misc.obj & mach_dep.obj os_dep.obj mark_rts.obj headers.obj mark.obj & @@ -96,23 +95,12 @@ gc.dll: $(OBJS) .AUTODEPEND !endif @%append $*.lnk name $* @for %i in ($(OBJS)) do @%append $*.lnk file '%i' -!ifeq CALLING s - @%append $*.lnk export GC_is_marked - @%append $*.lnk export GC_incr_bytes_allocd - @%append $*.lnk export GC_incr_bytes_freed - @%append $*.lnk export GC_generic_malloc_words_small -!else - @%append $*.lnk export GC_is_marked_ - @%append $*.lnk export GC_incr_bytes_allocd_ - @%append $*.lnk export GC_incr_bytes_freed_ - @%append $*.lnk export GC_generic_malloc_words_small_ -!endif *wlink @$*.lnk !else gc.lib: $(OBJS) gc_cpp.obj @%create $*.lb1 @for %i in ($(OBJS)) do @%append $*.lb1 +'%i' - @%append $*.lb1 +'gc_cpp.obj' + @%append $*.lb1 +'gc_cpp.obj' *wlib -b -c -n -p=512 $@ @$*.lb1 !endif @@ -132,13 +120,6 @@ gctest.exe: test.obj gc.lib @%append $*.lnk name $* @%append $*.lnk file test.obj @%append $*.lnk library gc.lib -!ifdef MAKE_AS_DLL -!ifeq CALLING s - @%append $*.lnk import GC_is_marked gc -!else - @%append $*.lnk import GC_is_marked_ gc -!endif -!endif *wlink @$*.lnk test_cpp.exe: test_cpp.obj gc.lib %create $*.lnk @@ -154,26 +135,14 @@ test_cpp.exe: test_cpp.obj gc.lib @%append $*.lnk name $* @%append $*.lnk file test_cpp.obj @%append $*.lnk library gc.lib -!ifdef MAKE_AS_DLL -!ifeq CALLING s - @%append $*.lnk import GC_incr_bytes_allocd gc - @%append $*.lnk import GC_incr_bytes_freed gc - @%append $*.lnk import GC_generic_malloc_words_small gc -!else - @%append $*.lnk import GC_incr_bytes_allocd_ gc - @%append $*.lnk import GC_incr_bytes_freed_ gc - @%append $*.lnk import GC_generic_malloc_words_small_ gc -!endif -!endif *wlink @$*.lnk gc_cpp.obj: gc_cpp.cc .AUTODEPEND - $(CXX) $(TEST_CXXFLAGS) -iinclude $*.cc + $(CXX) $(TEST_CXXFLAGS) $*.cc test.obj: tests\test.c .AUTODEPEND - $(CC) $(TEST_CFLAGS) $*.c + $(CC) $(TEST_CFLAGS) tests\test.c test_cpp.obj: tests\test_cpp.cc .AUTODEPEND - $(CXX) $(TEST_CXXFLAGS) -iinclude $*.cc - + $(CXX) $(TEST_CXXFLAGS) tests\test_cpp.cc .c.obj: .AUTODEPEND $(CC) $(CFLAGS) $*.c diff --git a/src/bdwgc/aclocal.m4 b/src/bdwgc/aclocal.m4 index ebf66d5d7..127d17906 100644 --- a/src/bdwgc/aclocal.m4 +++ b/src/bdwgc/aclocal.m4 @@ -20,32 +20,63 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# serial 1 (pkg-config-0.24) -# -# Copyright © 2004 Scott James Remnant . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) -# PKG_PROG_PKG_CONFIG([MIN-VERSION]) -# ---------------------------------- +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) @@ -67,18 +98,19 @@ if test -n "$PKG_CONFIG"; then PKG_CONFIG="" fi fi[]dnl -])# PKG_PROG_PKG_CONFIG +])dnl PKG_PROG_PKG_CONFIG -# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# -# Check to see whether a particular set of modules exists. Similar -# to PKG_CHECK_MODULES(), but does not set variables or print errors. -# -# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -# only at the first occurence in configure.ac, so if the first place -# it's called might be skipped (such as if it is within an "if", you -# have to call PKG_CHECK_EXISTS manually -# -------------------------------------------------------------- +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ @@ -88,8 +120,10 @@ m4_ifvaln([$3], [else $3])dnl fi]) -# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -# --------------------------------------------- +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" @@ -101,10 +135,11 @@ m4_define([_PKG_CONFIG], else pkg_failed=untried fi[]dnl -])# _PKG_CONFIG +])dnl _PKG_CONFIG -# _PKG_SHORT_ERRORS_SUPPORTED -# ----------------------------- +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -112,26 +147,24 @@ if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then else _pkg_short_errors_supported=no fi[]dnl -])# _PKG_SHORT_ERRORS_SUPPORTED +])dnl _PKG_SHORT_ERRORS_SUPPORTED -# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# -# -# Note that if there is a possibility the first call to -# PKG_CHECK_MODULES might not happen, you should be sure to include an -# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac -# -# -# -------------------------------------------------------------- +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no -AC_MSG_CHECKING([for $1]) +AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) @@ -141,11 +174,11 @@ and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` - else + else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs @@ -162,7 +195,7 @@ installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -178,16 +211,40 @@ else AC_MSG_RESULT([yes]) $3 fi[]dnl -])# PKG_CHECK_MODULES +])dnl PKG_CHECK_MODULES -# PKG_INSTALLDIR(DIRECTORY) -# ------------------------- -# Substitutes the variable pkgconfigdir as the location where a module -# should install pkg-config .pc files. By default the directory is -# $libdir/pkgconfig, but the default can be changed by passing -# DIRECTORY. The user can override through the --with-pkgconfigdir -# parameter. +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], @@ -198,16 +255,18 @@ AC_ARG_WITH([pkgconfigdir], AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) -]) dnl PKG_INSTALLDIR +])dnl PKG_INSTALLDIR -# PKG_NOARCH_INSTALLDIR(DIRECTORY) -# ------------------------- -# Substitutes the variable noarch_pkgconfigdir as the location where a -# module should install arch-independent pkg-config .pc files. By -# default the directory is $datadir/pkgconfig, but the default can be -# changed by passing DIRECTORY. The user can override through the -# --with-noarch-pkgconfigdir parameter. +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], @@ -218,13 +277,15 @@ AC_ARG_WITH([noarch-pkgconfigdir], AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) -]) dnl PKG_NOARCH_INSTALLDIR +])dnl PKG_NOARCH_INSTALLDIR -# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, -# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# ------------------------------------------- -# Retrieves the value of the pkg-config variable for the given module. +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl @@ -233,7 +294,7 @@ _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl -])# PKG_CHECK_VAR +])dnl PKG_CHECK_VAR # Copyright (C) 2002-2014 Free Software Foundation, Inc. # @@ -1421,6 +1482,7 @@ AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR +m4_include([m4/gc_set_version.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) diff --git a/src/bdwgc/allchblk.c b/src/bdwgc/allchblk.c index 8ae1f671a..18b5bbefd 100644 --- a/src/bdwgc/allchblk.c +++ b/src/bdwgc/allchblk.c @@ -103,12 +103,13 @@ STATIC int GC_hblk_fl_from_blocks(word blocks_needed) /* Should return the same value as GC_large_free_bytes. */ GC_INNER word GC_compute_large_free_bytes(void) { - struct hblk * h; - hdr * hhdr; word total_free = 0; unsigned i; for (i = 0; i <= N_HBLK_FLS; ++i) { + struct hblk * h; + hdr * hhdr; + for (h = GC_hblkfreelist[i]; h != 0; h = hhdr->hb_next) { hhdr = HDR(h); total_free += hhdr->hb_sz; @@ -121,17 +122,17 @@ STATIC int GC_hblk_fl_from_blocks(word blocks_needed) # if !defined(NO_DEBUGGING) void GC_print_hblkfreelist(void) { - struct hblk * h; - hdr * hhdr; unsigned i; word total; for (i = 0; i <= N_HBLK_FLS; ++i) { - h = GC_hblkfreelist[i]; + struct hblk * h = GC_hblkfreelist[i]; + if (0 != h) GC_printf("Free list %u (total size %lu):\n", i, (unsigned long)GC_free_bytes[i]); while (h != 0) { - hhdr = HDR(h); + hdr * hhdr = HDR(h); + GC_printf("\t%p size %lu %s black listed\n", (void *)h, (unsigned long) hhdr -> hb_sz, GC_is_black_listed(h, HBLKSIZE) != 0 ? "start" : @@ -152,42 +153,42 @@ void GC_print_hblkfreelist(void) /* appears, or -1 if it appears nowhere. */ static int free_list_index_of(hdr *wanted) { - struct hblk * h; - hdr * hhdr; int i; for (i = 0; i <= N_HBLK_FLS; ++i) { - h = GC_hblkfreelist[i]; - while (h != 0) { + struct hblk * h; + hdr * hhdr; + + for (h = GC_hblkfreelist[i]; h != 0; h = hhdr -> hb_next) { hhdr = HDR(h); if (hhdr == wanted) return i; - h = hhdr -> hb_next; } } return -1; } -void GC_dump_regions(void) +GC_API void GC_CALL GC_dump_regions(void) { unsigned i; - ptr_t start, end; - ptr_t p; - size_t bytes; - hdr *hhdr; + for (i = 0; i < GC_n_heap_sects; ++i) { - start = GC_heap_sects[i].hs_start; - bytes = GC_heap_sects[i].hs_bytes; - end = start + bytes; + ptr_t start = GC_heap_sects[i].hs_start; + size_t bytes = GC_heap_sects[i].hs_bytes; + ptr_t end = start + bytes; + ptr_t p; + /* Merge in contiguous sections. */ while (i+1 < GC_n_heap_sects && GC_heap_sects[i+1].hs_start == end) { ++i; end = GC_heap_sects[i].hs_start + GC_heap_sects[i].hs_bytes; } - GC_printf("***Section from %p to %p\n", start, end); + GC_printf("***Section from %p to %p\n", (void *)start, (void *)end); for (p = start; (word)p < (word)end; ) { - hhdr = HDR(p); + hdr *hhdr = HDR(p); + if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { - GC_printf("\t%p Missing header!!(%p)\n", p, (void *)hhdr); + GC_printf("\t%p Missing header!!(%p)\n", + (void *)p, (void *)hhdr); p += HBLKSIZE; continue; } @@ -196,8 +197,8 @@ void GC_dump_regions(void) divHBLKSZ(hhdr -> hb_sz)); int actual_index; - GC_printf("\t%p\tfree block of size 0x%lx bytes%s\n", p, - (unsigned long)(hhdr -> hb_sz), + GC_printf("\t%p\tfree block of size 0x%lx bytes%s\n", + (void *)p, (unsigned long)(hhdr -> hb_sz), IS_MAPPED(hhdr) ? "" : " (unmapped)"); actual_index = free_list_index_of(hhdr); if (-1 == actual_index) { @@ -209,8 +210,8 @@ void GC_dump_regions(void) } p += hhdr -> hb_sz; } else { - GC_printf("\t%p\tused for blocks of size 0x%lx bytes\n", p, - (unsigned long)(hhdr -> hb_sz)); + GC_printf("\t%p\tused for blocks of size 0x%lx bytes\n", + (void *)p, (unsigned long)(hhdr -> hb_sz)); p += HBLKSIZE * OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz); } } @@ -226,9 +227,8 @@ static GC_bool setup_header(hdr * hhdr, struct hblk *block, size_t byte_sz, int kind, unsigned flags) { word descr; -# ifdef MARK_BIT_PER_GRANULE - size_t granules; +# ifdef MARK_BIT_PER_GRANULE if (byte_sz > MAXOBJBYTES) flags |= LARGE_BLOCK; # endif @@ -250,7 +250,7 @@ static GC_bool setup_header(hdr * hhdr, struct hblk *block, size_t byte_sz, # ifdef MARK_BIT_PER_OBJ /* Set hb_inv_sz as portably as possible. */ - /* We set it to the smallest value such that sz * inv_sz > 2**32 */ + /* We set it to the smallest value such that sz * inv_sz >= 2**32 */ /* This may be more precision than necessary. */ if (byte_sz > MAXOBJBYTES) { hhdr -> hb_inv_sz = LARGE_INV_SZ; @@ -265,11 +265,16 @@ static GC_bool setup_header(hdr * hhdr, struct hblk *block, size_t byte_sz, inv_sz = ((unsigned)1 << 31)/byte_sz; inv_sz *= 2; while (inv_sz*byte_sz > byte_sz) ++inv_sz; +# endif +# ifdef INV_SZ_COMPUTATION_CHECK + GC_ASSERT(((1ULL << 32) + byte_sz - 1) / byte_sz == inv_sz); # endif hhdr -> hb_inv_sz = inv_sz; } # else /* MARK_BIT_PER_GRANULE */ - granules = BYTES_TO_GRANULES(byte_sz); + { + size_t granules = BYTES_TO_GRANULES(byte_sz); + if (EXPECT(!GC_add_map_entry(granules), FALSE)) { /* Make it look like a valid block. */ hhdr -> hb_sz = HBLKSIZE; @@ -280,6 +285,7 @@ static GC_bool setup_header(hdr * hhdr, struct hblk *block, size_t byte_sz, } hhdr -> hb_map = GC_obj_map[(hhdr -> hb_flags & LARGE_BLOCK) != 0 ? 0 : granules]; + } # endif /* MARK_BIT_PER_GRANULE */ /* Clear mark bits */ @@ -353,19 +359,18 @@ STATIC void GC_add_to_fl(struct hblk *h, hdr *hhdr) { int index = GC_hblk_fl_from_blocks(divHBLKSZ(hhdr -> hb_sz)); struct hblk *second = GC_hblkfreelist[index]; - hdr * second_hdr; # if defined(GC_ASSERTIONS) && !defined(USE_MUNMAP) struct hblk *next = (struct hblk *)((word)h + hhdr -> hb_sz); hdr * nexthdr = HDR(next); struct hblk *prev = GC_free_block_ending_at(h); hdr * prevhdr = HDR(prev); + GC_ASSERT(nexthdr == 0 || !HBLK_IS_FREE(nexthdr) - || (signed_word)GC_heapsize < 0); + || (GC_heapsize & SIGNB) != 0); /* In the last case, blocks may be too large to merge. */ GC_ASSERT(prev == 0 || !HBLK_IS_FREE(prevhdr) - || (signed_word)GC_heapsize < 0); + || (GC_heapsize & SIGNB) != 0); # endif - GC_ASSERT(((hhdr -> hb_sz) & (HBLKSIZE-1)) == 0); GC_hblkfreelist[index] = h; GC_free_bytes[index] += hhdr -> hb_sz; @@ -373,6 +378,8 @@ STATIC void GC_add_to_fl(struct hblk *h, hdr *hhdr) hhdr -> hb_next = second; hhdr -> hb_prev = 0; if (0 != second) { + hdr * second_hdr; + GET_HDR(second, second_hdr); second_hdr -> hb_prev = h; } @@ -391,19 +398,22 @@ GC_INNER int GC_unmap_threshold = MUNMAP_THRESHOLD; /* way blocks are ever unmapped. */ GC_INNER void GC_unmap_old(void) { - struct hblk * h; - hdr * hhdr; int i; if (GC_unmap_threshold == 0) return; /* unmapping disabled */ for (i = 0; i <= N_HBLK_FLS; ++i) { + struct hblk * h; + hdr * hhdr; + for (h = GC_hblkfreelist[i]; 0 != h; h = hhdr -> hb_next) { hhdr = HDR(h); if (!IS_MAPPED(hhdr)) continue; - if ((unsigned short)GC_gc_no - hhdr -> hb_last_reclaimed > + /* Check that the interval is larger than the threshold (the */ + /* truncated counter value wrapping is handled correctly). */ + if ((unsigned short)(GC_gc_no - hhdr->hb_last_reclaimed) > (unsigned short)GC_unmap_threshold) { GC_unmap((ptr_t)h, hhdr -> hb_sz); hhdr -> hb_flags |= WAS_UNMAPPED; @@ -417,14 +427,16 @@ GC_INNER void GC_unmap_old(void) /* fully mapped or fully unmapped. */ GC_INNER void GC_merge_unmapped(void) { - struct hblk * h, *next; - hdr * hhdr, *nexthdr; - word size, nextsize; int i; for (i = 0; i <= N_HBLK_FLS; ++i) { - h = GC_hblkfreelist[i]; + struct hblk *h = GC_hblkfreelist[i]; + while (h != 0) { + struct hblk *next; + hdr *hhdr, *nexthdr; + word size, nextsize; + GET_HDR(h, hhdr); size = hhdr->hb_sz; next = (struct hblk *)((word)h + size); @@ -500,7 +512,7 @@ STATIC struct hblk * GC_get_first_part(struct hblk *h, hdr *hhdr, rest_hdr = GC_install_header(rest); if (0 == rest_hdr) { /* FIXME: This is likely to be very bad news ... */ - WARN("Header allocation failed: Dropping block.\n", 0); + WARN("Header allocation failed: dropping block\n", 0); return(0); } rest_hdr -> hb_sz = total_size - bytes; @@ -583,7 +595,7 @@ GC_allochblk(size_t sz, int kind, unsigned flags/* IGNORE_OFF_PAGE or 0 */) /* split. */ GC_ASSERT((sz & (GRANULE_BYTES - 1)) == 0); - blocks = OBJ_SZ_TO_BLOCKS(sz); + blocks = OBJ_SZ_TO_BLOCKS_CHECKED(sz); if ((signed_word)(blocks * HBLKSIZE) < 0) { return 0; } @@ -643,26 +655,26 @@ GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n, int may_split) hdr * hhdr; /* Header corr. to hbp */ struct hblk *thishbp; hdr * thishdr; /* Header corr. to thishbp */ - signed_word size_needed; /* number of bytes in requested objects */ - signed_word size_avail; /* bytes available in this block */ - - size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz); + signed_word size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS_CHECKED(sz); + /* number of bytes in requested objects */ /* search for a big enough block in free list */ for (hbp = GC_hblkfreelist[n];; hbp = hhdr -> hb_next) { + signed_word size_avail; /* bytes available in this block */ + if (NULL == hbp) return NULL; GET_HDR(hbp, hhdr); /* set hhdr value */ size_avail = hhdr->hb_sz; if (size_avail < size_needed) continue; if (size_avail != size_needed) { - signed_word next_size; - if (!may_split) continue; /* If the next heap block is obviously better, go on. */ /* This prevents us from disassembling a single large */ /* block to get tiny blocks. */ thishbp = hhdr -> hb_next; if (thishbp != 0) { + signed_word next_size; + GET_HDR(thishbp, thishdr); next_size = (signed_word)(thishdr -> hb_sz); if (next_size < size_avail @@ -721,12 +733,13 @@ GC_allochblk_nth(size_t sz, int kind, unsigned flags, int n, int may_split) >= GC_large_alloc_warn_interval) { WARN("Repeated allocation of very large block " "(appr. size %" WARN_PRIdPTR "):\n" - "\tMay lead to memory leak and poor performance.\n", + "\tMay lead to memory leak and poor performance\n", size_needed); GC_large_alloc_warn_suppressed = 0; } size_avail = orig_avail; - } else if (size_avail == 0 && size_needed == HBLKSIZE + } else if (size_avail == 0 + && size_needed == (signed_word)HBLKSIZE && IS_MAPPED(hhdr)) { if (!GC_find_leak) { static unsigned count = 0; diff --git a/src/bdwgc/alloc.c b/src/bdwgc/alloc.c index 2f877fba1..569b3cbf2 100644 --- a/src/bdwgc/alloc.c +++ b/src/bdwgc/alloc.c @@ -3,6 +3,7 @@ * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved. * Copyright (c) 1998 by Silicon Graphics. All rights reserved. * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P. + * Copyright (c) 2008-2018 Ivan Maidanski * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -64,21 +65,21 @@ word GC_non_gc_bytes = 0; /* Number of bytes not intended to be collected */ word GC_gc_no = 0; #ifndef GC_DISABLE_INCREMENTAL - GC_INNER int GC_incremental = 0; /* By default, stop the world. */ + GC_INNER GC_bool GC_incremental = FALSE; /* By default, stop the world. */ #endif #ifdef THREADS int GC_parallel = FALSE; /* By default, parallel GC is off. */ #endif -#ifndef GC_FULL_FREQ -# define GC_FULL_FREQ 19 /* Every 20th collection is a full */ +#if defined(GC_FULL_FREQ) && !defined(CPPCHECK) + int GC_full_freq = GC_FULL_FREQ; +#else + int GC_full_freq = 19; /* Every 20th collection is a full */ /* collection, whether we need it */ /* or not. */ #endif -int GC_full_freq = GC_FULL_FREQ; - STATIC GC_bool GC_need_full_gc = FALSE; /* Need full GC do to heap growth. */ @@ -90,10 +91,11 @@ STATIC word GC_used_heap_size_after_full = 0; /* GC_copyright symbol is externally visible. */ char * const GC_copyright[] = -{"Copyright 1988,1989 Hans-J. Boehm and Alan J. Demers ", +{"Copyright 1988, 1989 Hans-J. Boehm and Alan J. Demers ", "Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. ", "Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved. ", "Copyright (c) 1999-2009 by Hewlett-Packard Company. All rights reserved. ", +"Copyright (c) 2008-2018 Ivan Maidanski ", "THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY", " EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.", "See source code for details." }; @@ -119,24 +121,25 @@ GC_API unsigned GC_CALL GC_get_version(void) int GC_dont_expand = FALSE; #endif -#ifndef GC_FREE_SPACE_DIVISOR -# define GC_FREE_SPACE_DIVISOR 3 /* must be > 0 */ +#if defined(GC_FREE_SPACE_DIVISOR) && !defined(CPPCHECK) + word GC_free_space_divisor = GC_FREE_SPACE_DIVISOR; /* must be > 0 */ +#else + word GC_free_space_divisor = 3; #endif -word GC_free_space_divisor = GC_FREE_SPACE_DIVISOR; - GC_INNER int GC_CALLBACK GC_never_stop_func(void) { return(0); } -#ifndef GC_TIME_LIMIT -# define GC_TIME_LIMIT 50 /* We try to keep pause times from exceeding */ +#if defined(GC_TIME_LIMIT) && !defined(CPPCHECK) + unsigned long GC_time_limit = GC_TIME_LIMIT; + /* We try to keep pause times from exceeding */ /* this by much. In milliseconds. */ +#else + unsigned long GC_time_limit = 50; #endif -unsigned long GC_time_limit = GC_TIME_LIMIT; - #ifndef NO_CLOCK STATIC CLOCK_TYPE GC_start_time = 0; /* Time at which we stopped world. */ @@ -152,7 +155,7 @@ STATIC GC_stop_func GC_default_stop_func = GC_never_stop_func; GC_API void GC_CALL GC_set_stop_func(GC_stop_func stop_func) { DCL_LOCK_STATE; - GC_ASSERT(stop_func != 0); + GC_ASSERT(NONNULL_ARG_NOT_NULL(stop_func)); LOCK(); GC_default_stop_func = stop_func; UNLOCK(); @@ -202,15 +205,7 @@ GC_API GC_stop_func GC_CALL GC_get_stop_func(void) static word min_bytes_allocd(void) { word result; -# ifdef STACK_NOT_SCANNED - word stack_size = 0; -# elif defined(STACK_GROWS_UP) - word stack_size = GC_approx_sp() - GC_stackbottom; - /* GC_stackbottom is used only for a single-threaded case. */ -# else - word stack_size = GC_stackbottom - GC_approx_sp(); -# endif - + word stack_size; word total_root_size; /* includes double stack size, */ /* since the stack is expensive */ /* to scan. */ @@ -226,8 +221,17 @@ static word min_bytes_allocd(void) GC_log_printf("Total stacks size: %lu\n", (unsigned long)stack_size); # endif - } + } else # endif + /* else*/ { +# ifdef STACK_NOT_SCANNED + stack_size = 0; +# elif defined(STACK_GROWS_UP) + stack_size = GC_approx_sp() - GC_stackbottom; +# else + stack_size = GC_stackbottom - GC_approx_sp(); +# endif + } total_root_size = 2 * stack_size + GC_root_size; scan_size = 2 * GC_composite_in_use + GC_atomic_in_use / 4 @@ -355,11 +359,11 @@ STATIC void GC_finish_collection(void); */ STATIC void GC_maybe_gc(void) { - static int n_partial_gcs = 0; - GC_ASSERT(I_HOLD_LOCK()); ASSERT_CANCEL_DISABLED(); if (GC_should_collect()) { + static int n_partial_gcs = 0; + if (!GC_incremental) { /* FIXME: If possible, GC_default_stop_func should be used here */ GC_try_to_collect_inner(GC_never_stop_func); @@ -386,7 +390,7 @@ STATIC void GC_maybe_gc(void) } /* We try to mark with the world stopped. */ /* If we run out of time, this turns into */ - /* incremental marking. */ + /* incremental marking. */ # ifndef NO_CLOCK if (GC_time_limit != GC_TIME_UNLIMITED) { GET_TIME(GC_start_time); } # endif @@ -407,26 +411,50 @@ STATIC void GC_maybe_gc(void) } } +STATIC GC_on_collection_event_proc GC_on_collection_event = 0; -/* - * Stop the world garbage collection. Assumes lock held. If stop_func is - * not GC_never_stop_func then abort if stop_func returns TRUE. - * Return TRUE if we successfully completed the collection. - */ +GC_API void GC_CALL GC_set_on_collection_event(GC_on_collection_event_proc fn) +{ + /* fn may be 0 (means no event notifier). */ + DCL_LOCK_STATE; + LOCK(); + GC_on_collection_event = fn; + UNLOCK(); +} + +GC_API GC_on_collection_event_proc GC_CALL GC_get_on_collection_event(void) +{ + GC_on_collection_event_proc fn; + DCL_LOCK_STATE; + LOCK(); + fn = GC_on_collection_event; + UNLOCK(); + return fn; +} + +/* Stop the world garbage collection. If stop_func is not */ +/* GC_never_stop_func then abort if stop_func returns TRUE. */ +/* Return TRUE if we successfully completed the collection. */ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func) { # ifndef SMALL_CONFIG CLOCK_TYPE start_time = 0; /* initialized to prevent warning. */ - CLOCK_TYPE current_time; # endif + ASSERT_CANCEL_DISABLED(); + GC_ASSERT(I_HOLD_LOCK()); if (GC_dont_gc || (*stop_func)()) return FALSE; + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_START); if (GC_incremental && GC_collection_in_progress()) { GC_COND_LOG_PRINTF( "GC_try_to_collect_inner: finishing collection in progress\n"); /* Just finish collection already in progress. */ while(GC_collection_in_progress()) { - if ((*stop_func)()) return(FALSE); + if ((*stop_func)()) { + /* TODO: Notify GC_EVENT_ABANDON */ + return(FALSE); + } GC_collect_a_little_inner(1); } } @@ -450,6 +478,7 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func) if ((GC_find_leak || stop_func != GC_never_stop_func) && !GC_reclaim_all(stop_func, FALSE)) { /* Aborted. So far everything is still consistent. */ + /* TODO: Notify GC_EVENT_ABANDON */ return(FALSE); } GC_invalidate_mark_state(); /* Flush mark stack. */ @@ -467,16 +496,21 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func stop_func) GC_unpromote_black_lists(); } /* else we claim the world is already still consistent. We'll */ /* finish incrementally. */ + /* TODO: Notify GC_EVENT_ABANDON */ return(FALSE); } GC_finish_collection(); # ifndef SMALL_CONFIG if (GC_print_stats) { + CLOCK_TYPE current_time; + GET_TIME(current_time); GC_log_printf("Complete collection took %lu msecs\n", MS_TIME_DIFF(current_time,start_time)); } # endif + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_END); return(TRUE); } @@ -503,12 +537,13 @@ STATIC int GC_deficit = 0;/* The number of extra calls to GC_mark_some */ GC_INNER void GC_collect_a_little_inner(int n) { - int i; IF_CANCEL(int cancel_state;) if (GC_dont_gc) return; DISABLE_CANCEL(cancel_state); if (GC_incremental && GC_collection_in_progress()) { + int i; + for (i = GC_deficit; i < GC_RATE*n; i++) { if (GC_mark_some((ptr_t)0)) { /* Need to finish a collection */ @@ -593,7 +628,6 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) unsigned i; # ifndef SMALL_CONFIG CLOCK_TYPE start_time = 0; /* initialized to prevent warning. */ - CLOCK_TYPE current_time; # endif # if !defined(REDIRECT_MALLOC) && defined(USE_WINALLOC) @@ -608,7 +642,19 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) GET_TIME(start_time); # endif +# if !defined(GC_NO_FINALIZATION) && !defined(GC_TOGGLE_REFS_NOT_NEEDED) + GC_process_togglerefs(); +# endif +# ifdef THREADS + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_PRE_STOP_WORLD); +# endif STOP_WORLD(); +# ifdef THREADS + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_POST_STOP_WORLD); +# endif + # ifdef THREAD_LOCAL_ALLOC GC_world_stopped = TRUE; # endif @@ -623,6 +669,9 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) # endif /* Mark from all roots. */ + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_MARK_START); + /* Minimize junk left in my registers and on the stack */ GC_clear_a_few_frames(); GC_noop6(0,0,0,0,0,0); @@ -636,7 +685,20 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) # ifdef THREAD_LOCAL_ALLOC GC_world_stopped = FALSE; # endif + +# ifdef THREADS + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_PRE_START_WORLD); +# endif + START_WORLD(); + +# ifdef THREADS + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_POST_START_WORLD); +# endif + + /* TODO: Notify GC_EVENT_MARK_ABANDON */ return(FALSE); } if (GC_mark_some(GC_approx_sp())) break; @@ -653,15 +715,31 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) if (GC_debugging_started) { (*GC_check_heap)(); } + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_MARK_END); # ifdef THREAD_LOCAL_ALLOC GC_world_stopped = FALSE; # endif + +# ifdef THREADS + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_PRE_START_WORLD); +# endif + START_WORLD(); + +# ifdef THREADS + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_POST_START_WORLD); +# endif + # ifndef SMALL_CONFIG if (GC_PRINT_STATS_FLAG) { unsigned long time_diff; unsigned total_time, divisor; + CLOCK_TYPE current_time; + GET_TIME(current_time); time_diff = MS_TIME_DIFF(current_time,start_time); @@ -691,19 +769,15 @@ STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func) /* Set all mark bits for the free list whose first entry is q */ GC_INNER void GC_set_fl_marks(ptr_t q) { - struct hblk *h, *last_h; - hdr *hhdr; - IF_PER_OBJ(size_t sz;) - unsigned bit_no; + if (q != NULL) { + struct hblk *h = HBLKPTR(q); + struct hblk *last_h = h; + hdr *hhdr = HDR(h); + IF_PER_OBJ(size_t sz = hhdr->hb_sz;) - if (q != NULL) { - h = HBLKPTR(q); - last_h = h; - hhdr = HDR(h); - IF_PER_OBJ(sz = hhdr->hb_sz;) + for (;;) { + unsigned bit_no = MARK_BIT_NO((ptr_t)q - (ptr_t)h, sz); - for (;;) { - bit_no = MARK_BIT_NO((ptr_t)q - (ptr_t)h, sz); if (!mark_bit_from_hdr(hhdr, bit_no)) { set_mark_bit_from_hdr(hhdr, bit_no); ++hhdr -> hb_n_marks; @@ -719,8 +793,8 @@ GC_INNER void GC_set_fl_marks(ptr_t q) hhdr = HDR(h); IF_PER_OBJ(sz = hhdr->hb_sz;) } - } - } + } + } } #if defined(GC_ASSERTIONS) && defined(THREADS) && defined(THREAD_LOCAL_ALLOC) @@ -769,22 +843,21 @@ GC_INNER void GC_set_fl_marks(ptr_t q) /* Decrement GC_bytes_found by number of bytes on free list. */ STATIC void GC_clear_fl_marks(ptr_t q) { - struct hblk *h, *last_h; - hdr *hhdr; - size_t sz; - unsigned bit_no; + if (q != NULL) { + struct hblk *h = HBLKPTR(q); + struct hblk *last_h = h; + hdr *hhdr = HDR(h); + size_t sz = hhdr->hb_sz; /* Normally set only once. */ - if (q != NULL) { - h = HBLKPTR(q); - last_h = h; - hhdr = HDR(h); - sz = hhdr->hb_sz; /* Normally set only once. */ + for (;;) { + unsigned bit_no = MARK_BIT_NO((ptr_t)q - (ptr_t)h, sz); - for (;;) { - bit_no = MARK_BIT_NO((ptr_t)q - (ptr_t)h, sz); if (mark_bit_from_hdr(hhdr, bit_no)) { - size_t n_marks = hhdr -> hb_n_marks - 1; + size_t n_marks = hhdr -> hb_n_marks; + + GC_ASSERT(n_marks != 0); clear_mark_bit_from_hdr(hhdr, bit_no); + n_marks--; # ifdef PARALLEL_MARK /* Appr. count, don't decrement to zero! */ if (0 != n_marks || !GC_parallel) { @@ -806,8 +879,8 @@ STATIC void GC_clear_fl_marks(ptr_t q) hhdr = HDR(h); sz = hhdr->hb_sz; } - } - } + } + } } #if defined(GC_ASSERTIONS) && defined(THREADS) && defined(THREAD_LOCAL_ALLOC) @@ -832,7 +905,6 @@ STATIC void GC_finish_collection(void) # ifndef SMALL_CONFIG CLOCK_TYPE start_time = 0; /* initialized to prevent warning. */ CLOCK_TYPE finalize_time = 0; - CLOCK_TYPE done_time; # endif # if defined(GC_ASSERTIONS) && defined(THREADS) \ @@ -846,6 +918,8 @@ STATIC void GC_finish_collection(void) if (GC_print_stats) GET_TIME(start_time); # endif + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_RECLAIM_START); # ifndef GC_GET_HEAP_USAGE_NOT_NEEDED if (GC_bytes_found > 0) @@ -951,8 +1025,12 @@ STATIC void GC_finish_collection(void) IF_USE_MUNMAP(GC_unmap_old()); + if (GC_on_collection_event) + GC_on_collection_event(GC_EVENT_RECLAIM_END); # ifndef SMALL_CONFIG if (GC_print_stats) { + CLOCK_TYPE done_time; + GET_TIME(done_time); # ifndef GC_NO_FINALIZATION /* A convenient place to output finalization statistics. */ @@ -1004,7 +1082,7 @@ STATIC GC_bool GC_try_to_collect_general(GC_stop_func stop_func, /* Externally callable routines to invoke full, stop-the-world collection. */ GC_API int GC_CALL GC_try_to_collect(GC_stop_func stop_func) { - GC_ASSERT(stop_func != 0); + GC_ASSERT(NONNULL_ARG_NOT_NULL(stop_func)); return (int)GC_try_to_collect_general(stop_func, FALSE); } @@ -1130,9 +1208,9 @@ GC_INNER void GC_add_to_heap(struct hblk *p, size_t bytes) for (h = (struct hblk *)start; (word)h < (word)(start + len); h++) { if (GC_is_black_listed(h, HBLKSIZE)) nbl++; } - GC_printf("Section %d from %p to %p %lu/%lu blacklisted\n", - i, start, start + len, - (unsigned long)nbl, (unsigned long)(len/HBLKSIZE)); + GC_printf("Section %d from %p to %p %u/%lu blacklisted\n", + i, (void *)start, (void *)&start[len], + nbl, (unsigned long)divHBLKSZ(len)); } } #endif @@ -1165,25 +1243,28 @@ GC_word GC_max_retries = 0; /* Returns FALSE on failure. */ GC_INNER GC_bool GC_expand_hp_inner(word n) { - word bytes; + size_t bytes; struct hblk * space; word expansion_slop; /* Number of bytes by which we expect the */ /* heap to expand soon. */ if (n < MINHINCR) n = MINHINCR; - bytes = ROUNDUP_PAGESIZE(n * HBLKSIZE); - if (GC_max_heapsize != 0 && GC_heapsize + bytes > GC_max_heapsize) { + bytes = ROUNDUP_PAGESIZE((size_t)n * HBLKSIZE); + if (GC_max_heapsize != 0 + && (GC_max_heapsize < (word)bytes + || GC_heapsize > GC_max_heapsize - (word)bytes)) { /* Exceeded self-imposed limit */ return(FALSE); } space = GET_MEM(bytes); GC_add_to_our_memory((ptr_t)space, bytes); if (space == 0) { - WARN("Failed to expand heap by %" WARN_PRIdPTR " bytes\n", bytes); + WARN("Failed to expand heap by %" WARN_PRIdPTR " bytes\n", + (word)bytes); return(FALSE); } GC_INFOLOG_PRINTF("Grow heap to %lu KiB after %lu bytes allocated\n", - TO_KiB_UL(GC_heapsize + bytes), + TO_KiB_UL(GC_heapsize + (word)bytes), (unsigned long)GC_bytes_allocd); /* Adjust heap limits generously for blacklisting to work better. */ /* GC_add_to_heap performs minimal adjustment needed for */ @@ -1193,7 +1274,7 @@ GC_INNER GC_bool GC_expand_hp_inner(word n) || (GC_last_heap_addr != 0 && (word)GC_last_heap_addr < (word)space)) { /* Assume the heap is growing up */ - word new_limit = (word)space + bytes + expansion_slop; + word new_limit = (word)space + (word)bytes + expansion_slop; if (new_limit > (word)space) { GC_greatest_plausible_heap_addr = (void *)GC_max((word)GC_greatest_plausible_heap_addr, @@ -1229,8 +1310,8 @@ GC_API int GC_CALL GC_expand_hp(size_t bytes) int result; DCL_LOCK_STATE; - LOCK(); if (!EXPECT(GC_is_initialized, TRUE)) GC_init(); + LOCK(); result = (int)GC_expand_hp_inner(divHBLKSZ((word)bytes)); if (result) GC_requested_heapsize += bytes; UNLOCK(); @@ -1246,6 +1327,8 @@ GC_INNER unsigned GC_fail_count = 0; static word last_fo_entries = 0; static word last_bytes_finalized = 0; +#define GC_WORD_MAX (~(word)0) + /* Collect or expand heap in an attempt make the indicated number of */ /* free blocks available. Should be called until the blocks are */ /* available (setting retry value to TRUE unless this is the first call */ @@ -1300,6 +1383,8 @@ GC_INNER GC_bool GC_collect_or_expand(word needed_blocks, } else { blocks_to_get = MAXHINCR; } + if (blocks_to_get > divHBLKSZ(GC_WORD_MAX)) + blocks_to_get = divHBLKSZ(GC_WORD_MAX); } if (!GC_expand_hp_inner(blocks_to_get) @@ -1310,7 +1395,7 @@ GC_INNER GC_bool GC_collect_or_expand(word needed_blocks, GC_gcollect_inner(); GC_ASSERT(GC_bytes_allocd == 0); } else if (GC_fail_count++ < GC_max_retries) { - WARN("Out of Memory! Trying to continue ...\n", 0); + WARN("Out of Memory! Trying to continue...\n", 0); GC_gcollect_inner(); } else { # if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC) diff --git a/src/bdwgc/backgraph.c b/src/bdwgc/backgraph.c index 4b087e43d..4d09ea5b9 100644 --- a/src/bdwgc/backgraph.c +++ b/src/bdwgc/backgraph.c @@ -86,13 +86,13 @@ static back_edges *avail_back_edges = 0; static back_edges * new_back_edges(void) { if (0 == back_edge_space) { - back_edge_space = (back_edges *)GET_MEM( - ROUNDUP_PAGESIZE_IF_MMAP(MAX_BACK_EDGE_STRUCTS - * sizeof(back_edges))); + size_t bytes_to_get = ROUNDUP_PAGESIZE_IF_MMAP(MAX_BACK_EDGE_STRUCTS + * sizeof(back_edges)); + + back_edge_space = (back_edges *)GET_MEM(bytes_to_get); if (NULL == back_edge_space) ABORT("Insufficient memory for back edges"); - GC_add_to_our_memory((ptr_t)back_edge_space, - MAX_BACK_EDGE_STRUCTS*sizeof(back_edges)); + GC_add_to_our_memory((ptr_t)back_edge_space, bytes_to_get); } if (0 != avail_back_edges) { back_edges * result = avail_back_edges; @@ -129,26 +129,32 @@ static size_t n_in_progress = 0; static void push_in_progress(ptr_t p) { if (n_in_progress >= in_progress_size) { - if (in_progress_size == 0) { + ptr_t * new_in_progress_space; + + if (NULL == in_progress_space) { in_progress_size = ROUNDUP_PAGESIZE_IF_MMAP(INITIAL_IN_PROGRESS * sizeof(ptr_t)) / sizeof(ptr_t); - in_progress_space = (ptr_t *)GET_MEM(in_progress_size * sizeof(ptr_t)); - GC_add_to_our_memory((ptr_t)in_progress_space, - in_progress_size * sizeof(ptr_t)); + new_in_progress_space = + (ptr_t *)GET_MEM(in_progress_size * sizeof(ptr_t)); } else { - ptr_t * new_in_progress_space; in_progress_size *= 2; new_in_progress_space = (ptr_t *) GET_MEM(in_progress_size * sizeof(ptr_t)); - GC_add_to_our_memory((ptr_t)new_in_progress_space, - in_progress_size * sizeof(ptr_t)); if (new_in_progress_space != NULL) BCOPY(in_progress_space, new_in_progress_space, n_in_progress * sizeof(ptr_t)); - in_progress_space = new_in_progress_space; - /* FIXME: This just drops the old space. */ } + GC_add_to_our_memory((ptr_t)new_in_progress_space, + in_progress_size * sizeof(ptr_t)); +# ifndef GWW_VDB + GC_scratch_recycle_no_gww(in_progress_space, + n_in_progress * sizeof(ptr_t)); +# elif defined(LINT2) + /* TODO: implement GWW-aware recycling as in alloc_mark_stack */ + GC_noop1((word)in_progress_space); +# endif + in_progress_space = new_in_progress_space; } if (in_progress_space == 0) ABORT("MAKE_BACK_GRAPH: Out of in-progress space: " @@ -227,13 +233,6 @@ static void add_edge(ptr_t p, ptr_t q) ptr_t old_back_ptr = GET_OH_BG_PTR(q); back_edges * be, *be_cont; word i; - static unsigned random_number = 13; -# define GOT_LUCKY_NUMBER (((++random_number) & 0x7f) == 0) - /* A not very random number we use to occasionally allocate a */ - /* back_edges structure even for a single backward edge. This */ - /* prevents us from repeatedly tracing back through very long */ - /* chains, since we will have some place to store height and */ - /* in_progress flags along the way. */ GC_ASSERT(p == GC_base(p) && q == GC_base(q)); if (!GC_HAS_DEBUG_INFO(q) || !GC_HAS_DEBUG_INFO(p)) { @@ -242,6 +241,14 @@ static void add_edge(ptr_t p, ptr_t q) return; } if (0 == old_back_ptr) { + static unsigned random_number = 13; +# define GOT_LUCKY_NUMBER (((++random_number) & 0x7f) == 0) + /* A not very random number we use to occasionally allocate a */ + /* back_edges structure even for a single backward edge. This */ + /* prevents us from repeatedly tracing back through very long */ + /* chains, since we will have some place to store height and */ + /* in_progress flags along the way. */ + SET_OH_BG_PTR(q, p); if (GOT_LUCKY_NUMBER) ensure_struct(q); return; @@ -382,7 +389,8 @@ static word backwards_height(ptr_t p) FOR_EACH_PRED(q, p, { word this_height; if (GC_is_marked(q) && !(FLAG_MANY & (word)GET_OH_BG_PTR(p))) { - GC_COND_LOG_PRINTF("Found bogus pointer from %p to %p\n", q, p); + GC_COND_LOG_PRINTF("Found bogus pointer from %p to %p\n", + (void *)q, (void *)p); /* Reachable object "points to" unreachable one. */ /* Could be caused by our lax treatment of GC descriptors. */ this_height = 1; @@ -463,14 +471,19 @@ GC_INNER void GC_traverse_back_graph(void) void GC_print_back_graph_stats(void) { + GC_ASSERT(I_HOLD_LOCK()); GC_printf("Maximum backwards height of reachable objects at GC %lu is %lu\n", (unsigned long) GC_gc_no, (unsigned long)GC_max_height); if (GC_max_height > GC_max_max_height) { + ptr_t obj = GC_deepest_obj; + GC_max_max_height = GC_max_height; + UNLOCK(); GC_err_printf( "The following unreachable object is last in a longest chain " "of unreachable objects:\n"); - GC_print_heap_obj(GC_deepest_obj); + GC_print_heap_obj(obj); + LOCK(); } GC_COND_LOG_PRINTF("Needed max total of %d back-edge structs\n", GC_n_back_edge_structs); diff --git a/src/bdwgc/blacklst.c b/src/bdwgc/blacklst.c index dcac51a7a..c06fbddec 100644 --- a/src/bdwgc/blacklst.c +++ b/src/bdwgc/blacklst.c @@ -60,7 +60,7 @@ GC_INNER void GC_default_print_heap_obj_proc(ptr_t p) int kind = HDR(base)->hb_obj_kind; GC_err_printf("object at %p of appr. %lu bytes (%s)\n", - base, (unsigned long)GC_size(base), + (void *)base, (unsigned long)GC_size(base), kind == PTRFREE ? "atomic" : IS_UNCOLLECTABLE(kind) ? "uncollectable" : "composite"); } @@ -75,7 +75,7 @@ GC_INNER void (*GC_print_heap_obj)(ptr_t p) = GC_default_print_heap_obj_proc; if (0 == base) { GC_err_printf("Black listing (%s) %p referenced from %p in %s\n", - kind_str, (ptr_t)p, source, + kind_str, (void *)p, (void *)source, NULL != source ? "root set" : "register"); } else { /* FIXME: We can't call the debug version of GC_print_heap_obj */ @@ -83,8 +83,8 @@ GC_INNER void (*GC_print_heap_obj)(ptr_t p) = GC_default_print_heap_obj_proc; /* the world is stopped. */ GC_err_printf("Black listing (%s) %p referenced from %p in" " object at %p of appr. %lu bytes\n", - kind_str, (ptr_t)p, source, - base, (unsigned long)GC_size(base)); + kind_str, (void *)p, (void *)source, + (void *)base, (unsigned long)GC_size(base)); } } #endif /* PRINT_BLACK_LIST */ @@ -109,6 +109,7 @@ GC_INNER void GC_bl_init(void) if (!GC_all_interior_pointers) { GC_bl_init_no_interiors(); } + GC_ASSERT(NULL == GC_old_stack_bl && NULL == GC_incomplete_stack_bl); GC_old_stack_bl = (word *)GC_scratch_alloc(sizeof(page_hash_table)); GC_incomplete_stack_bl = (word *)GC_scratch_alloc(sizeof(page_hash_table)); if (GC_old_stack_bl == 0 || GC_incomplete_stack_bl == 0) { @@ -281,7 +282,7 @@ static word total_stack_black_listed(void) for (i = 0; i < GC_n_heap_sects; i++) { struct hblk * start = (struct hblk *) GC_heap_sects[i].hs_start; - struct hblk * endp1 = start + GC_heap_sects[i].hs_bytes/HBLKSIZE; + struct hblk * endp1 = start + divHBLKSZ(GC_heap_sects[i].hs_bytes); total += GC_number_stack_black_listed(start, endp1); } diff --git a/src/bdwgc/checksums.c b/src/bdwgc/checksums.c index f0f902a33..4847661a1 100644 --- a/src/bdwgc/checksums.c +++ b/src/bdwgc/checksums.c @@ -39,18 +39,21 @@ STATIC word GC_faulted[NSUMS] = { 0 }; STATIC size_t GC_n_faulted = 0; -void GC_record_fault(struct hblk * h) -{ - word page = ROUNDUP_PAGESIZE((word)h); +#if defined(MPROTECT_VDB) && !defined(DARWIN) + void GC_record_fault(struct hblk * h) + { + word page = (word)h & ~(GC_page_size - 1); + GC_ASSERT(GC_page_size != 0); if (GC_n_faulted >= NSUMS) ABORT("write fault log overflowed"); GC_faulted[GC_n_faulted++] = page; -} + } +#endif STATIC GC_bool GC_was_faulted(struct hblk *h) { size_t i; - word page = ROUNDUP_PAGESIZE((word)h); + word page = (word)h & ~(GC_page_size - 1); for (i = 0; i < GC_n_faulted; ++i) { if (GC_faulted[i] == page) return TRUE; @@ -90,8 +93,8 @@ STATIC word GC_checksum(struct hblk *h) int GC_n_dirty_errors = 0; int GC_n_faulted_dirty_errors = 0; int GC_n_changed_errors = 0; -int GC_n_clean = 0; -int GC_n_dirty = 0; +unsigned long GC_n_clean = 0; +unsigned long GC_n_dirty = 0; STATIC void GC_update_check_page(struct hblk *h, int index) { @@ -196,14 +199,13 @@ void GC_check_dirty(void) } out: GC_COND_LOG_PRINTF("Checked %lu clean and %lu dirty pages\n", - (unsigned long)GC_n_clean, (unsigned long)GC_n_dirty); + GC_n_clean, GC_n_dirty); if (GC_n_dirty_errors > 0) { GC_err_printf("Found %d dirty bit errors (%d were faulted)\n", GC_n_dirty_errors, GC_n_faulted_dirty_errors); } if (GC_n_changed_errors > 0) { - GC_err_printf("Found %lu changed bit errors\n", - (unsigned long)GC_n_changed_errors); + GC_err_printf("Found %d changed bit errors\n", GC_n_changed_errors); GC_err_printf( "These may be benign (provoked by nonpointer changes)\n"); # ifdef THREADS diff --git a/src/bdwgc/configure b/src/bdwgc/configure index 2ba70b67d..bc062644e 100755 --- a/src/bdwgc/configure +++ b/src/bdwgc/configure @@ -1,8 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for gc 7.5.0. +# Generated by GNU Autoconf 2.69 for gc 7.6.8. # -# Report bugs to . +# Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -275,10 +275,10 @@ fi $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and -$0: bdwgc@lists.opendylan.org about your system, including -$0: any error possibly output before this message. Then -$0: install a modern shell, or manually run the script -$0: under such a shell if you do have one." +$0: https://github.com/ivmai/bdwgc/issues about your +$0: system, including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." fi exit 1 fi @@ -590,9 +590,9 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='gc' PACKAGE_TARNAME='gc' -PACKAGE_VERSION='7.5.0' -PACKAGE_STRING='gc 7.5.0' -PACKAGE_BUGREPORT='bdwgc@lists.opendylan.org' +PACKAGE_VERSION='7.6.8' +PACKAGE_STRING='gc 7.6.8' +PACKAGE_BUGREPORT='https://github.com/ivmai/bdwgc/issues' PACKAGE_URL='' ac_unique_file="gcj_mlc.c" @@ -647,8 +647,11 @@ ATOMIC_OPS_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG +ENABLE_DOCS_FALSE +ENABLE_DOCS_TRUE SINGLE_GC_OBJ_FALSE SINGLE_GC_OBJ_TRUE +WERROR_CFLAGS USE_LIBDIR_FALSE USE_LIBDIR_TRUE UNWINDLIBS @@ -672,6 +675,8 @@ AVOID_CPP_LIB_FALSE AVOID_CPP_LIB_TRUE ASM_WITH_CPP_UNSUPPORTED_FALSE ASM_WITH_CPP_UNSUPPORTED_TRUE +PTHREAD_START_STANDALONE_FALSE +PTHREAD_START_STANDALONE_TRUE WIN32_THREADS_FALSE WIN32_THREADS_TRUE DARWIN_THREADS_FALSE @@ -681,6 +686,7 @@ PTHREADS_TRUE THREADS_FALSE THREADS_TRUE THREADDLLIBS +CFLAGS_EXTRA GC_CFLAGS CXXCPP CPP @@ -846,7 +852,10 @@ enable_large_config enable_handle_fork enable_gc_assertions enable_munmap +enable_werror enable_single_obj_compilation +enable_gcov +enable_docs with_libatomic_ops ' ac_precious_vars='build_alias @@ -1410,7 +1419,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures gc 7.5.0 to adapt to many kinds of systems. +\`configure' configures gc 7.6.8 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1481,7 +1490,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of gc 7.5.0:";; + short | recursive ) echo "Configuration of gc 7.6.8:";; esac cat <<\_ACEOF @@ -1506,25 +1515,28 @@ Optional Features: --enable-threads=TYPE choose threading package --enable-parallel-mark parallelize marking and free list construction --enable-cplusplus install C++ support - --disable-gcj-support Disable support for gcj. - --enable-sigrt-signals Force GC to use SIGRTMIN-based signals for thread + --disable-gcj-support disable support for gcj + --enable-sigrt-signals force GC to use SIGRTMIN-based signals for thread suspend/resume --enable-gc-debug include full support for pointer backtracing etc. --disable-java-finalization - Disable support for java finalization. + disable support for java finalization --disable-atomic-uncollectible - Disable support for atomic uncollectible allocation. + disable support for atomic uncollectible allocation --enable-redirect-malloc - Redirect malloc and friends to GC routines - --disable-disclaim Disable alternative (more efficient) finalization - interface. - --enable-large-config Optimize for large (> 100 MB) heap or root set - --enable-handle-fork Attempt to ensure a usable collector after fork() in - multi-threaded programs. + redirect malloc and friends to GC routines + --disable-disclaim disable alternative (more efficient) finalization + interface + --enable-large-config optimize for large (> 100 MB) heap or root set + --enable-handle-fork attempt to ensure a usable collector after fork() in + multi-threaded programs --enable-gc-assertions collector-internal assertion checking --enable-munmap=N return page to the os if empty for N collections + --enable-werror pass -Werror to the C compiler --enable-single-obj-compilation - Compile all library .c files into single .o + compile all libgc source files into single .o + --enable-gcov turn on code coverage analysis + --disable-docs do not build and install documentation Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1542,7 +1554,7 @@ Optional Packages: configuring with a cross compiler --with-cross-host=HOST configuring with a cross compiler --with-libatomic-ops=yes|no|check - Use a external libatomic_ops? (default: check) + Use an external libatomic_ops? (default: check) Some influential environment variables: CC C compiler command @@ -1573,7 +1585,7 @@ Some influential environment variables: Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. -Report bugs to . +Report bugs to . _ACEOF ac_status=$? fi @@ -1636,7 +1648,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -gc configure 7.5.0 +gc configure 7.6.8 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2102,9 +2114,9 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( $as_echo "## ---------------------------------------- ## -## Report this to bdwgc@lists.opendylan.org ## -## ---------------------------------------- ##" +( $as_echo "## ---------------------------------------------------- ## +## Report this to https://github.com/ivmai/bdwgc/issues ## +## ---------------------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac @@ -2126,7 +2138,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by gc $as_me 7.5.0, which was +It was created by gc $as_me 7.6.8, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2474,7 +2486,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu - ## version must conform to [0-9]+[.][0-9]+[.][0-9]+ + ac_aux_dir= @@ -2617,7 +2629,42 @@ test -n "$target_alias" && NONENONEs,x,x, && program_prefix=${target_alias}- -GC_SET_VERSION + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking GC version numbers" >&5 +$as_echo_n "checking GC version numbers... " >&6; } + GC_VERSION_MAJOR=`echo $PACKAGE_VERSION | sed 's/^\([0-9][0-9]*\)[.].*$/\1/g'` + GC_VERSION_MINOR=`echo $PACKAGE_VERSION | sed 's/^[^.]*[.]\([0-9][0-9]*\).*$/\1/g'` + GC_VERSION_MICRO=`echo $PACKAGE_VERSION | sed 's/^[^.]*[.][^.]*[.]\([0-9][0-9]*\)$/\1/g'` + + if test :$GC_VERSION_MAJOR: = :: \ + -o :$GC_VERSION_MINOR: = :: \ + -o :$GC_VERSION_MICRO: = :: ; + then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: invalid" >&5 +$as_echo "invalid" >&6; } + as_fn_error $? "nonconforming PACKAGE_VERSION='$PACKAGE_VERSION'" "$LINENO" 5 + fi + + +cat >>confdefs.h <<_ACEOF +#define GC_VERSION_MAJOR $GC_VERSION_MAJOR +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define GC_VERSION_MINOR $GC_VERSION_MINOR +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define GC_VERSION_MICRO $GC_VERSION_MICRO +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: major=$GC_VERSION_MAJOR minor=$GC_VERSION_MINOR \ + micro=$GC_VERSION_MICRO" >&5 +$as_echo "major=$GC_VERSION_MAJOR minor=$GC_VERSION_MINOR \ + micro=$GC_VERSION_MICRO" >&6; } + am__api_version='1.15' # Find a good install program. We prefer a C program (faster), @@ -3104,7 +3151,7 @@ fi # Define the identity of the package. PACKAGE='gc' - VERSION='7.5.0' + VERSION='7.6.8' cat >>confdefs.h <<_ACEOF @@ -16098,8 +16145,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu # Only expand once: -# Note: If Autoconf reports that LIBTOOL (or AC_ENABLE_SHARED, or -# AC_PROG_LIBTOOL) is undefined, Libtool installation should be checked. # Special CFLAGS to use when building gc_cflags="" @@ -16118,7 +16163,7 @@ else if test :$GCC: != :"yes": ; then gc_cflags="${gc_flags} +ESdbgasm" fi - # :TODO: actaully we should check using Autoconf if + # :TODO: actually we should check using Autoconf if # the compiler supports this option. ;; esac @@ -16157,6 +16202,8 @@ esac GC_CFLAGS=${gc_cflags} + + # Check whether --enable-threads was given. if test "${enable_threads+set}" = set; then : enableval=$enable_threads; THREADS=$enableval @@ -16227,6 +16274,9 @@ fi + +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $CFLAGS_EXTRA" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : @@ -16269,10 +16319,11 @@ _ACEOF ;; esac +CFLAGS="$old_CFLAGS" THREADDLLIBS= need_atomic_ops_asm=false -## Libraries needed to support dynamic loading and/or threads. +# Libraries needed to support dynamic loading and/or threads. case "$THREADS" in no | none | single) THREADS=none @@ -16333,9 +16384,9 @@ fi $as_echo "#define THREAD_LOCAL_ALLOC 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&5 -$as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;}; +$as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;} ;; - *-*-linux*) + *-*-*linux* | *-*-nacl*) $as_echo "#define GC_LINUX_THREADS 1" >>confdefs.h $as_echo "#define _REENTRANT 1" >>confdefs.h @@ -16346,6 +16397,12 @@ $as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;}; $as_echo "#define _REENTRANT 1" >>confdefs.h + ;; + *-*-haiku*) + $as_echo "#define GC_HAIKU_THREADS 1" >>confdefs.h + + $as_echo "#define _REENTRANT 1" >>confdefs.h + ;; *-*-hpux11*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Only HP/UX 11 POSIX threads are supported.\"" >&5 @@ -16361,7 +16418,7 @@ $as_echo "$as_me: WARNING: \"Only HP/UX 11 POSIX threads are supported.\"" >&2;} $as_echo "#define THREAD_LOCAL_ALLOC 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&5 -$as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;}; +$as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;} THREADDLLIBS="-lpthread -lrt" # HPUX needs REENTRANT for the _r calls. @@ -16378,7 +16435,7 @@ $as_echo "$as_me: WARNING: \"Only HP-UX 11 POSIX threads are supported.\"" >&2;} THREADDLLIBS=-pthread AM_CFLAGS="$AM_CFLAGS -pthread" ;; - *-*-freebsd*) + *-*-dragonfly* | *-*-freebsd*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"FreeBSD does not yet fully support threads with Boehm GC.\"" >&5 $as_echo "$as_me: WARNING: \"FreeBSD does not yet fully support threads with Boehm GC.\"" >&2;} $as_echo "#define GC_FREEBSD_THREADS 1" >>confdefs.h @@ -16402,8 +16459,12 @@ $as_echo "$as_me: WARNING: \"FreeBSD does not yet fully support threads with Boe $as_echo "#define PARALLEL_MARK 1" >>confdefs.h fi - $as_echo "#define THREAD_LOCAL_ALLOC 1" >>confdefs.h + # FIXME: For a reason, gctest hangs up on kFreeBSD if both of + # THREAD_LOCAL_ALLOC and GC_ENABLE_SUSPEND_THREAD are defined. + if test x"$enable_gcj_support" = xno; then + $as_echo "#define THREAD_LOCAL_ALLOC 1" >>confdefs.h + fi $as_echo "#define USE_COMPILER_TLS 1" >>confdefs.h ;; @@ -16476,7 +16537,7 @@ $as_echo "$as_me: WARNING: \"Only on NetBSD 2.0 or later.\"" >&2;} $as_echo "#define GC_DARWIN_THREADS 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&5 -$as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;}; +$as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;} # Parallel-mark is not well-tested on Darwin if test "${enable_parallel_mark}" != no; then $as_echo "#define PARALLEL_MARK 1" >>confdefs.h @@ -16552,7 +16613,7 @@ $as_echo "$THREADDLLIBS" >&6; } $as_echo "#define THREAD_LOCAL_ALLOC 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&5 -$as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;}; +$as_echo "$as_me: WARNING: \"Explicit GC_INIT() calls may be required.\"" >&2;} $as_echo "#define GC_DGUX386_THREADS 1" >>confdefs.h @@ -16619,18 +16680,25 @@ fi compiler_suncc=no +pthread_start_standalone=no case "$host" in - powerpc-*-darwin*) + *-*-*linux*) + # Turn on the workaround described in pthread_start.c. + if test "$THREADS" = posix; then : + pthread_start_standalone=yes +fi + ;; + powerpc-*-darwin*) powerpc_darwin=true ;; - *-*-solaris*) + *-*-solaris*) if test "$GCC" != yes; then # Solaris SunCC compiler_suncc=yes CFLAGS="-O $CFLAGS" fi ;; - *-*-wince*) + *-*-wince*) if test "$enable_gc_debug" != "no"; then $as_echo "#define GC_READ_ENV_FILE 1" >>confdefs.h @@ -16638,11 +16706,19 @@ $as_echo "#define GC_READ_ENV_FILE 1" >>confdefs.h fi ;; esac + if test x$pthread_start_standalone = xyes; then + PTHREAD_START_STANDALONE_TRUE= + PTHREAD_START_STANDALONE_FALSE='#' +else + PTHREAD_START_STANDALONE_TRUE='#' + PTHREAD_START_STANDALONE_FALSE= +fi + if test "$GCC" = yes; then # Output all warnings. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc -Wextra" >&5 -$as_echo_n "checking for gcc -Wextra... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wextra" >&5 +$as_echo_n "checking whether compiler supports -Wextra... " >&6; } old_CFLAGS="$CFLAGS" CFLAGS="-Wextra $CFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -16670,7 +16746,36 @@ $as_echo "$ac_cv_cc_wextra" >&6; } else WEXTRA="-W" fi - CFLAGS="-Wall $WEXTRA $CFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wpedantic" >&5 +$as_echo_n "checking whether compiler supports -Wpedantic... " >&6; } + CFLAGS="-Wpedantic -Wno-long-long $CFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + extern int quiet; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_cc_pedantic=yes +else + ac_cv_cc_pedantic=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$old_CFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_pedantic" >&5 +$as_echo "$ac_cv_cc_pedantic" >&6; } + WPEDANTIC= + if test "$ac_cv_cc_pedantic" = yes; then : + WPEDANTIC="-Wpedantic -Wno-long-long" +fi + CFLAGS="-Wall $WEXTRA $WPEDANTIC $CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xlc" >&5 @@ -16718,8 +16823,8 @@ fi if test "$GCC" = yes; then # Disable aliasing optimization unless forced to. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc supports -fno-strict-aliasing" >&5 -$as_echo_n "checking whether gcc supports -fno-strict-aliasing... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fno-strict-aliasing" >&5 +$as_echo_n "checking whether compiler supports -fno-strict-aliasing... " >&6; } ac_cv_fno_strict_aliasing=no for cflag in $CFLAGS; do case "$cflag" in @@ -16757,6 +16862,42 @@ fi $as_echo "$ac_cv_fno_strict_aliasing" >&6; } fi +# Check for getcontext (uClibc can be configured without it, for example) +for ac_func in getcontext +do : + ac_fn_c_check_func "$LINENO" "getcontext" "ac_cv_func_getcontext" +if test "x$ac_cv_func_getcontext" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETCONTEXT 1 +_ACEOF + +fi +done + +if test "$ac_cv_func_getcontext" = "no"; then + +$as_echo "#define NO_GETCONTEXT 1" >>confdefs.h + +fi + +# Check whether dl_iterate_phdr exists (as a strong symbol). +for ac_func in dl_iterate_phdr +do : + ac_fn_c_check_func "$LINENO" "dl_iterate_phdr" "ac_cv_func_dl_iterate_phdr" +if test "x$ac_cv_func_dl_iterate_phdr" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DL_ITERATE_PHDR 1 +_ACEOF + +fi +done + +if test "$ac_cv_func_dl_iterate_phdr" = "yes"; then + +$as_echo "#define HAVE_DL_ITERATE_PHDR 1" >>confdefs.h + +fi + case "$host" in # While IRIX 6 has libdl for the O32 and N32 ABIs, it's missing for N64 # and unnecessary everywhere. @@ -16825,6 +16966,25 @@ else fi +# Check for various headers. +for ac_header in execinfo.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default" +if test "x$ac_cv_header_execinfo_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EXECINFO_H 1 +_ACEOF + +fi + +done + +if test "$ac_cv_header_execinfo_h" != "yes"; then + +$as_echo "#define GC_MISSING_EXECINFO_H 1" >>confdefs.h + +fi + # extra LD Flags which are required for targets case "${host}" in *-*-darwin*) @@ -16948,8 +17108,8 @@ if test "${enable_shared}" = yes; then if test "$GCC" = yes; then # Pass -fvisibility=hidden option if supported - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc supports -fvisibility" >&5 -$as_echo_n "checking whether gcc supports -fvisibility... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fvisibility" >&5 +$as_echo_n "checking whether compiler supports -fvisibility... " >&6; } old_CFLAGS="$CFLAGS" CFLAGS="-Werror -fvisibility=hidden $CFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -16972,6 +17132,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$old_CFLAGS" if test "$ac_cv_fvisibility_hidden" = yes; then : CFLAGS="-DGC_VISIBILITY_HIDDEN_SET -fvisibility=hidden $CFLAGS" +else + CFLAGS="-DGC_NO_VISIBILITY $CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_fvisibility_hidden" >&5 $as_echo "$ac_cv_fvisibility_hidden" >&6; } @@ -17016,6 +17178,10 @@ $as_echo "#define SUNOS53_SHARED_LIB 1" >>confdefs.h ;; ia64-*-*) machdep="ia64_save_regs_in_stack.lo" + ;; + *-*-nacl*) + $as_echo "#define NO_EXECUTE_PERMISSION 1" >>confdefs.h + ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $machdep" >&5 @@ -17039,14 +17205,8 @@ if test "${with_cross_host+set}" = set; then : fi -# automake wants to see AC_EXEEXT. But we don't need it. And having -# it is actually a problem, because the compiler we're passed can't -# necessarily do a full link. So we fool automake here. if false; then - # autoconf 2.50 runs AC_EXEEXT by default, and the macro expands - # to nothing, so nothing would remain between `then' and `fi' if it - # were not for the `:' below. - : + : fi @@ -17094,6 +17254,9 @@ if test x"$enable_gcj_support" != xno; then $as_echo "#define GC_GCJ_SUPPORT 1" >>confdefs.h + +$as_echo "#define GC_ENABLE_SUSPEND_THREAD 1" >>confdefs.h + fi # Check whether --enable-sigrt-signals was given. @@ -17217,6 +17380,8 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dladdr" >&5 $as_echo_n "checking for dladdr... " >&6; } have_dladdr=no +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $CFLAGS_EXTRA" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -17237,6 +17402,7 @@ if ac_fn_c_try_compile "$LINENO"; then : have_dladdr=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +CFLAGS="$old_CFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_dladdr" >&5 $as_echo "$have_dladdr" >&6; } if test x"$have_dladdr" = xyes; then @@ -17254,7 +17420,6 @@ fi - ## :GOTCHA: we do not check anything but sys/dg_sys_info.h if test $ac_is_dgux = yes; then dgux_spec_opts="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2" CFLAGS="$dgux_spec_opts $CFLAGS" @@ -17285,7 +17450,7 @@ fi if test x"$enable_atomic_uncollectible" != x"no"; then -$as_echo "#define ATOMIC_UNCOLLECTABLE 1" >>confdefs.h +$as_echo "#define GC_ATOMIC_UNCOLLECTABLE 1" >>confdefs.h fi @@ -17339,7 +17504,6 @@ if test "${enable_large_config+set}" = set; then : enableval=$enable_large_config; fi - if test "${enable_large_config}" = yes; then $as_echo "#define LARGE_CONFIG 1" >>confdefs.h @@ -17351,7 +17515,6 @@ if test "${enable_handle_fork+set}" = set; then : enableval=$enable_handle_fork; fi - if test "${enable_handle_fork}" = yes; then $as_echo "#define HANDLE_FORK 1" >>confdefs.h @@ -17395,18 +17558,11 @@ if test "${enable_munmap+set}" = set; then : enableval=$enable_munmap; MUNMAP_THRESHOLD=$enableval fi -if test "${enable_munmap}" != ""; then +if test x$enable_munmap != x -a x$enable_munmap != xno; then $as_echo "#define USE_MMAP 1" >>confdefs.h - case "$host" in - *-*-cygwin*) - # Workaround for Cygwin: use VirtualAlloc since mmap(PROT_NONE) fails -$as_echo "#define USE_WINALLOC 1" >>confdefs.h - - ;; - esac $as_echo "#define USE_MUNMAP 1" >>confdefs.h @@ -17435,6 +17591,24 @@ else fi +# Check whether --enable-werror was given. +if test "${enable_werror+set}" = set; then : + enableval=$enable_werror; werror_flag=$enableval +else + werror_flag=no +fi + +if test x$werror_flag = xyes; then + WERROR_CFLAGS="-Werror" + case "$host" in + # _dyld_bind_fully_image_containing_address is deprecated in OS X 10.5+ + *-*-darwin*) + WERROR_CFLAGS="$WERROR_CFLAGS -Wno-deprecated-declarations" + ;; + esac +fi + + # Check whether --enable-single-obj-compilation was given. if test "${enable_single_obj_compilation+set}" = set; then : enableval=$enable_single_obj_compilation; single_obj_compilation=yes @@ -17449,6 +17623,37 @@ else fi +# Check whether --enable-gcov was given. +if test "${enable_gcov+set}" = set; then : + enableval=$enable_gcov; +fi + +if test "$enable_gcov" = "yes"; then + CFLAGS="$CFLAGS --coverage" + if test "${enable_shared}" = no; then + # FIXME: As of g++-4.8.4/x86_64, in case of shared library build, test_cpp + # linkage fails with "hidden symbol atexit is referenced by DSO" message. + CXXFLAGS="$CXXFLAGS --coverage" + fi + # Turn off optimization to get accurate line numbers. + CFLAGS=`echo "$CFLAGS" | sed -e 's/-O\(1\|2\|3\|4\|s\|fast\)\?//g'` + CXXFLAGS=`echo "$CXXFLAGS" | sed -e 's/-O\(1\|2\|3\|4\|s\|fast\)\?//g'` +fi + +# Check whether --enable-docs was given. +if test "${enable_docs+set}" = set; then : + enableval=$enable_docs; +fi + + if test x$enable_docs != xno; then + ENABLE_DOCS_TRUE= + ENABLE_DOCS_FALSE='#' +else + ENABLE_DOCS_TRUE='#' + ENABLE_DOCS_FALSE= +fi + + # Atomic Ops # ---------- @@ -17463,11 +17668,14 @@ else fi -# Check for an external libatomic_ops if the answer was yes or check. If not -# found, fail on yes, and convert check to no. -# Note: "syntax error near unexpected token ATOMIC_OPS" reported by configure -# means Autotools pkg.m4 file was not found during aclocal.m4 generation. +# Check for an external libatomic_ops if the above answer is "yes" or "check". +# If not found, fail on "yes", and convert "check" to "no". +# First, check that libatomic_ops usage is not disabled explicitly. missing_libatomic_ops=false +if test x"$with_libatomic_ops" != xno -a x"$THREADS" != xnone; then : + missing_libatomic_ops=true +fi + @@ -17588,11 +17796,11 @@ $as_echo "no" >&6; } PKG_CONFIG="" fi fi -if test x"$with_libatomic_ops" != xno; then : +if test x$missing_libatomic_ops = xtrue; then : pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ATOMIC_OPS" >&5 -$as_echo_n "checking for ATOMIC_OPS... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic_ops" >&5 +$as_echo_n "checking for atomic_ops... " >&6; } if test -n "$ATOMIC_OPS_CFLAGS"; then pkg_cv_ATOMIC_OPS_CFLAGS="$ATOMIC_OPS_CFLAGS" @@ -17632,7 +17840,7 @@ fi if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -17648,20 +17856,29 @@ fi # Put the nasty error message in config.log where it belongs echo "$ATOMIC_OPS_PKG_ERRORS" >&5 - missing_libatomic_ops=true + elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - missing_libatomic_ops=true + else ATOMIC_OPS_CFLAGS=$pkg_cv_ATOMIC_OPS_CFLAGS ATOMIC_OPS_LIBS=$pkg_cv_ATOMIC_OPS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } + missing_libatomic_ops=false +fi +fi + +if test x$missing_libatomic_ops = xtrue; then : + ac_fn_c_check_header_mongrel "$LINENO" "atomic_ops.h" "ac_cv_header_atomic_ops_h" "$ac_includes_default" +if test "x$ac_cv_header_atomic_ops_h" = xyes; then : + missing_libatomic_ops=false +fi + fi -fi -if test x$missing_libatomic_ops = xtrue ; then : +if test x$missing_libatomic_ops = xtrue; then : if test x"$with_libatomic_ops" != xcheck; then : as_fn_error $? "An external libatomic_ops was not found" "$LINENO" 5 fi @@ -17670,7 +17887,8 @@ fi # If we have neither an external or an internal version, offer a useful hint # and exit. -if test x"$with_libatomic_ops" = xno -a ! -e "$srcdir/libatomic_ops"; then : +if test x"$with_libatomic_ops" = xno \ + -a ! -e "$srcdir/libatomic_ops/src/atomic_ops.h"; then : as_fn_error $? "libatomic_ops is required. You can either install it on your system, or fetch and unpack a recent version into the source directory and link or rename it to libatomic_ops." "$LINENO" 5 @@ -17682,8 +17900,13 @@ $as_echo_n "checking which libatomic_ops to use... " >&6; } if test x"$with_libatomic_ops" != xno; then : + if test x"$THREADS" != xnone; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: external" >&5 $as_echo "external" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: internal" >&5 $as_echo "internal" >&6; } @@ -17879,6 +18102,10 @@ if test -z "${WIN32_THREADS_TRUE}" && test -z "${WIN32_THREADS_FALSE}"; then as_fn_error $? "conditional \"WIN32_THREADS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${PTHREAD_START_STANDALONE_TRUE}" && test -z "${PTHREAD_START_STANDALONE_FALSE}"; then + as_fn_error $? "conditional \"PTHREAD_START_STANDALONE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${ASM_WITH_CPP_UNSUPPORTED_TRUE}" && test -z "${ASM_WITH_CPP_UNSUPPORTED_FALSE}"; then as_fn_error $? "conditional \"ASM_WITH_CPP_UNSUPPORTED\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -17911,6 +18138,10 @@ if test -z "${SINGLE_GC_OBJ_TRUE}" && test -z "${SINGLE_GC_OBJ_FALSE}"; then as_fn_error $? "conditional \"SINGLE_GC_OBJ\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${ENABLE_DOCS_TRUE}" && test -z "${ENABLE_DOCS_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_DOCS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${USE_INTERNAL_LIBATOMIC_OPS_TRUE}" && test -z "${USE_INTERNAL_LIBATOMIC_OPS_FALSE}"; then as_fn_error $? "conditional \"USE_INTERNAL_LIBATOMIC_OPS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -18316,7 +18547,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by gc $as_me 7.5.0, which was +This file was extended by gc $as_me 7.6.8, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18376,13 +18607,13 @@ $config_headers Configuration commands: $config_commands -Report bugs to ." +Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -gc config.status 7.5.0 +gc config.status 7.6.8 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/src/bdwgc/configure.ac b/src/bdwgc/configure.ac index 45ab69329..9a2951e16 100644 --- a/src/bdwgc/configure.ac +++ b/src/bdwgc/configure.ac @@ -1,4 +1,6 @@ # Copyright (c) 1999-2001 by Red Hat, Inc. All rights reserved. +# Copyright (c) 2005-2009 Hewlett-Packard Development Company, L.P. +# Copyright (c) 2009-2018 Ivan Maidanski # # THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED # OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -11,15 +13,16 @@ dnl Process this file with autoconf to produce configure. -# Initialization -AC_INIT(gc,7.5.0,bdwgc@lists.opendylan.org) - ## version must conform to [0-9]+[.][0-9]+[.][0-9]+ +dnl Initialization. +AC_INIT(gc,7.6.8,https://github.com/ivmai/bdwgc/issues) +dnl Version must conform to: [0-9]+[.][0-9]+[.][0-9]+ + AC_CONFIG_SRCDIR(gcj_mlc.c) AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_TARGET AC_PREREQ(2.61) GC_SET_VERSION -AM_INIT_AUTOMAKE([foreign dist-bzip2 nostdinc subdir-objects]) +AM_INIT_AUTOMAKE([foreign nostdinc subdir-objects]) AC_CONFIG_HEADERS([include/config.h]) AM_MAINTAINER_MODE @@ -31,8 +34,8 @@ AC_PROG_CXX AM_PROG_AS AC_PROG_INSTALL LT_INIT -# Note: If Autoconf reports that LIBTOOL (or AC_ENABLE_SHARED, or -# AC_PROG_LIBTOOL) is undefined, Libtool installation should be checked. +dnl Note: If Autoconf reports that LIBTOOL (or AC_ENABLE_SHARED, or +dnl AC_PROG_LIBTOOL) is undefined, Libtool installation should be checked. # Special CFLAGS to use when building gc_cflags="" @@ -51,7 +54,7 @@ else if test :$GCC: != :"yes": ; then gc_cflags="${gc_flags} +ESdbgasm" fi - # :TODO: actaully we should check using Autoconf if + # :TODO: actually we should check using Autoconf if # the compiler supports this option. ;; esac @@ -90,6 +93,9 @@ esac GC_CFLAGS=${gc_cflags} AC_SUBST(GC_CFLAGS) +dnl Extra user-defined flags to pass both to C and C++ compilers. +AC_SUBST([CFLAGS_EXTRA]) + AC_ARG_ENABLE(threads, [AC_HELP_STRING([--enable-threads=TYPE], [choose threading package])], THREADS=$enableval, @@ -137,6 +143,7 @@ AH_TEMPLATE([GC_AIX_THREADS], [Define to support IBM AIX threads.]) AH_TEMPLATE([GC_DARWIN_THREADS], [Define to support Darwin pthreads.]) AH_TEMPLATE([GC_FREEBSD_THREADS], [Define to support FreeBSD pthreads.]) AH_TEMPLATE([GC_GNU_THREADS], [Define to support GNU pthreads.]) +AH_TEMPLATE([GC_HAIKU_THREADS], [Define to support Haiku pthreads.]) AH_TEMPLATE([GC_HPUX_THREADS], [Define to support HP/UX 11 pthreads.]) AH_TEMPLATE([GC_IRIX_THREADS], [Define to support Irix pthreads.]) AH_TEMPLATE([GC_LINUX_THREADS], [Define to support pthreads on Linux.]) @@ -164,11 +171,14 @@ AH_TEMPLATE([GC_DLL], [Define to build dynamic libraries with only API symbols exposed.]) dnl Check for a flavor of supported inline keyword. +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $CFLAGS_EXTRA" AC_C_INLINE +CFLAGS="$old_CFLAGS" THREADDLLIBS= need_atomic_ops_asm=false -## Libraries needed to support dynamic loading and/or threads. +# Libraries needed to support dynamic loading and/or threads. case "$THREADS" in no | none | single) THREADS=none @@ -185,9 +195,9 @@ case "$THREADS" in AC_DEFINE(PARALLEL_MARK) fi AC_DEFINE(THREAD_LOCAL_ALLOC) - AC_MSG_WARN("Explicit GC_INIT() calls may be required."); + AC_MSG_WARN("Explicit GC_INIT() calls may be required.") ;; - *-*-linux*) + *-*-*linux* | *-*-nacl*) AC_DEFINE(GC_LINUX_THREADS) AC_DEFINE(_REENTRANT) ;; @@ -195,6 +205,10 @@ case "$THREADS" in AC_DEFINE(GC_AIX_THREADS) AC_DEFINE(_REENTRANT) ;; + *-*-haiku*) + AC_DEFINE(GC_HAIKU_THREADS) + AC_DEFINE(_REENTRANT) + ;; *-*-hpux11*) AC_MSG_WARN("Only HP/UX 11 POSIX threads are supported.") AC_DEFINE(GC_HPUX_THREADS) @@ -203,7 +217,7 @@ case "$THREADS" in AC_DEFINE(PARALLEL_MARK) fi AC_DEFINE(THREAD_LOCAL_ALLOC) - AC_MSG_WARN("Explicit GC_INIT() calls may be required."); + AC_MSG_WARN("Explicit GC_INIT() calls may be required.") THREADDLLIBS="-lpthread -lrt" # HPUX needs REENTRANT for the _r calls. AC_DEFINE(_REENTRANT, 1, [Required define if using POSIX threads.]) @@ -216,7 +230,7 @@ case "$THREADS" in THREADDLLIBS=-pthread AM_CFLAGS="$AM_CFLAGS -pthread" ;; - *-*-freebsd*) + *-*-dragonfly* | *-*-freebsd*) AC_MSG_WARN("FreeBSD does not yet fully support threads with Boehm GC.") AC_DEFINE(GC_FREEBSD_THREADS) AM_CFLAGS="$AM_CFLAGS -pthread" @@ -233,7 +247,11 @@ case "$THREADS" in if test "${enable_parallel_mark}" = yes; then AC_DEFINE(PARALLEL_MARK) fi - AC_DEFINE(THREAD_LOCAL_ALLOC) + # FIXME: For a reason, gctest hangs up on kFreeBSD if both of + # THREAD_LOCAL_ALLOC and GC_ENABLE_SUSPEND_THREAD are defined. + if test x"$enable_gcj_support" = xno; then + AC_DEFINE(THREAD_LOCAL_ALLOC) + fi AC_DEFINE(USE_COMPILER_TLS) ;; *-*-gnu*) @@ -286,7 +304,7 @@ case "$THREADS" in ;; *-*-darwin*) AC_DEFINE(GC_DARWIN_THREADS) - AC_MSG_WARN("Explicit GC_INIT() calls may be required."); + AC_MSG_WARN("Explicit GC_INIT() calls may be required.") # Parallel-mark is not well-tested on Darwin if test "${enable_parallel_mark}" != no; then AC_DEFINE(PARALLEL_MARK) @@ -346,7 +364,7 @@ case "$THREADS" in AC_DEFINE(PARALLEL_MARK) fi AC_DEFINE(THREAD_LOCAL_ALLOC) - AC_MSG_WARN("Explicit GC_INIT() calls may be required."); + AC_MSG_WARN("Explicit GC_INIT() calls may be required.") AC_DEFINE([GC_DGUX386_THREADS], 1, [Define to enable support for DB/UX threads on i386.]) AC_DEFINE([DGUX_THREADS], 1, @@ -379,35 +397,52 @@ AM_CONDITIONAL(DARWIN_THREADS, test x$darwin_threads = xtrue) AM_CONDITIONAL(WIN32_THREADS, test x$win32_threads = xtrue) compiler_suncc=no +pthread_start_standalone=no case "$host" in - powerpc-*-darwin*) + *-*-*linux*) + # Turn on the workaround described in pthread_start.c. + AS_IF([test "$THREADS" = posix], [pthread_start_standalone=yes]) + ;; + powerpc-*-darwin*) powerpc_darwin=true ;; - *-*-solaris*) + *-*-solaris*) if test "$GCC" != yes; then # Solaris SunCC compiler_suncc=yes CFLAGS="-O $CFLAGS" fi ;; - *-*-wince*) + *-*-wince*) if test "$enable_gc_debug" != "no"; then AC_DEFINE([GC_READ_ENV_FILE], 1, [Read environment variables from the GC 'env' file.]) fi ;; esac +AM_CONDITIONAL(PTHREAD_START_STANDALONE, + test x$pthread_start_standalone = xyes) if test "$GCC" = yes; then # Output all warnings. - AC_MSG_CHECKING(for gcc -Wextra) + AC_MSG_CHECKING([whether compiler supports -Wextra]) old_CFLAGS="$CFLAGS" CFLAGS="-Wextra $CFLAGS" AC_TRY_COMPILE([],[], [ac_cv_cc_wextra=yes], [ac_cv_cc_wextra=no]) CFLAGS="$old_CFLAGS" AC_MSG_RESULT($ac_cv_cc_wextra) AS_IF([test "$ac_cv_cc_wextra" = yes], [WEXTRA="-Wextra"], [WEXTRA="-W"]) - CFLAGS="-Wall $WEXTRA $CFLAGS" + AC_MSG_CHECKING([whether compiler supports -Wpedantic]) + CFLAGS="-Wpedantic -Wno-long-long $CFLAGS" + AC_TRY_COMPILE([],[ + extern int quiet; + ], [ac_cv_cc_pedantic=yes], [ac_cv_cc_pedantic=no]) + CFLAGS="$old_CFLAGS" + AC_MSG_RESULT($ac_cv_cc_pedantic) + WPEDANTIC= + AS_IF([test "$ac_cv_cc_pedantic" = yes], + [WPEDANTIC="-Wpedantic -Wno-long-long"]) + CFLAGS="-Wall $WEXTRA $WPEDANTIC $CFLAGS" fi AC_MSG_CHECKING(for xlc) @@ -429,7 +464,7 @@ AM_CONDITIONAL([ASM_WITH_CPP_UNSUPPORTED], if test "$GCC" = yes; then # Disable aliasing optimization unless forced to. - AC_MSG_CHECKING([whether gcc supports -fno-strict-aliasing]) + AC_MSG_CHECKING([whether compiler supports -fno-strict-aliasing]) ac_cv_fno_strict_aliasing=no for cflag in $CFLAGS; do case "$cflag" in @@ -451,6 +486,19 @@ if test "$GCC" = yes; then AC_MSG_RESULT($ac_cv_fno_strict_aliasing) fi +# Check for getcontext (uClibc can be configured without it, for example) +AC_CHECK_FUNCS([getcontext]) +if test "$ac_cv_func_getcontext" = "no"; then + AC_DEFINE([NO_GETCONTEXT], [1], [Missing getcontext function.]) +fi + +# Check whether dl_iterate_phdr exists (as a strong symbol). +AC_CHECK_FUNCS([dl_iterate_phdr]) +if test "$ac_cv_func_dl_iterate_phdr" = "yes"; then + AC_DEFINE([HAVE_DL_ITERATE_PHDR], [1], + [Define if 'dl_iterate_phdr' function is available.]) +fi + case "$host" in # While IRIX 6 has libdl for the O32 and N32 ABIs, it's missing for N64 # and unnecessary everywhere. @@ -473,6 +521,12 @@ case "$host" in esac AM_CONDITIONAL(AVOID_CPP_LIB,test $avoid_cpp_lib = yes) +# Check for various headers. +AC_CHECK_HEADERS([execinfo.h]) +if test "$ac_cv_header_execinfo_h" != "yes"; then + AC_DEFINE([GC_MISSING_EXECINFO_H], [1], [Missing execinfo.h header.]) +fi + # extra LD Flags which are required for targets case "${host}" in *-*-darwin*) @@ -555,14 +609,15 @@ if test "${enable_shared}" = yes; then AC_DEFINE(GC_DLL) if test "$GCC" = yes; then # Pass -fvisibility=hidden option if supported - AC_MSG_CHECKING([whether gcc supports -fvisibility]) + AC_MSG_CHECKING([whether compiler supports -fvisibility]) old_CFLAGS="$CFLAGS" CFLAGS="-Werror -fvisibility=hidden $CFLAGS" AC_TRY_COMPILE([],[], [ac_cv_fvisibility_hidden=yes], [ac_cv_fvisibility_hidden=no]) CFLAGS="$old_CFLAGS" AS_IF([test "$ac_cv_fvisibility_hidden" = yes], - [CFLAGS="-DGC_VISIBILITY_HIDDEN_SET -fvisibility=hidden $CFLAGS"]) + [CFLAGS="-DGC_VISIBILITY_HIDDEN_SET -fvisibility=hidden $CFLAGS"], + [CFLAGS="-DGC_NO_VISIBILITY $CFLAGS"]) AC_MSG_RESULT($ac_cv_fvisibility_hidden) fi fi @@ -606,6 +661,9 @@ case "$host" in ia64-*-*) machdep="ia64_save_regs_in_stack.lo" ;; + *-*-nacl*) + AC_DEFINE(NO_EXECUTE_PERMISSION) + ;; esac AC_MSG_RESULT($machdep) addobjs="$addobjs $machdep" @@ -621,13 +679,13 @@ AC_ARG_WITH(target-subdir, AC_ARG_WITH(cross-host, [ --with-cross-host=HOST configuring with a cross compiler]) -# automake wants to see AC_EXEEXT. But we don't need it. And having -# it is actually a problem, because the compiler we're passed can't -# necessarily do a full link. So we fool automake here. +dnl automake wants to see AC_EXEEXT. But we don't need it. And having +dnl it is actually a problem, because the compiler we're passed can't +dnl necessarily do a full link. So we fool automake here. if false; then - # autoconf 2.50 runs AC_EXEEXT by default, and the macro expands - # to nothing, so nothing would remain between `then' and `fi' if it - # were not for the `:' below. + dnl autoconf 2.50 runs AC_EXEEXT by default, and the macro expands + dnl to nothing, so nothing would remain between `then' and `fi' if it + dnl were not for the `:' below. : AC_EXEEXT fi @@ -674,16 +732,17 @@ dnl dnl By default, make the library as general as possible. dnl enable_gcj_support=no AC_ARG_ENABLE(gcj-support, - [AC_HELP_STRING([--disable-gcj-support], - [Disable support for gcj.])]) + [AC_HELP_STRING([--disable-gcj-support], [disable support for gcj])]) if test x"$enable_gcj_support" != xno; then AC_DEFINE(GC_GCJ_SUPPORT, 1, [Define to include support for gcj.]) + AC_DEFINE([GC_ENABLE_SUSPEND_THREAD], 1, + [Define to turn on GC_suspend_thread support.]) fi dnl Interaction with other programs that might use signals. AC_ARG_ENABLE(sigrt-signals, [AC_HELP_STRING([--enable-sigrt-signals], - [Force GC to use SIGRTMIN-based signals for thread suspend/resume])]) + [force GC to use SIGRTMIN-based signals for thread suspend/resume])]) if test x"${enable_sigrt_signals}" = xyes; then AC_DEFINE([GC_USESIGRT_SIGNALS], 1, [Force the GC to use signals based on SIGRTMIN+k.]) @@ -740,12 +799,15 @@ AM_CONDITIONAL([KEEP_BACK_PTRS], [test x"$keep_back_ptrs" = xtrue]) # Check for dladdr (used for debugging). AC_MSG_CHECKING(for dladdr) have_dladdr=no +old_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $CFLAGS_EXTRA" AC_TRY_COMPILE([ #define _GNU_SOURCE 1 #include ], [{ Dl_info info; (void)dladdr("", &info); }], [ have_dladdr=yes ]) +CFLAGS="$old_CFLAGS" AC_MSG_RESULT($have_dladdr) if test x"$have_dladdr" = xyes; then AC_DEFINE([HAVE_DLADDR], 1, [Define to use 'dladdr' function.]) @@ -756,7 +818,7 @@ ac_is_dgux=no AC_CHECK_HEADER(sys/dg_sys_info.h, [ac_is_dgux=yes;]) - ## :GOTCHA: we do not check anything but sys/dg_sys_info.h +dnl :GOTCHA: we do not check anything but sys/dg_sys_info.h if test $ac_is_dgux = yes; then dgux_spec_opts="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2" CFLAGS="$dgux_spec_opts $CFLAGS" @@ -771,22 +833,22 @@ fi AC_ARG_ENABLE(java-finalization, [AC_HELP_STRING([--disable-java-finalization], - [Disable support for java finalization.])]) + [disable support for java finalization])]) if test x"$enable_java_finalization" != xno; then AC_DEFINE([JAVA_FINALIZATION], 1, [See doc/README.macros.]) fi AC_ARG_ENABLE(atomic-uncollectable, [AC_HELP_STRING([--disable-atomic-uncollectible], - [Disable support for atomic uncollectible allocation.])]) + [disable support for atomic uncollectible allocation])]) if test x"$enable_atomic_uncollectible" != x"no"; then - AC_DEFINE(ATOMIC_UNCOLLECTABLE, 1, + AC_DEFINE([GC_ATOMIC_UNCOLLECTABLE], 1, [Define to enable atomic uncollectible allocation.]) fi AC_ARG_ENABLE(redirect-malloc, [AC_HELP_STRING([--enable-redirect-malloc], - [Redirect malloc and friends to GC routines])]) + [redirect malloc and friends to GC routines])]) if test "${enable_redirect_malloc}" = yes; then if test "${enable_gc_debug}" = yes; then @@ -804,7 +866,7 @@ fi AC_ARG_ENABLE(disclaim, [AC_HELP_STRING([--disable-disclaim], - [Disable alternative (more efficient) finalization interface.])]) + [disable alternative (more efficient) finalization interface])]) if test x"$enable_disclaim" != xno; then AC_DEFINE(ENABLE_DISCLAIM, 1, [Define to enable alternative finalization interface.]) @@ -814,17 +876,16 @@ AM_CONDITIONAL(ENABLE_DISCLAIM, AC_ARG_ENABLE(large-config, [AC_HELP_STRING([--enable-large-config], - [Optimize for large (> 100 MB) heap or root set])]) - + [optimize for large (> 100 MB) heap or root set])]) if test "${enable_large_config}" = yes; then - AC_DEFINE(LARGE_CONFIG, 1, [Define to optimize for large heaps or root sets.]) + AC_DEFINE(LARGE_CONFIG, 1, + [Define to optimize for large heaps or root sets.]) fi AC_ARG_ENABLE(handle-fork, [AC_HELP_STRING([--enable-handle-fork], - [Attempt to ensure a usable collector after fork() in multi-threaded - programs.])]) - + [attempt to ensure a usable collector after fork() in multi-threaded + programs])]) if test "${enable_handle_fork}" = yes; then AC_DEFINE(HANDLE_FORK, 1, [Define to install pthread_atfork() handlers by default.]) @@ -835,7 +896,7 @@ fi dnl This is something of a hack. When cross-compiling we turn off dnl some functionality. We also enable the "small" configuration. -dnl These is only correct when targetting an embedded system. FIXME. +dnl These is only correct when targeting an embedded system. FIXME. if test -n "${with_cross_host}"; then AC_DEFINE([NO_CLOCK], 1, [Define to not use system clock (cross compiling).]) AC_DEFINE([SMALL_CONFIG], 1, @@ -853,24 +914,20 @@ AC_ARG_ENABLE(gc-assertions, [AC_HELP_STRING([--enable-gc-assertions], [collector-internal assertion checking])]) if test "${enable_gc_assertions}" = yes; then - AC_DEFINE([GC_ASSERTIONS], 1, [Define to enable internal debug assertions.]) + AC_DEFINE([GC_ASSERTIONS], 1, + [Define to enable internal debug assertions.]) fi AC_ARG_ENABLE(munmap, [AC_HELP_STRING([--enable-munmap=N], [return page to the os if empty for N collections])], MUNMAP_THRESHOLD=$enableval) -if test "${enable_munmap}" != ""; then +if test x$enable_munmap != x -a x$enable_munmap != xno; then AC_DEFINE([USE_MMAP], 1, [Define to use mmap instead of sbrk to expand the heap.]) - case "$host" in - *-*-cygwin*) - # Workaround for Cygwin: use VirtualAlloc since mmap(PROT_NONE) fails - AC_DEFINE([USE_WINALLOC], 1, + AH_TEMPLATE([USE_WINALLOC], [Define to use Win32 VirtualAlloc (instead of sbrk or mmap) to expand the heap.]) - ;; - esac AC_DEFINE([USE_MUNMAP], 1, [Define to return memory to OS with munmap calls (see doc/README.macros).]) @@ -888,12 +945,45 @@ fi AM_CONDITIONAL(USE_LIBDIR, test -z "$with_cross_host") +AC_ARG_ENABLE(werror, + [AS_HELP_STRING([--enable-werror], [pass -Werror to the C compiler])], + werror_flag=$enableval, werror_flag=no) +if test x$werror_flag = xyes; then + WERROR_CFLAGS="-Werror" + case "$host" in + # _dyld_bind_fully_image_containing_address is deprecated in OS X 10.5+ + *-*-darwin*) + WERROR_CFLAGS="$WERROR_CFLAGS -Wno-deprecated-declarations" + ;; + esac +fi +AC_SUBST([WERROR_CFLAGS]) + AC_ARG_ENABLE(single-obj-compilation, [AC_HELP_STRING([--enable-single-obj-compilation], - [Compile all library .c files into single .o])], + [compile all libgc source files into single .o])], [single_obj_compilation=yes]) AM_CONDITIONAL([SINGLE_GC_OBJ], [test "$single_obj_compilation" = "yes"]) +AC_ARG_ENABLE(gcov, + [AC_HELP_STRING([--enable-gcov], [turn on code coverage analysis])]) +if test "$enable_gcov" = "yes"; then + CFLAGS="$CFLAGS --coverage" + if test "${enable_shared}" = no; then + # FIXME: As of g++-4.8.4/x86_64, in case of shared library build, test_cpp + # linkage fails with "hidden symbol atexit is referenced by DSO" message. + CXXFLAGS="$CXXFLAGS --coverage" + fi + # Turn off optimization to get accurate line numbers. + CFLAGS=`echo "$CFLAGS" | sed -e 's/-O\(1\|2\|3\|4\|s\|fast\)\?//g'` + CXXFLAGS=`echo "$CXXFLAGS" | sed -e 's/-O\(1\|2\|3\|4\|s\|fast\)\?//g'` +fi + +AC_ARG_ENABLE(docs, + [AC_HELP_STRING([--disable-docs], + [do not build and install documentation])]) +AM_CONDITIONAL(ENABLE_DOCS, test x$enable_docs != xno) + # Atomic Ops # ---------- @@ -901,25 +991,36 @@ AM_CONDITIONAL([SINGLE_GC_OBJ], [test "$single_obj_compilation" = "yes"]) # found. AC_ARG_WITH([libatomic-ops], [AS_HELP_STRING([--with-libatomic-ops[=yes|no|check]], - [Use a external libatomic_ops? (default: check)])], + [Use an external libatomic_ops? (default: check)])], [], [with_libatomic_ops=check]) -# Check for an external libatomic_ops if the answer was yes or check. If not -# found, fail on yes, and convert check to no. -# Note: "syntax error near unexpected token ATOMIC_OPS" reported by configure -# means Autotools pkg.m4 file was not found during aclocal.m4 generation. +# Check for an external libatomic_ops if the above answer is "yes" or "check". +# If not found, fail on "yes", and convert "check" to "no". +# First, check that libatomic_ops usage is not disabled explicitly. missing_libatomic_ops=false -AS_IF([test x"$with_libatomic_ops" != xno], - [ PKG_CHECK_MODULES([ATOMIC_OPS], [atomic_ops], [], - [ missing_libatomic_ops=true ]) ]) -AS_IF([test x$missing_libatomic_ops = xtrue ], +AS_IF([test x"$with_libatomic_ops" != xno -a x"$THREADS" != xnone], + [ missing_libatomic_ops=true ]) + +dnl Note: "syntax error near unexpected token ATOMIC_OPS" reported by configure +dnl means Autotools pkg.m4 file was not found during aclocal.m4 generation; +dnl in this case, most probably, you should run pkg-config once before running +dnl autogen.sh (autoreconf); alternatively, comment out the following 3 lines. +AS_IF([test x$missing_libatomic_ops = xtrue], + [ PKG_CHECK_MODULES([ATOMIC_OPS], [atomic_ops], + [ missing_libatomic_ops=false ], [ [] ]) ]) + +dnl Retry with AC_CHECK_HEADER if PKG_CHECK_MODULES failed. +AS_IF([test x$missing_libatomic_ops = xtrue], + [ AC_CHECK_HEADER([atomic_ops.h], [missing_libatomic_ops=false]) ]) +AS_IF([test x$missing_libatomic_ops = xtrue], [ AS_IF([test x"$with_libatomic_ops" != xcheck], [ AC_MSG_ERROR([An external libatomic_ops was not found]) ]) with_libatomic_ops=no ]) # If we have neither an external or an internal version, offer a useful hint # and exit. -AS_IF([test x"$with_libatomic_ops" = xno -a ! -e "$srcdir/libatomic_ops"], +AS_IF([test x"$with_libatomic_ops" = xno \ + -a ! -e "$srcdir/libatomic_ops/src/atomic_ops.h"], [ AC_MSG_ERROR([libatomic_ops is required. You can either install it on your system, or fetch and unpack a recent version into the source directory and link or rename it to libatomic_ops.]) ]) @@ -927,7 +1028,8 @@ AS_IF([test x"$with_libatomic_ops" = xno -a ! -e "$srcdir/libatomic_ops"], # Finally, emit the definitions for bundled or external AO. AC_MSG_CHECKING([which libatomic_ops to use]) AS_IF([test x"$with_libatomic_ops" != xno], - [ AC_MSG_RESULT([external]) ], + [ AS_IF([test x"$THREADS" != xnone], + [ AC_MSG_RESULT([external]) ], [ AC_MSG_RESULT([none]) ]) ], [ AC_MSG_RESULT([internal]) ATOMIC_OPS_CFLAGS='-I$(top_builddir)/libatomic_ops/src -I$(top_srcdir)/libatomic_ops/src' ATOMIC_OPS_LIBS="" diff --git a/src/bdwgc/cord/cord.am b/src/bdwgc/cord/cord.am index 7793ec8f0..05ffcff5b 100644 --- a/src/bdwgc/cord/cord.am +++ b/src/bdwgc/cord/cord.am @@ -1,8 +1,14 @@ +## This file is processed with automake. + +# Info (current:revision:age) for the Libtool versioning system. +# These numbers should be updated at most once just before the release, +# and, optionally, at most once during the development (after the release). +LIBCORD_VER_INFO = 4:1:3 lib_LTLIBRARIES += libcord.la libcord_la_LIBADD = $(top_builddir)/libgc.la -libcord_la_LDFLAGS = -version-info 1:3:0 -no-undefined +libcord_la_LDFLAGS = -version-info $(LIBCORD_VER_INFO) -no-undefined libcord_la_CPPFLAGS = $(AM_CPPFLAGS) libcord_la_SOURCES = \ diff --git a/src/bdwgc/cord/cordbscs.c b/src/bdwgc/cord/cordbscs.c index 565367266..7fe241153 100644 --- a/src/bdwgc/cord/cordbscs.c +++ b/src/bdwgc/cord/cordbscs.c @@ -37,7 +37,7 @@ typedef void (* oom_fn)(void); oom_fn CORD_oom_fn = (oom_fn) 0; # define OUT_OF_MEMORY { if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \ - ABORT("Out of memory\n"); } + ABORT("Out of memory"); } # define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); } typedef unsigned long word; @@ -126,14 +126,14 @@ void CORD_dump_inner(CORD x, unsigned n) register struct Concatenation * conc = &(((CordRep *)x) -> concatenation); printf("Concatenation: %p (len: %d, depth: %d)\n", - x, (int)(conc -> len), (int)(conc -> depth)); + (void *)x, (int)(conc -> len), (int)(conc -> depth)); CORD_dump_inner(conc -> left, n+1); CORD_dump_inner(conc -> right, n+1); } else /* function */{ register struct Function * func = &(((CordRep *)x) -> function); if (IS_SUBSTR(x)) printf("(Substring) "); - printf("Function: %p (len: %d): ", x, (int)(func -> len)); + printf("Function: %p (len: %d): ", (void *)x, (int)(func -> len)); for (i = 0; i < 20 && i < func -> len; i++) { putchar((*(func -> fn))(i, func -> client_data)); } @@ -175,13 +175,14 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny) register CORD right; register CORD left; register char * new_right; - register size_t right_len; lenx = LEN(x); if (leny <= SHORT_LIMIT/2 && IS_CONCATENATION(x) && CORD_IS_STRING(right = ((CordRep *)x) -> concatenation.right)) { + size_t right_len; + /* Merge y into right part of x. */ if (!CORD_IS_STRING(left = ((CordRep *)x) -> concatenation.left)) { right_len = lenx - LEN(left); @@ -220,11 +221,15 @@ CORD CORD_cat_char_star(CORD x, const char * y, size_t leny) result = GC_NEW(struct Concatenation); if (result == 0) OUT_OF_MEMORY; result->header = CONCAT_HDR; - result->depth = depth; - if (lenx <= MAX_LEFT_LEN) result->left_len = lenx; - result->len = result_len; + result->depth = (char)depth; + if (lenx <= MAX_LEFT_LEN) + result->left_len = (unsigned char)lenx; + result->len = (word)result_len; result->left = x; result->right = y; + GC_END_STUBBORN_CHANGE(result); + GC_reachable_here(x); + GC_reachable_here(y); if (depth >= MAX_DEPTH) { return(CORD_balance((CORD)result)); } else { @@ -261,11 +266,15 @@ CORD CORD_cat(CORD x, CORD y) result = GC_NEW(struct Concatenation); if (result == 0) OUT_OF_MEMORY; result->header = CONCAT_HDR; - result->depth = depth; - if (lenx <= MAX_LEFT_LEN) result->left_len = lenx; - result->len = result_len; + result->depth = (char)depth; + if (lenx <= MAX_LEFT_LEN) + result->left_len = (unsigned char)lenx; + result->len = (word)result_len; result->left = x; result->right = y; + GC_END_STUBBORN_CHANGE(result); + GC_reachable_here(x); + GC_reachable_here(y); if (depth >= MAX_DEPTH) { return(CORD_balance((CORD)result)); } else { @@ -275,18 +284,17 @@ CORD CORD_cat(CORD x, CORD y) } - -CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len) +static CordRep *CORD_from_fn_inner(CORD_fn fn, void * client_data, size_t len) { - if (len <= 0) return(0); + if (len == 0) return(0); if (len <= SHORT_LIMIT) { register char * result; register size_t i; char buf[SHORT_LIMIT+1]; - register char c; for (i = 0; i < len; i++) { - c = (*fn)(i, client_data); + char c = (*fn)(i, client_data); + if (c == '\0') goto gen_case; buf[i] = c; } @@ -295,7 +303,7 @@ CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len) if (result == 0) OUT_OF_MEMORY; memcpy(result, buf, len); result[len] = '\0'; - return((CORD) result); + return (CordRep *)result; } gen_case: { @@ -305,13 +313,20 @@ CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len) if (result == 0) OUT_OF_MEMORY; result->header = FN_HDR; /* depth is already 0 */ - result->len = len; + result->len = (word)len; result->fn = fn; result->client_data = client_data; - return((CORD) result); + GC_END_STUBBORN_CHANGE(result); + GC_reachable_here(client_data); + return (CordRep *)result; } } +CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len) +{ + return (/* const */ CORD) CORD_from_fn_inner(fn, client_data, len); +} + size_t CORD_len(CORD x) { if (x == 0) { @@ -348,15 +363,17 @@ char CORD_apply_access_fn(size_t i, void * client_data) CORD CORD_substr_closure(CORD x, size_t i, size_t n, CORD_fn f) { register struct substr_args * sa = GC_NEW(struct substr_args); - CORD result; + CordRep * result; if (sa == 0) OUT_OF_MEMORY; sa->sa_cord = (CordRep *)x; sa->sa_index = i; - result = CORD_from_fn(f, (void *)sa, n); - if (result == CORD_EMPTY) return CORD_EMPTY; /* n == 0 */ - ((CordRep *)result) -> function.header = SUBSTR_HDR; - return (result); + GC_END_STUBBORN_CHANGE(sa); + GC_reachable_here(x); + result = CORD_from_fn_inner(f, (void *)sa, n); + if ((CORD)result != CORD_EMPTY && 0 == result -> function.null) + result -> function.header = SUBSTR_HDR; + return (CORD)result; } # define SUBSTR_LIMIT (10 * SHORT_LIMIT) @@ -430,12 +447,12 @@ CORD CORD_substr_checked(CORD x, size_t i, size_t n) register struct Function * f = &(((CordRep *)x) -> function); char buf[SUBSTR_LIMIT+1]; register char * p = buf; - register char c; - register int j; - register int lim = i + n; + register size_t j; + register size_t lim = i + n; for (j = i; j < lim; j++) { - c = (*(f -> fn))(j, f -> client_data); + char c = (*(f -> fn))(j, f -> client_data); + if (c == '\0') { return(CORD_substr_closure(x, i, n, CORD_apply_access_fn)); } @@ -454,9 +471,7 @@ CORD CORD_substr(CORD x, size_t i, size_t n) { register size_t len = CORD_len(x); - if (i >= len || n <= 0) return(0); - /* n < 0 is impossible in a correct C implementation, but */ - /* quite possible under SunOS 4.X. */ + if (i >= len || n == 0) return(0); if (i + n > len) n = len - i; return(CORD_substr_checked(x, i, n)); } @@ -521,10 +536,10 @@ int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data) if (x == 0) return(0); if (CORD_IS_STRING(x)) { register const char *p = x + i; - register char c; for(;;) { - c = *p; + char c = *p; + if (c == '\0') ABORT("2nd arg to CORD_riter4 too big"); if ((*f1)(c, client_data)) return(1); if (p == x) break; @@ -601,18 +616,19 @@ typedef ForestElement Forest [ MAX_DEPTH ]; void CORD_init_min_len(void) { register int i; - register size_t last, previous, current; + size_t last, previous; min_len[0] = previous = 1; min_len[1] = last = 2; for (i = 2; i < MAX_DEPTH; i++) { - current = last + previous; + size_t current = last + previous; + if (current < last) /* overflow */ current = last; min_len[i] = current; previous = last; last = current; } - CORD_max_len = last - 1; + CORD_max_len = (int)last - 1; min_len_init = 1; } @@ -869,7 +885,7 @@ void CORD__prev(register CORD_pos p) char CORD_pos_fetch(register CORD_pos p) { - if (p[0].cur_start <= p[0].cur_pos && p[0].cur_pos < p[0].cur_end) { + if (p[0].cur_end != 0) { return(p[0].cur_leaf[p[0].cur_pos - p[0].cur_start]); } else { return(CORD__pos_fetch(p)); @@ -878,7 +894,7 @@ char CORD_pos_fetch(register CORD_pos p) void CORD_next(CORD_pos p) { - if (p[0].cur_pos < p[0].cur_end - 1) { + if (p[0].cur_pos + 1 < p[0].cur_end) { p[0].cur_pos++; } else { CORD__next(p); diff --git a/src/bdwgc/cord/cordprnt.c b/src/bdwgc/cord/cordprnt.c index 7e7745b1b..acd31a347 100644 --- a/src/bdwgc/cord/cordprnt.c +++ b/src/bdwgc/cord/cordprnt.c @@ -30,9 +30,12 @@ #include "cord.h" #include "ec.h" -#include + #include +#include +#include #include + #include "gc.h" #define CONV_SPEC_LEN 50 /* Maximum length of a single */ @@ -41,6 +44,11 @@ /* conversion with default */ /* width and prec. */ +#define OUT_OF_MEMORY do { \ + if (CORD_oom_fn != 0) (*CORD_oom_fn)(); \ + fprintf(stderr, "Out of memory\n"); \ + abort(); \ + } while (0) static int ec_len(CORD_ec x) { @@ -84,7 +92,9 @@ static int extract_conv_spec(CORD_pos source, char *buf, if (!saw_number) { /* Zero fill flag; ignore */ break; - } /* otherwise fall through: */ + } + current_number *= 10; + break; case '1': case '2': case '3': @@ -164,6 +174,20 @@ static int extract_conv_spec(CORD_pos source, char *buf, return(result); } +#if defined(DJGPP) || defined(__STRICT_ANSI__) + /* vsnprintf is missing in DJGPP (v2.0.3) */ +# define GC_VSNPRINTF(buf, bufsz, format, args) vsprintf(buf, format, args) +#elif defined(_MSC_VER) +# ifdef MSWINCE + /* _vsnprintf is deprecated in WinCE */ +# define GC_VSNPRINTF StringCchVPrintfA +# else +# define GC_VSNPRINTF _vsnprintf +# endif +#else +# define GC_VSNPRINTF vsnprintf +#endif + int CORD_vsprintf(CORD * out, CORD format, va_list args) { CORD_ec result; @@ -220,11 +244,12 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) if (prec != NONE && len > (size_t)prec) { if (prec < 0) return(-1); arg = CORD_substr(arg, 0, prec); - len = prec; + len = (unsigned)prec; } if (width != NONE && len < (size_t)width) { char * blanks = GC_MALLOC_ATOMIC(width-len+1); + if (NULL == blanks) OUT_OF_MEMORY; memset(blanks, ' ', width-len); blanks[width-len] = '\0'; if (left_adj) { @@ -249,7 +274,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) char * str = va_arg(args, char *); register char c; - while ((c = *str++)) { + while ((c = *str++) != '\0') { CORD_ec_append(result, c); } goto done; @@ -263,16 +288,17 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) register char * buf; va_list vsprintf_args; int max_size = 0; - int res; -# ifdef __va_copy + int res = 0; + +# if defined(CPPCHECK) + va_copy(vsprintf_args, args); +# elif defined(__va_copy) __va_copy(vsprintf_args, args); -# else -# if defined(__GNUC__) && !defined(__DJGPP__) \ +# elif defined(__GNUC__) && !defined(__DJGPP__) \ && !defined(__EMX__) /* and probably in other cases */ - va_copy(vsprintf_args, args); -# else - vsprintf_args = args; -# endif + va_copy(vsprintf_args, args); +# else + vsprintf_args = args; # endif if (width == VARIABLE) width = va_arg(args, int); if (prec == VARIABLE) prec = va_arg(args, int); @@ -281,6 +307,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) max_size += CONV_RESULT_LEN; if (max_size >= CORD_BUFSZ) { buf = GC_MALLOC_ATOMIC(max_size + 1); + if (NULL == buf) OUT_OF_MEMORY; } else { if (CORD_BUFSZ - (result[0].ec_bufptr-result[0].ec_buf) < max_size) { @@ -298,7 +325,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) case 'c': if (long_arg <= 0) { (void) va_arg(args, int); - } else if (long_arg > 0) { + } else /* long_arg > 0 */ { (void) va_arg(args, long); } break; @@ -314,15 +341,12 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) (void) va_arg(args, double); break; default: -# if defined(__va_copy) \ - || (defined(__GNUC__) && !defined(__DJGPP__) \ - && !defined(__EMX__)) - va_end(vsprintf_args); -# endif - return(-1); + res = -1; } - res = vsprintf(buf, conv_spec, vsprintf_args); -# if defined(__va_copy) \ + if (0 == res) + res = GC_VSNPRINTF(buf, max_size + 1, conv_spec, + vsprintf_args); +# if defined(CPPCHECK) || defined(__va_copy) \ || (defined(__GNUC__) && !defined(__DJGPP__) \ && !defined(__EMX__)) va_end(vsprintf_args); @@ -337,7 +361,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) if (buf != result[0].ec_bufptr) { register char c; - while ((c = *buf++)) { + while ((c = *buf++) != '\0') { CORD_ec_append(result, c); } } else { diff --git a/src/bdwgc/cord/cordxtra.c b/src/bdwgc/cord/cordxtra.c index 610ea8937..9f3e10005 100644 --- a/src/bdwgc/cord/cordxtra.c +++ b/src/bdwgc/cord/cordxtra.c @@ -59,8 +59,8 @@ typedef void (* oom_fn)(void); -# define OUT_OF_MEMORY { if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \ - ABORT("Out of memory\n"); } +# define OUT_OF_MEMORY { if (CORD_oom_fn != (oom_fn) 0) (*CORD_oom_fn)(); \ + ABORT("Out of memory"); } # define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); } #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) @@ -136,22 +136,23 @@ int CORD_batched_fill_proc(const char * s, void * client_data) } /* Fill buf with len characters starting at i. */ -/* Assumes len characters are available. */ -void CORD_fill_buf(CORD x, size_t i, size_t len, char * buf) +/* Assumes len characters are available in buf. */ +/* Return 1 if buf is filled fully (and len is */ +/* non-zero), 0 otherwise. */ +int CORD_fill_buf(CORD x, size_t i, size_t len, char * buf) { CORD_fill_data fd; fd.len = len; fd.buf = buf; fd.count = 0; - (void)CORD_iter5(x, i, CORD_fill_proc, CORD_batched_fill_proc, &fd); + return CORD_iter5(x, i, CORD_fill_proc, CORD_batched_fill_proc, &fd); } int CORD_cmp(CORD x, CORD y) { CORD_pos xpos; CORD_pos ypos; - register size_t avail, yavail; if (y == CORD_EMPTY) return(x != CORD_EMPTY); if (x == CORD_EMPTY) return(-1); @@ -159,6 +160,8 @@ int CORD_cmp(CORD x, CORD y) CORD_set_pos(xpos, x, 0); CORD_set_pos(ypos, y, 0); for(;;) { + size_t avail, yavail; + if (!CORD_pos_valid(xpos)) { if (CORD_pos_valid(ypos)) { return(-1); @@ -169,8 +172,9 @@ int CORD_cmp(CORD x, CORD y) if (!CORD_pos_valid(ypos)) { return(1); } - if ((avail = CORD_pos_chars_left(xpos)) <= 0 - || (yavail = CORD_pos_chars_left(ypos)) <= 0) { + avail = CORD_pos_chars_left(xpos); + if (avail == 0 + || (yavail = CORD_pos_chars_left(ypos)) == 0) { register char xcurrent = CORD_pos_fetch(xpos); register char ycurrent = CORD_pos_fetch(ypos); if (xcurrent != ycurrent) return(xcurrent - ycurrent); @@ -195,11 +199,12 @@ int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len) CORD_pos xpos; CORD_pos ypos; register size_t count; - register long avail, yavail; CORD_set_pos(xpos, x, x_start); CORD_set_pos(ypos, y, y_start); for(count = 0; count < len;) { + long avail, yavail; + if (!CORD_pos_valid(xpos)) { if (CORD_pos_valid(ypos)) { return(-1); @@ -224,7 +229,8 @@ int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start, size_t len) if (avail > yavail) avail = yavail; count += avail; - if (count > len) avail -= (count - len); + if (count > len) + avail -= (long)(count - len); result = strncmp(CORD_pos_cur_char_addr(xpos), CORD_pos_cur_char_addr(ypos), (size_t)avail); if (result != 0) return(result); @@ -241,7 +247,8 @@ char * CORD_to_char_star(CORD x) char * result = GC_MALLOC_ATOMIC(len + 1); if (result == 0) OUT_OF_MEMORY; - CORD_fill_buf(x, 0, len, result); + if (len > 0 && CORD_fill_buf(x, 0, len, result) != 1) + ABORT("CORD_fill_buf malfunction"); result[len] = '\0'; return(result); } @@ -341,7 +348,7 @@ size_t CORD_chr(CORD x, size_t i, int c) chr_data d; d.pos = i; - d.target = c; + d.target = (char)c; if (CORD_iter5(x, i, CORD_chr_proc, CORD_batched_chr_proc, &d)) { return(d.pos); } else { @@ -354,7 +361,7 @@ size_t CORD_rchr(CORD x, size_t i, int c) chr_data d; d.pos = i; - d.target = c; + d.target = (char)c; if (CORD_riter4(x, i, CORD_rchr_proc, &d)) { return(d.pos); } else { @@ -428,6 +435,7 @@ void CORD_ec_flush_buf(CORD_ec x) if (len == 0) return; s = GC_MALLOC_ATOMIC(len+1); + if (NULL == s) OUT_OF_MEMORY; memcpy(s, x[0].ec_buf, len); s[len] = '\0'; x[0].ec_cord = CORD_cat_char_star(x[0].ec_cord, s, len); @@ -442,23 +450,22 @@ void CORD_ec_append_cord(CORD_ec x, CORD s) char CORD_nul_func(size_t i CORD_ATTR_UNUSED, void * client_data) { - return((char)(unsigned long)client_data); + return (char)(GC_word)client_data; } - CORD CORD_chars(char c, size_t i) { - return(CORD_from_fn(CORD_nul_func, (void *)(unsigned long)c, i)); + return CORD_from_fn(CORD_nul_func, (void *)(GC_word)(unsigned char)c, i); } CORD CORD_from_file_eager(FILE * f) { - register int c; CORD_ec ecord; CORD_ec_init(ecord); for(;;) { - c = getc(f); + int c = getc(f); + if (c == 0) { /* Append the right number of NULs */ /* Note that any string of NULs is represented in 4 words, */ @@ -470,7 +477,7 @@ CORD CORD_from_file_eager(FILE * f) ecord[0].ec_cord = CORD_cat(ecord[0].ec_cord, CORD_nul(count)); } if (c == EOF) break; - CORD_ec_append(ecord, c); + CORD_ec_append(ecord, (char)c); } (void) fclose(f); return(CORD_balance(CORD_ec_to_cord(ecord))); @@ -519,17 +526,17 @@ typedef struct { } refill_data; /* Executed with allocation lock. */ -static char refill_cache(refill_data * client_data) +static void * GC_CALLBACK refill_cache(void * client_data) { - register lf_state * state = client_data -> state; - register size_t file_pos = client_data -> file_pos; + register lf_state * state = ((refill_data *)client_data) -> state; + register size_t file_pos = ((refill_data *)client_data) -> file_pos; FILE *f = state -> lf_file; size_t line_start = LINE_START(file_pos); size_t line_no = DIV_LINE_SZ(MOD_CACHE_SZ(file_pos)); - cache_line * new_cache = client_data -> new_cache; + cache_line * new_cache = ((refill_data *)client_data) -> new_cache; if (line_start != state -> lf_current - && fseek(f, line_start, SEEK_SET) != 0) { + && fseek(f, (long)line_start, SEEK_SET) != 0) { ABORT("fseek failed"); } if (fread(new_cache -> data, sizeof(char), LINE_SZ, f) @@ -539,8 +546,10 @@ static char refill_cache(refill_data * client_data) new_cache -> tag = DIV_LINE_SZ(file_pos); /* Store barrier goes here. */ ATOMIC_WRITE(state -> lf_cache[line_no], new_cache); + GC_END_STUBBORN_CHANGE((/* no volatile */ void *)(state -> lf_cache + + line_no)); state -> lf_current = line_start + LINE_SZ; - return(new_cache->data[MOD_LINE_SZ(file_pos)]); + return (void *)((GC_word)new_cache->data[MOD_LINE_SZ(file_pos)]); } char CORD_lf_func(size_t i, void * client_data) @@ -558,8 +567,7 @@ char CORD_lf_func(size_t i, void * client_data) rd.file_pos = i; rd.new_cache = GC_NEW_ATOMIC(cache_line); if (rd.new_cache == 0) OUT_OF_MEMORY; - return((char)(GC_word) - GC_call_with_alloc_lock((GC_fn_type) refill_cache, &rd)); + return (char)((GC_word)GC_call_with_alloc_lock(refill_cache, &rd)); } return(cl -> data[MOD_LINE_SZ(i)]); } @@ -585,11 +593,10 @@ CORD CORD_from_file_lazy_inner(FILE * f, size_t len) /* world is multi-threaded. */ char buf[1]; - if (fread(buf, 1, 1, f) > 1) { - /* Just to suppress "unused result" compiler warning. */ - ABORT("fread unexpected result"); + if (fread(buf, 1, 1, f) > 1 + || fseek(f, 0l, SEEK_SET) != 0) { + ABORT("Bad f argument or I/O failure"); } - rewind(f); } state -> lf_file = f; for (i = 0; i < CACHE_SZ/LINE_SZ; i++) { @@ -604,13 +611,11 @@ CORD CORD_from_file_lazy(FILE * f) { register long len; - if (fseek(f, 0l, SEEK_END) != 0) { - ABORT("Bad fd argument - fseek failed"); + if (fseek(f, 0l, SEEK_END) != 0 + || (len = ftell(f)) < 0 + || fseek(f, 0l, SEEK_SET) != 0) { + ABORT("Bad f argument or I/O failure"); } - if ((len = ftell(f)) < 0) { - ABORT("Bad fd argument - ftell failed"); - } - rewind(f); return(CORD_from_file_lazy_inner(f, (size_t)len)); } @@ -620,13 +625,11 @@ CORD CORD_from_file(FILE * f) { register long len; - if (fseek(f, 0l, SEEK_END) != 0) { - ABORT("Bad fd argument - fseek failed"); + if (fseek(f, 0l, SEEK_END) != 0 + || (len = ftell(f)) < 0 + || fseek(f, 0l, SEEK_SET) != 0) { + ABORT("Bad f argument or I/O failure"); } - if ((len = ftell(f)) < 0) { - ABORT("Bad fd argument - ftell failed"); - } - rewind(f); if (len < LAZY_THRESHOLD) { return(CORD_from_file_eager(f)); } else { diff --git a/src/bdwgc/cord/tests/cordtest.c b/src/bdwgc/cord/tests/cordtest.c index 906f739df..e05e6a5bb 100644 --- a/src/bdwgc/cord/tests/cordtest.c +++ b/src/bdwgc/cord/tests/cordtest.c @@ -13,15 +13,28 @@ # include "gc.h" /* For GC_INIT() only */ # include "cord.h" + +# include # include # include # include + /* This is a very incomplete test of the cord package. It knows about */ /* a few internals of the package (e.g. when C strings are returned) */ -/* that real clients shouldn't rely on. */ +/* that real clients shouldn't rely on. */ # define ABORT(string) \ - { int x = 0; fprintf(stderr, "FAILED: %s\n", string); x = 1 / x; abort(); } + { fprintf(stderr, "FAILED: %s\n", string); abort(); } + +#if defined(CPPCHECK) +# undef CORD_iter +# undef CORD_next +# undef CORD_pos_fetch +# undef CORD_pos_to_cord +# undef CORD_pos_to_index +# undef CORD_pos_valid +# undef CORD_prev +#endif int count; @@ -53,7 +66,6 @@ void test_basics(void) { CORD x = CORD_from_char_star("ab"); register int i; - char c; CORD y; CORD_pos p; @@ -114,11 +126,22 @@ void test_basics(void) i = 0; CORD_set_pos(p, y, i); while(CORD_pos_valid(p)) { - c = CORD_pos_fetch(p); + char c = CORD_pos_fetch(p); + if(c != i) ABORT("Traversal of function node failed"); - CORD_next(p); i++; + CORD_next(p); + i++; } if (i != 13) ABORT("Bad apparent length for function node"); +# if defined(CPPCHECK) + /* TODO: Actually test these functions. */ + CORD_prev(p); + (void)CORD_pos_to_cord(p); + (void)CORD_pos_to_index(p); + (void)CORD_iter(CORD_EMPTY, test_fn, NULL); + (void)CORD_riter(CORD_EMPTY, test_fn, NULL); + CORD_dump(y); +# endif } void test_extras(void) @@ -128,7 +151,7 @@ void test_extras(void) register int i; CORD y = "abcdefghijklmnopqrstuvwxyz0123456789"; CORD x = "{}"; - CORD w, z; + CORD u, w, z; FILE *f; FILE *f1a, *f1b, *f2; @@ -180,7 +203,9 @@ void test_extras(void) ABORT("file substr wrong"); if (strcmp(CORD_to_char_star(CORD_substr(w, 1000*36, 36)), y) != 0) ABORT("char * file substr wrong"); - if (strcmp(CORD_substr(w, 1000*36, 2), "ab") != 0) + u = CORD_substr(w, 1000*36, 2); + if (!u) ABORT("CORD_substr returned NULL"); + if (strcmp(u, "ab") != 0) ABORT("short file substr wrong"); if (CORD_str(x,1,"9a") != 35) ABORT("CORD_str failed 1"); if (CORD_str(x,0,"9abcdefghijk") != 35) ABORT("CORD_str failed 2"); @@ -197,13 +222,35 @@ void test_extras(void) if (remove(FNAME1) != 0) { /* On some systems, e.g. OS2, this may fail if f1 is still open. */ /* But we cannot call fclose as it might lead to double close. */ - fprintf(stderr, "WARNING: remove(FNAME1) failed\n"); + fprintf(stderr, "WARNING: remove failed: " FNAME1 "\n"); } if (remove(FNAME2) != 0) { - fprintf(stderr, "WARNING: remove(FNAME2) failed\n"); + fprintf(stderr, "WARNING: remove failed: " FNAME2 "\n"); } } +int wrap_vprintf(CORD format, ...) +{ + va_list args; + int result; + + va_start(args, format); + result = CORD_vprintf(format, args); + va_end(args); + return result; +} + +int wrap_vfprintf(FILE * f, CORD format, ...) +{ + va_list args; + int result; + + va_start(args, format); + result = CORD_vfprintf(f, format, args); + va_end(args); + return result; +} + #if defined(__DJGPP__) || defined(__STRICT_ANSI__) /* snprintf is missing in DJGPP (v2.0.3) */ #else @@ -249,6 +296,10 @@ void test_printf(void) # endif result2[sizeof(result2) - 1] = '\0'; if (CORD_cmp(result, result2) != 0)ABORT("CORD_sprintf goofed 5"); + /* TODO: Better test CORD_[v][f]printf. */ + (void)CORD_printf(CORD_EMPTY); + (void)wrap_vfprintf(stdout, CORD_EMPTY); + (void)wrap_vprintf(CORD_EMPTY); } int main(void) diff --git a/src/bdwgc/cord/tests/de.c b/src/bdwgc/cord/tests/de.c index 28182ddda..61ee72fb6 100644 --- a/src/bdwgc/cord/tests/de.c +++ b/src/bdwgc/cord/tests/de.c @@ -27,13 +27,15 @@ */ #include +#include /* for exit() */ + #include "gc.h" #include "cord.h" #ifdef THINK_C #define MACINTOSH -#include #endif +#include #if (defined(__BORLANDC__) || defined(__CYGWIN__)) && !defined(WIN32) /* If this is DOS or win16, we'll fail anyway. */ @@ -63,10 +65,16 @@ # define COLS 80 #else # include +# include /* for sleep() */ # define de_error(s) { fprintf(stderr, s); sleep(2); } #endif #include "de_cmds.h" +#define OUT_OF_MEMORY do { \ + fprintf(stderr, "Out of memory\n"); \ + exit(3); \ + } while (0) + /* List of line number to position mappings, in descending order. */ /* There may be holes. */ typedef struct LineMapRep { @@ -125,21 +133,30 @@ void prune_map(void) do { current_map_size++; if (map -> line < start_line - LINES && map -> previous != 0) { - map -> previous = map -> previous -> previous; + line_map pred = map -> previous -> previous; + + map -> previous = pred; + GC_END_STUBBORN_CHANGE(map); + GC_reachable_here(pred); } map = map -> previous; } while (map != 0); } /* Add mapping entry */ -void add_map(int line, size_t pos) +void add_map(int line_arg, size_t pos) { line_map new_map = GC_NEW(struct LineMapRep); + line_map cur_map; + if (NULL == new_map) OUT_OF_MEMORY; if (current_map_size >= MAX_MAP_SIZE) prune_map(); - new_map -> line = line; + new_map -> line = line_arg; new_map -> pos = pos; - new_map -> previous = current_map; + cur_map = current_map; + new_map -> previous = cur_map; + GC_END_STUBBORN_CHANGE(new_map); + GC_reachable_here(cur_map); current_map = new_map; current_map_size++; } @@ -155,7 +172,6 @@ size_t line_pos(int i, int *c) { int j; size_t cur; - size_t next; line_map map = current_map; while (map -> line > i) map = map -> previous; @@ -167,10 +183,11 @@ size_t line_pos(int i, int *c) if (++j > current_map -> line) add_map(j, cur); } if (c != 0) { - next = CORD_chr(current, cur, '\n'); + size_t next = CORD_chr(current, cur, '\n'); + if (next == CORD_NOT_FOUND) next = current_len - 1; if (next < cur + *c) { - *c = next - cur; + *c = (int)(next - cur); } cur += *c; } @@ -181,10 +198,15 @@ void add_hist(CORD s) { history new_file = GC_NEW(struct HistoryRep); + if (NULL == new_file) OUT_OF_MEMORY; new_file -> file_contents = current = s; current_len = CORD_len(s); new_file -> previous = now; - if (now != 0) now -> map = current_map; + GC_END_STUBBORN_CHANGE(new_file); + if (now != NULL) { + now -> map = current_map; + GC_END_STUBBORN_CHANGE(now); + } now = new_file; } @@ -206,7 +228,6 @@ int screen_size = 0; /* terribly appropriate for tabs. */ void replace_line(int i, CORD s) { - register int c; CORD_pos p; # if !defined(MACINTOSH) size_t len = CORD_len(s); @@ -215,10 +236,11 @@ void replace_line(int i, CORD s) if (screen == 0 || LINES > screen_size) { screen_size = LINES; screen = (CORD *)GC_MALLOC(screen_size * sizeof(CORD)); + if (NULL == screen) OUT_OF_MEMORY; } # if !defined(MACINTOSH) /* A gross workaround for an apparent curses bug: */ - if (i == LINES-1 && len == COLS) { + if (i == LINES-1 && len == (unsigned)COLS) { s = CORD_substr(s, 0, len - 1); } # endif @@ -226,7 +248,8 @@ void replace_line(int i, CORD s) move(i, 0); clrtoeol(); move(i,0); CORD_FOR (p, s) { - c = CORD_pos_fetch(p) & 0x7f; + int c = CORD_pos_fetch(p) & 0x7f; + if (iscntrl(c)) { standout(); addch(c + 0x40); standend(); } else { @@ -234,6 +257,8 @@ void replace_line(int i, CORD s) } } screen[i] = s; + GC_END_STUBBORN_CHANGE(screen + i); + GC_reachable_here(s); } } #else @@ -336,7 +361,8 @@ void fix_pos(void) { int my_col = col; - if ((size_t)line > current_len) line = current_len; + if ((size_t)line > current_len) + line = (int)current_len; file_pos = line_pos(line, &my_col); if (file_pos == CORD_NOT_FOUND) { for (line = current_map -> line, file_pos = current_map -> pos; @@ -417,7 +443,7 @@ void do_command(int c) if (file_pos > new_pos) break; line++; } - col = new_pos - line_pos(line, 0); + col = (int)(new_pos - line_pos(line, 0)); file_pos = new_pos; fix_cursor(); } else { @@ -448,7 +474,8 @@ void do_command(int c) locate_mode = 1; break; case TOP: - line = col = file_pos = 0; + line = col = 0; + file_pos = 0; break; case UP: if (line != 0) { @@ -479,7 +506,7 @@ void do_command(int c) break; } col--; file_pos--; - /* fall through: */ + /* FALLTHRU */ case DEL: if (file_pos == current_len-1) break; /* Can't delete trailing newline */ @@ -541,9 +568,11 @@ void generic_init(void) if ((f = fopen(arg_file_name, "rb")) == NULL) { initial = "\n"; } else { + size_t len; + initial = CORD_from_file(f); - if (initial == CORD_EMPTY - || CORD_fetch(initial, CORD_len(initial)-1) != '\n') { + len = CORD_len(initial); + if (0 == len || CORD_fetch(initial, len - 1) != '\n') { initial = CORD_cat(initial, "\n"); } } @@ -551,50 +580,51 @@ void generic_init(void) add_hist(initial); now -> map = current_map; now -> previous = now; /* Can't back up further: beginning of the world */ + GC_END_STUBBORN_CHANGE(now); need_redisplay = ALL; fix_cursor(); } #ifndef WIN32 -main(argc, argv) -int argc; -char ** argv; +int main(int argc, char **argv) { int c; + void *buf; -#if defined(MACINTOSH) +# if defined(MACINTOSH) console_options.title = "\pDumb Editor"; cshow(stdout); argc = ccommand(&argv); -#endif +# endif GC_INIT(); - if (argc != 2) goto usage; + if (argc != 2) { + fprintf(stderr, "Usage: %s file\n", argv[0]); + fprintf(stderr, "Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n"); + fprintf(stderr, "Undo: ^U Write to .new: ^W"); + fprintf(stderr, "Quit:^D Repeat count: ^R[n]\n"); + fprintf(stderr, "Top: ^T Locate (search, find): ^L text ^L\n"); + exit(1); + } arg_file_name = argv[1]; - setvbuf(stdout, GC_MALLOC_ATOMIC(8192), _IOFBF, 8192); + buf = GC_MALLOC_ATOMIC(8192); + if (NULL == buf) OUT_OF_MEMORY; + setvbuf(stdout, buf, _IOFBF, 8192); initscr(); noecho(); nonl(); cbreak(); generic_init(); while ((c = getchar()) != QUIT) { - if (c == EOF) break; - do_command(c); + if (c == EOF) break; + do_command(c); } -done: move(LINES-1, 0); clrtoeol(); refresh(); nl(); echo(); endwin(); - exit(0); -usage: - fprintf(stderr, "Usage: %s file\n", argv[0]); - fprintf(stderr, "Cursor keys: ^B(left) ^F(right) ^P(up) ^N(down)\n"); - fprintf(stderr, "Undo: ^U Write to .new: ^W"); - fprintf(stderr, "Quit:^D Repeat count: ^R[n]\n"); - fprintf(stderr, "Top: ^T Locate (search, find): ^L text ^L\n"); - exit(1); + return 0; } #endif /* !WIN32 */ diff --git a/src/bdwgc/cord/tests/de_win.c b/src/bdwgc/cord/tests/de_win.c index a19ff4956..f197b2ff6 100644 --- a/src/bdwgc/cord/tests/de_win.c +++ b/src/bdwgc/cord/tests/de_win.c @@ -46,9 +46,9 @@ int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, WNDCLASS wndclass; HANDLE hAccel; -# ifdef THREAD_LOCAL_ALLOC - GC_INIT(); /* Required if GC is built with THREAD_LOCAL_ALLOC */ - /* Always safe, but this is used as a GC test. */ + GC_INIT(); +# if defined(CPPCHECK) + GC_noop1((GC_word)&WinMain); # endif if (!hPrevInstance) @@ -65,11 +65,7 @@ int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wndclass.lpszClassName = szAppName; if (RegisterClass (&wndclass) == 0) { - char buf[50]; - - sprintf(buf, "RegisterClass: error code: 0x%X", - (unsigned)GetLastError()); - de_error(buf); + de_error("RegisterClass error"); return(0); } } @@ -102,11 +98,7 @@ int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, NULL, /* Window class menu */ hInstance, NULL); if (hwnd == NULL) { - char buf[50]; - - sprintf(buf, "CreateWindow: error code: 0x%X", - (unsigned)GetLastError()); - de_error(buf); + de_error("CreateWindow error"); return(0); } @@ -122,7 +114,7 @@ int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, DispatchMessage (&msg); } } - return msg.wParam; + return (int)msg.wParam; } /* Return the argument with all control characters replaced by blanks. */ @@ -131,6 +123,7 @@ char * plain_chars(char * text, size_t len) char * result = GC_MALLOC_ATOMIC(len + 1); register size_t i; + if (NULL == result) return NULL; for (i = 0; i < len; i++) { if (iscntrl(((unsigned char *)text)[i])) { result[i] = ' '; @@ -149,6 +142,7 @@ char * control_chars(char * text, size_t len) char * result = GC_MALLOC_ATOMIC(len + 1); register size_t i; + if (NULL == result) return NULL; for (i = 0; i < len; i++) { if (iscntrl(((unsigned char *)text)[i])) { result[i] = text[i] + 0x40; @@ -163,9 +157,9 @@ char * control_chars(char * text, size_t len) int char_width; int char_height; -void get_line_rect(int line, int win_width, RECT * rectp) +void get_line_rect(int line_arg, int win_width, RECT * rectp) { - rectp -> top = line * char_height; + rectp -> top = line_arg * (LONG)char_height; rectp -> bottom = rectp->top + char_height; rectp -> left = 0; rectp -> right = win_width; @@ -204,7 +198,7 @@ INT_PTR CALLBACK AboutBoxCallback( HWND hDlg, UINT message, return FALSE; } -LRESULT CALLBACK WndProc (HWND hwnd, UINT message, +LRESULT CALLBACK WndProc (HWND hwnd_arg, UINT message, WPARAM wParam, LPARAM lParam) { static HANDLE hInstance; @@ -221,13 +215,13 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message, { case WM_CREATE: hInstance = ( (LPCREATESTRUCT) lParam)->hInstance; - dc = GetDC(hwnd); + dc = GetDC(hwnd_arg); SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT)); GetTextMetrics(dc, &tm); - ReleaseDC(hwnd, dc); + ReleaseDC(hwnd_arg, dc); char_width = tm.tmAveCharWidth; char_height = tm.tmHeight + tm.tmExternalLeading; - GetClientRect(hwnd, &client_area); + GetClientRect(hwnd_arg, &client_area); COLS = (client_area.right - client_area.left)/char_width; LINES = (client_area.bottom - client_area.top)/char_height; generic_init(); @@ -235,21 +229,21 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message, case WM_CHAR: if (wParam == QUIT) { - SendMessage( hwnd, WM_CLOSE, 0, 0L ); + SendMessage(hwnd_arg, WM_CLOSE, 0, 0L); } else { do_command((int)wParam); } return(0); case WM_SETFOCUS: - CreateCaret(hwnd, NULL, char_width, char_height); - ShowCaret(hwnd); + CreateCaret(hwnd_arg, NULL, char_width, char_height); + ShowCaret(hwnd_arg); caret_visible = 1; update_cursor(); return(0); case WM_KILLFOCUS: - HideCaret(hwnd); + HideCaret(hwnd_arg); DestroyCaret(); caret_visible = 0; return(0); @@ -273,13 +267,13 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message, } else { switch(id) { case IDM_FILEEXIT: - SendMessage( hwnd, WM_CLOSE, 0, 0L ); + SendMessage(hwnd_arg, WM_CLOSE, 0, 0L); return( 0 ); case IDM_HELPABOUT: if( DialogBox( hInstance, TEXT("ABOUTBOX"), - hwnd, AboutBoxCallback ) ) - InvalidateRect( hwnd, NULL, TRUE ); + hwnd_arg, AboutBoxCallback ) ) + InvalidateRect(hwnd_arg, NULL, TRUE); return( 0 ); case IDM_HELPCONTENTS: de_error( @@ -292,7 +286,7 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message, break; case WM_CLOSE: - DestroyWindow( hwnd ); + DestroyWindow(hwnd_arg); return 0; case WM_DESTROY: @@ -301,8 +295,8 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message, return 0; case WM_PAINT: - dc = BeginPaint(hwnd, &ps); - GetClientRect(hwnd, &client_area); + dc = BeginPaint(hwnd_arg, &ps); + GetClientRect(hwnd_arg, &client_area); COLS = (client_area.right - client_area.left)/char_width; LINES = (client_area.bottom - client_area.top)/char_height; SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT)); @@ -317,27 +311,32 @@ LRESULT CALLBACK WndProc (HWND hwnd, UINT message, char * blanks = CORD_to_char_star(CORD_chars(' ', COLS - len)); char * control = control_chars(text, len); + if (NULL == plain || NULL == control) + de_error("Out of memory!"); + # define RED RGB(255,0,0) SetBkMode(dc, OPAQUE); SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT)); - TextOutA(dc, this_line.left, this_line.top, - plain, (int)len); + if (plain != NULL) + TextOutA(dc, this_line.left, this_line.top, + plain, (int)len); TextOutA(dc, this_line.left + (int)len * char_width, this_line.top, blanks, (int)(COLS - len)); SetBkMode(dc, TRANSPARENT); SetTextColor(dc, RED); - TextOutA(dc, this_line.left, this_line.top, - control, (int)strlen(control)); + if (control != NULL) + TextOutA(dc, this_line.left, this_line.top, + control, (int)strlen(control)); } } - EndPaint(hwnd, &ps); + EndPaint(hwnd_arg, &ps); screen_was_painted = 1; return 0; } - return DefWindowProc (hwnd, message, wParam, lParam); + return DefWindowProc(hwnd_arg, message, wParam, lParam); } int last_col; @@ -359,11 +358,11 @@ void update_cursor(void) void invalidate_line(int i) { - RECT line; + RECT line_r; if (!screen_was_painted) return; /* Invalidating a rectangle before painting seems result in a */ /* major performance problem. */ - get_line_rect(i, COLS*char_width, &line); - InvalidateRect(hwnd, &line, FALSE); + get_line_rect(i, COLS*char_width, &line_r); + InvalidateRect(hwnd, &line_r, FALSE); } diff --git a/src/bdwgc/cord/tests/de_win.h b/src/bdwgc/cord/tests/de_win.h index a6a02f391..93c5eebdb 100644 --- a/src/bdwgc/cord/tests/de_win.h +++ b/src/bdwgc/cord/tests/de_win.h @@ -44,11 +44,7 @@ /* Windows UI stuff */ LRESULT CALLBACK WndProc (HWND hwnd, UINT message, - UINT wParam, LONG lParam); - -LRESULT CALLBACK AboutBox( HWND hDlg, UINT message, - UINT wParam, LONG lParam ); - + WPARAM wParam, LPARAM lParam); /* Screen dimensions. Maintained by de_win.c. */ extern int LINES; diff --git a/src/bdwgc/cord/tests/de_win.rc b/src/bdwgc/cord/tests/de_win.rc index 3d1c59fb1..4ea3475a5 100644 --- a/src/bdwgc/cord/tests/de_win.rc +++ b/src/bdwgc/cord/tests/de_win.rc @@ -12,52 +12,49 @@ #include "de_cmds.h" #include "de_win.h" - ABOUTBOX DIALOG 19, 21, 163, 47 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About Demonstration Text Editor" BEGIN - /* ICON "DE", -1, 8, 8, 13, 13, WS_CHILD | WS_VISIBLE */ - LTEXT "Demonstration Text Editor", -1, 44, 8, 118, 8, WS_CHILD | WS_VISIBLE | WS_GROUP - LTEXT "Version 4.1", -1, 44, 16, 60, 8, WS_CHILD | WS_VISIBLE | WS_GROUP - PUSHBUTTON "OK", IDOK, 118, 27, 24, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP + /* ICON "DE", -1, 8, 8, 13, 13, WS_CHILD | WS_VISIBLE */ + LTEXT "Demonstration Text Editor", -1, 44, 8, 118, 8, WS_CHILD | WS_VISIBLE | WS_GROUP + LTEXT "Version 4.1", -1, 44, 16, 60, 8, WS_CHILD | WS_VISIBLE | WS_GROUP + PUSHBUTTON "OK", IDOK, 118, 27, 24, 14, WS_CHILD | WS_VISIBLE | WS_TABSTOP END - DE MENU BEGIN - POPUP "&File" - BEGIN - MENUITEM "&Save\t^W", IDM_FILESAVE - MENUITEM "E&xit\t^D", IDM_FILEEXIT - END + POPUP "&File" + BEGIN + MENUITEM "&Save\t^W", IDM_FILESAVE + MENUITEM "E&xit\t^D", IDM_FILEEXIT + END - POPUP "&Edit" - BEGIN - MENUITEM "Page &Down\t^R^N", IDM_EDITPDOWN - MENUITEM "Page &Up\t^R^P", IDM_EDITPUP - MENUITEM "U&ndo\t^U", IDM_EDITUNDO - MENUITEM "&Locate\t^L ... ^L", IDM_EDITLOCATE - MENUITEM "D&own\t^N", IDM_EDITDOWN - MENUITEM "U&p\t^P", IDM_EDITUP - MENUITEM "Le&ft\t^B", IDM_EDITLEFT - MENUITEM "&Right\t^F", IDM_EDITRIGHT - MENUITEM "Delete &Backward\tBS", IDM_EDITBS - MENUITEM "Delete F&orward\tDEL", IDM_EDITDEL - MENUITEM "&Top\t^T", IDM_EDITTOP - END + POPUP "&Edit" + BEGIN + MENUITEM "Page &Down\t^R^N", IDM_EDITPDOWN + MENUITEM "Page &Up\t^R^P", IDM_EDITPUP + MENUITEM "U&ndo\t^U", IDM_EDITUNDO + MENUITEM "&Locate\t^L ... ^L", IDM_EDITLOCATE + MENUITEM "D&own\t^N", IDM_EDITDOWN + MENUITEM "U&p\t^P", IDM_EDITUP + MENUITEM "Le&ft\t^B", IDM_EDITLEFT + MENUITEM "&Right\t^F", IDM_EDITRIGHT + MENUITEM "Delete &Backward\tBS", IDM_EDITBS + MENUITEM "Delete F&orward\tDEL", IDM_EDITDEL + MENUITEM "&Top\t^T", IDM_EDITTOP + END - POPUP "&Help" - BEGIN - MENUITEM "&Contents", IDM_HELPCONTENTS - MENUITEM "&About...", IDM_HELPABOUT - END + POPUP "&Help" + BEGIN + MENUITEM "&Contents", IDM_HELPCONTENTS + MENUITEM "&About...", IDM_HELPABOUT + END - MENUITEM "Page_&Down", IDM_EDITPDOWN - MENUITEM "Page_&Up", IDM_EDITPUP + MENUITEM "Page_&Down", IDM_EDITPDOWN + MENUITEM "Page_&Up", IDM_EDITPUP END - DE ACCELERATORS BEGIN "^R", IDM_EDITREPEAT @@ -67,9 +64,8 @@ BEGIN "^B", IDM_EDITLEFT "^F", IDM_EDITRIGHT "^T", IDM_EDITTOP - VK_DELETE, IDM_EDITDEL, VIRTKEY - VK_BACK, IDM_EDITBS, VIRTKEY + VK_DELETE, IDM_EDITDEL, VIRTKEY + VK_BACK, IDM_EDITBS, VIRTKEY END - /* DE ICON cord\de_win.ICO */ diff --git a/src/bdwgc/darwin_stop_world.c b/src/bdwgc/darwin_stop_world.c index 84c60eb27..5f7dcfdef 100644 --- a/src/bdwgc/darwin_stop_world.c +++ b/src/bdwgc/darwin_stop_world.c @@ -73,7 +73,7 @@ GC_INNER ptr_t GC_FindTopOfStack(unsigned long stack_start) } # ifdef DEBUG_THREADS_EXTRA - GC_log_printf("FindTopOfStack start at sp = %p\n", frame); + GC_log_printf("FindTopOfStack start at sp = %p\n", (void *)frame); # endif while (frame->savedSP != 0) { /* if there are no more stack frames, stop */ @@ -83,11 +83,11 @@ GC_INNER ptr_t GC_FindTopOfStack(unsigned long stack_start) /* we do these next two checks after going to the next frame because the LR for the first stack frame in the loop is not set up on purpose, so we shouldn't check it. */ - if ((frame->savedLR & ~0x3) == 0 || (frame->savedLR & ~0x3) == ~0x3U) + if ((frame->savedLR & ~0x3) == 0 || (frame->savedLR & ~0x3) == ~0x3UL) break; /* if the next LR is bogus, stop */ } # ifdef DEBUG_THREADS_EXTRA - GC_log_printf("FindTopOfStack finish at sp = %p\n", frame); + GC_log_printf("FindTopOfStack finish at sp = %p\n", (void *)frame); # endif return (ptr_t)frame; } @@ -129,7 +129,9 @@ GC_API void GC_CALL GC_use_threads_discovery(void) /* Evaluates the stack range for a given thread. Returns the lower */ /* bound and sets *phi to the upper one. */ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p, - GC_bool thread_blocked, mach_port_t my_thread) + GC_bool thread_blocked, mach_port_t my_thread, + ptr_t *paltstack_lo, + ptr_t *paltstack_hi GC_ATTR_UNUSED) { ptr_t lo; if (thread == my_thread) { @@ -140,6 +142,9 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p, # endif } else if (thread_blocked) { +# if defined(CPPCHECK) + if (NULL == p) ABORT("Invalid GC_thread passed to GC_stack_range_for"); +# endif lo = p->stop_info.stack_ptr; # ifndef DARWIN_DONT_PARSE_STACK *phi = p->topOfStack; @@ -167,14 +172,20 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p, arm_unified_thread_state_t unified_state; mach_msg_type_number_t unified_thread_state_count = ARM_UNIFIED_THREAD_STATE_COUNT; - - kern_result = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE, +# if defined(CPPCHECK) +# define GC_ARM_UNIFIED_THREAD_STATE 1 +# else +# define GC_ARM_UNIFIED_THREAD_STATE ARM_UNIFIED_THREAD_STATE +# endif + kern_result = thread_get_state(thread, GC_ARM_UNIFIED_THREAD_STATE, (natural_t *)&unified_state, &unified_thread_state_count); - if (unified_state.ash.flavor != ARM_THREAD_STATE32) { - ABORT("unified_state flavor should be ARM_THREAD_STATE32"); - } - state = unified_state.ts_32; +# if !defined(CPPCHECK) + if (unified_state.ash.flavor != ARM_THREAD_STATE32) { + ABORT("unified_state flavor should be ARM_THREAD_STATE32"); + } +# endif + state = unified_state; } else # endif /* else */ { @@ -293,6 +304,8 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p, GC_push_one(state.THREAD_FLD(fp)); GC_push_one(state.THREAD_FLD(lr)); +# elif defined(CPPCHECK) + lo = NULL; # else # error FIXME for non-x86 || ppc || arm architectures # endif @@ -302,17 +315,30 @@ STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p, /* p is guaranteed to be non-NULL regardless of GC_query_task_threads. */ *phi = (p->flags & MAIN_THREAD) != 0 ? GC_stackbottom : p->stack_end; # endif + + /* TODO: Determine p and handle altstack if !DARWIN_DONT_PARSE_STACK */ +# ifdef DARWIN_DONT_PARSE_STACK + if (p->altstack != NULL && (word)p->altstack <= (word)lo + && (word)lo <= (word)p->altstack + p->altstack_size) { + *paltstack_lo = lo; + *paltstack_hi = p->altstack + p->altstack_size; + lo = p->stack; + *phi = p->stack + p->stack_size; + } else +# endif + /* else */ { + *paltstack_lo = NULL; + } # ifdef DEBUG_THREADS GC_log_printf("Darwin: Stack for thread %p = [%p,%p)\n", - (void *)thread, lo, *phi); + (void *)(word)thread, (void *)lo, (void *)(*phi)); # endif return lo; } GC_INNER void GC_push_all_stacks(void) { - int i; - ptr_t lo, hi; + ptr_t hi, altstack_lo, altstack_hi; task_t my_task = current_task(); mach_port_t my_thread = mach_thread_self(); GC_bool found_me = FALSE; @@ -324,6 +350,7 @@ GC_INNER void GC_push_all_stacks(void) # ifndef DARWIN_DONT_PARSE_STACK if (GC_query_task_threads) { + int i; kern_return_t kern_result; thread_act_array_t act_list = 0; @@ -334,10 +361,15 @@ GC_INNER void GC_push_all_stacks(void) for (i = 0; i < (int)listcount; i++) { thread_act_t thread = act_list[i]; - lo = GC_stack_range_for(&hi, thread, NULL, FALSE, my_thread); - GC_ASSERT((word)lo <= (word)hi); - total_size += hi - lo; - GC_push_all_stack(lo, hi); + ptr_t lo = GC_stack_range_for(&hi, thread, NULL, FALSE, my_thread, + &altstack_lo, &altstack_hi); + + if (lo) { + GC_ASSERT((word)lo <= (word)hi); + total_size += hi - lo; + GC_push_all_stack(lo, hi); + } + /* TODO: Handle altstack */ nthreads++; if (thread == my_thread) found_me = TRUE; @@ -349,16 +381,28 @@ GC_INNER void GC_push_all_stacks(void) } else # endif /* !DARWIN_DONT_PARSE_STACK */ /* else */ { + int i; + for (i = 0; i < (int)listcount; i++) { GC_thread p; + for (p = GC_threads[i]; p != NULL; p = p->next) if ((p->flags & FINISHED) == 0) { thread_act_t thread = (thread_act_t)p->stop_info.mach_thread; - lo = GC_stack_range_for(&hi, thread, p, (GC_bool)p->thread_blocked, - my_thread); - GC_ASSERT((word)lo <= (word)hi); - total_size += hi - lo; - GC_push_all_stack_sections(lo, hi, p->traced_stack_sect); + ptr_t lo = GC_stack_range_for(&hi, thread, p, + (GC_bool)p->thread_blocked, + my_thread, &altstack_lo, + &altstack_hi); + + if (lo) { + GC_ASSERT((word)lo <= (word)hi); + total_size += hi - lo; + GC_push_all_stack_sections(lo, hi, p->traced_stack_sect); + } + if (altstack_lo) { + total_size += altstack_hi - altstack_lo; + GC_push_all_stack(altstack_lo, altstack_hi); + } nthreads++; if (thread == my_thread) found_me = TRUE; @@ -429,7 +473,8 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, # endif # ifdef DEBUG_THREADS - GC_log_printf("Attempting to suspend thread %p\n", (void *)thread); + GC_log_printf("Attempting to suspend thread %p\n", + (void *)(word)thread); # endif /* find the current thread in the old list */ found = FALSE; @@ -473,7 +518,8 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, continue; } # ifdef DEBUG_THREADS - GC_log_printf("Thread state for %p = %d\n", (void *)thread, info.run_state); + GC_log_printf("Thread state for %p = %d\n", (void *)(word)thread, + info.run_state); # endif if (info.suspend_count != 0) { /* thread is already suspended. */ @@ -483,9 +529,11 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, } # ifdef DEBUG_THREADS - GC_log_printf("Suspending %p\n", (void *)thread); + GC_log_printf("Suspending %p\n", (void *)(word)thread); # endif - kern_result = thread_suspend(thread); + do { + kern_result = thread_suspend(thread); + } while (kern_result == KERN_ABORTED); if (kern_result != KERN_SUCCESS) { /* The thread may have quit since the thread_threads() call we */ /* mark already suspended so it's not dealt with anymore later. */ @@ -495,6 +543,8 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, } if (!found) GC_mach_threads_count++; + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, (void *)(word)thread); } return changed; } @@ -504,13 +554,13 @@ STATIC GC_bool GC_suspend_thread_list(thread_act_array_t act_list, int count, /* Caller holds allocation lock. */ GC_INNER void GC_stop_world(void) { - unsigned i; task_t my_task = current_task(); mach_port_t my_thread = mach_thread_self(); kern_return_t kern_result; # ifdef DEBUG_THREADS - GC_log_printf("Stopping the world from thread %p\n", (void *)my_thread); + GC_log_printf("Stopping the world from thread %p\n", + (void *)(word)my_thread); # endif # ifdef PARALLEL_MARK if (GC_parallel) { @@ -526,6 +576,7 @@ GC_INNER void GC_stop_world(void) if (GC_query_task_threads) { # ifndef GC_NO_THREADS_DISCOVERY + unsigned i; GC_bool changed; thread_act_array_t act_list, prev_list; mach_msg_type_number_t listcount, prevcount; @@ -573,6 +624,8 @@ GC_INNER void GC_stop_world(void) # endif /* !GC_NO_THREADS_DISCOVERY */ } else { + unsigned i; + for (i = 0; i < THREAD_TABLE_SZ; i++) { GC_thread p; @@ -580,9 +633,14 @@ GC_INNER void GC_stop_world(void) if ((p->flags & FINISHED) == 0 && !p->thread_blocked && p->stop_info.mach_thread != my_thread) { - kern_result = thread_suspend(p->stop_info.mach_thread); + do { + kern_result = thread_suspend(p->stop_info.mach_thread); + } while (kern_result == KERN_ABORTED); if (kern_result != KERN_SUCCESS) ABORT("thread_suspend failed"); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, + (void *)(word)p->stop_info.mach_thread); } } } @@ -599,7 +657,7 @@ GC_INNER void GC_stop_world(void) # endif # ifdef DEBUG_THREADS - GC_log_printf("World stopped from %p\n", (void *)my_thread); + GC_log_printf("World stopped from %p\n", (void *)(word)my_thread); # endif mach_port_deallocate(my_task, my_thread); } @@ -616,13 +674,15 @@ GC_INLINE void GC_thread_resume(thread_act_t thread) ABORT("thread_info failed"); # endif # ifdef DEBUG_THREADS - GC_log_printf("Resuming thread %p with state %d\n", (void *)thread, + GC_log_printf("Resuming thread %p with state %d\n", (void *)(word)thread, info.run_state); # endif /* Resume the thread */ kern_result = thread_resume(thread); if (kern_result != KERN_SUCCESS) ABORT("thread_resume failed"); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, (void *)(word)thread); } /* Caller holds allocation lock, and has held it continuously since */ @@ -630,7 +690,6 @@ GC_INLINE void GC_thread_resume(thread_act_t thread) GC_INNER void GC_start_world(void) { task_t my_task = current_task(); - int i; # ifdef DEBUG_THREADS GC_log_printf("World starting\n"); # endif @@ -642,6 +701,7 @@ GC_INNER void GC_start_world(void) if (GC_query_task_threads) { # ifndef GC_NO_THREADS_DISCOVERY + int i; int j = GC_mach_threads_count; kern_return_t kern_result; thread_act_array_t act_list; @@ -675,7 +735,7 @@ GC_INNER void GC_start_world(void) if (GC_mach_threads[j].already_suspended) { # ifdef DEBUG_THREADS GC_log_printf("Not resuming already suspended thread %p\n", - (void *)thread); + (void *)(word)thread); # endif } else { GC_thread_resume(thread); @@ -689,6 +749,7 @@ GC_INNER void GC_start_world(void) # endif /* !GC_NO_THREADS_DISCOVERY */ } else { + int i; mach_port_t my_thread = mach_thread_self(); for (i = 0; i < THREAD_TABLE_SZ; i++) { diff --git a/src/bdwgc/dbg_mlc.c b/src/bdwgc/dbg_mlc.c index fef1a251d..c5e4aa7ab 100644 --- a/src/bdwgc/dbg_mlc.c +++ b/src/bdwgc/dbg_mlc.c @@ -54,9 +54,24 @@ } #endif /* !SHORT_DBG_HDRS */ +#ifdef LINT2 + long GC_random(void) + { + static unsigned seed = 1; /* not thread-safe */ + + /* Linear congruential pseudo-random numbers generator. */ + seed = (seed * 1103515245U + 12345) & GC_RAND_MAX; /* overflow is ok */ + return (long)seed; + } +#endif + #ifdef KEEP_BACK_PTRS +#ifdef LINT2 +# define RANDOM() GC_random() +#else # include +# define GC_RAND_MAX RAND_MAX # if defined(__GLIBC__) || defined(SOLARIS) \ || defined(HPUX) || defined(IRIX5) || defined(OSF1) @@ -64,6 +79,7 @@ # else # define RANDOM() (long)rand() # endif +#endif /* !LINT2 */ /* Store back pointer to source in dest, if that appears to be possible. */ /* This is not completely safe, since we may mistakenly conclude that */ @@ -142,11 +158,10 @@ GC_API void * GC_CALL GC_generate_random_heap_address(void) { size_t i; - size_t size; word heap_offset = RANDOM(); - if (GC_heapsize > RAND_MAX) { - heap_offset *= RAND_MAX; + if (GC_heapsize > GC_RAND_MAX) { + heap_offset *= GC_RAND_MAX; heap_offset += RANDOM(); } heap_offset %= GC_heapsize; @@ -154,6 +169,8 @@ /* e.g. RAND_MAX = 1.5* GC_heapsize. But for typical cases, */ /* it's not too bad. */ for (i = 0;; ++i) { + size_t size; + if (i >= GC_n_heap_sects) ABORT("GC_generate_random_heap_address: size inconsistency"); @@ -250,15 +267,13 @@ # define CROSSES_HBLK(p, sz) \ (((word)((p) + sizeof(oh) + (sz) - 1) ^ (word)(p)) >= HBLKSIZE) -/* Store debugging info into p. Return displaced pointer. */ -/* This version assumes we do hold the allocation lock. */ -STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz GC_ATTR_UNUSED, - const char *string, int linenum) +GC_INNER void *GC_store_debug_info_inner(void *p, word sz GC_ATTR_UNUSED, + const char *string, int linenum) { word * result = (word *)((oh *)p + 1); GC_ASSERT(GC_size(p) >= sizeof(oh) + sz); - GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz))); + GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK((ptr_t)p, sz))); # ifdef KEEP_BACK_PTRS ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED); # endif @@ -276,14 +291,24 @@ STATIC ptr_t GC_store_debug_info_inner(ptr_t p, word sz GC_ATTR_UNUSED, return((ptr_t)result); } -GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *string, - int linenum) +/* Check the allocation is successful, store debugging info into p, */ +/* start the debugging mode (if not yet), and return displaced pointer. */ +static void *store_debug_info(void *p, size_t lb, + const char *fn, GC_EXTRA_PARAMS) { - ptr_t result; + void *result; DCL_LOCK_STATE; + if (NULL == p) { + GC_err_printf("%s(%lu) returning NULL (%s:%d)\n", + fn, (unsigned long)lb, s, i); + return NULL; + } LOCK(); - result = GC_store_debug_info_inner(p, sz, string, linenum); + if (!GC_debugging_started) + GC_start_debugging_inner(); + ADD_CALL_CHAIN(p, ra); + result = GC_store_debug_info_inner(p, (word)lb, s, i); UNLOCK(); return result; } @@ -370,7 +395,7 @@ STATIC void GC_print_obj(ptr_t p) case UNCOLLECTABLE: kind_str = "UNCOLLECTABLE"; break; -# ifdef ATOMIC_UNCOLLECTABLE +# ifdef GC_ATOMIC_UNCOLLECTABLE case AUNCOLLECTABLE: kind_str = "ATOMIC_UNCOLLECTABLE"; break; @@ -387,13 +412,14 @@ STATIC void GC_print_obj(ptr_t p) if (NULL != kind_str) { GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz=%lu,") " %s)\n", - (ptr_t)ohdr + sizeof(oh), + (void *)((ptr_t)ohdr + sizeof(oh)), ohdr->oh_string, GET_OH_LINENUM(ohdr) /*, */ COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz), kind_str); } else { GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz=%lu,") - " kind=%d descr=0x%lx)\n", (ptr_t)ohdr + sizeof(oh), + " kind=%d descr=0x%lx)\n", + (void *)((ptr_t)ohdr + sizeof(oh)), ohdr->oh_string, GET_OH_LINENUM(ohdr) /*, */ COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz), kind, (unsigned long)hhdr->hb_descr); @@ -428,11 +454,11 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t p) || ohdr -> oh_string == 0) { GC_err_printf( "%s %p in or near object at %p(, appr. sz = %lu)\n", - msg, clobbered_addr, p, + msg, (void *)clobbered_addr, (void *)p, (unsigned long)(GC_size((ptr_t)ohdr) - DEBUG_BYTES)); } else { GC_err_printf("%s %p in or near object at %p (%s:%d, sz=%lu)\n", - msg, clobbered_addr, p, + msg, (void *)clobbered_addr, (void *)p, (word)(ohdr -> oh_string) < HBLKSIZE ? "(smashed string)" : ohdr -> oh_string[0] == '\0' ? "EMPTY(smashed?)" : ohdr -> oh_string, @@ -440,16 +466,14 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t p) PRINT_CALL_CHAIN(ohdr); } } -#endif -#ifndef SHORT_DBG_HDRS STATIC void GC_check_heap_proc (void); STATIC void GC_print_all_smashed_proc (void); #else STATIC void GC_do_nothing(void) {} #endif -STATIC void GC_start_debugging_inner(void) +GC_INNER void GC_start_debugging_inner(void) { GC_ASSERT(I_HOLD_LOCK()); # ifndef SHORT_DBG_HDRS @@ -464,15 +488,6 @@ STATIC void GC_start_debugging_inner(void) GC_register_displacement_inner((word)sizeof(oh)); } -GC_INNER void GC_start_debugging(void) -{ - DCL_LOCK_STATE; - - LOCK(); - GC_start_debugging_inner(); - UNLOCK(); -} - size_t GC_debug_header_size = sizeof(oh); GC_API void GC_CALL GC_debug_register_displacement(size_t offset) @@ -486,7 +501,7 @@ GC_API void GC_CALL GC_debug_register_displacement(size_t offset) } #ifdef GC_ADD_CALLER -# if defined(HAVE_DLADDR) && defined(GC_RETURN_ADDR_PARENT) +# if defined(HAVE_DLADDR) && defined(GC_HAVE_RETURN_ADDR_PARENT) # include STATIC void GC_caller_func_offset(word ad, const char **symp, int *offp) @@ -514,84 +529,52 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc(size_t lb, /* Note that according to malloc() specification, if size is 0 then */ /* malloc() returns either NULL, or a unique pointer value that can */ /* later be successfully passed to free(). We always do the latter. */ - result = GC_malloc(lb + DEBUG_BYTES); + result = GC_malloc(SIZET_SAT_ADD(lb, DEBUG_BYTES)); # ifdef GC_ADD_CALLER if (s == NULL) { GC_caller_func_offset(ra, &s, &i); } # endif - if (result == 0) { - GC_err_printf("GC_debug_malloc(%lu) returning NULL (%s:%d)\n", - (unsigned long)lb, s, i); - return(0); - } - if (!GC_debugging_started) { - GC_start_debugging(); - } - ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, i)); + return store_debug_info(result, lb, "GC_debug_malloc", OPT_RA s, i); } GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_ignore_off_page(size_t lb, GC_EXTRA_PARAMS) { - void * result = GC_malloc_ignore_off_page(lb + DEBUG_BYTES); + void * result = GC_malloc_ignore_off_page(SIZET_SAT_ADD(lb, DEBUG_BYTES)); - if (result == 0) { - GC_err_printf("GC_debug_malloc_ignore_off_page(%lu)" - " returning NULL (%s:%d)\n", (unsigned long)lb, s, i); - return(0); - } - if (!GC_debugging_started) { - GC_start_debugging(); - } - ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, i)); + return store_debug_info(result, lb, "GC_debug_malloc_ignore_off_page", + OPT_RA s, i); } GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_atomic_ignore_off_page(size_t lb, GC_EXTRA_PARAMS) { - void * result = GC_malloc_atomic_ignore_off_page(lb + DEBUG_BYTES); + void * result = GC_malloc_atomic_ignore_off_page( + SIZET_SAT_ADD(lb, DEBUG_BYTES)); - if (result == 0) { - GC_err_printf("GC_debug_malloc_atomic_ignore_off_page(%lu)" - " returning NULL (%s:%d)\n", (unsigned long)lb, s, i); - return(0); - } - if (!GC_debugging_started) { - GC_start_debugging(); - } - ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, i)); + return store_debug_info(result, lb, + "GC_debug_malloc_atomic_ignore_off_page", + OPT_RA s, i); } STATIC void * GC_debug_generic_malloc(size_t lb, int knd, GC_EXTRA_PARAMS) { - void * result = GC_generic_malloc(lb + DEBUG_BYTES, knd); + void * result = GC_generic_malloc(SIZET_SAT_ADD(lb, DEBUG_BYTES), knd); - if (NULL == result) { - GC_err_printf( - "GC_debug_generic_malloc(%lu, %d) returning NULL (%s:%d)\n", - (unsigned long)lb, knd, s, i); - return NULL; - } - if (!GC_debugging_started) { - GC_start_debugging(); - } - ADD_CALL_CHAIN(result, ra); - return GC_store_debug_info(result, (word)lb, s, i); + return store_debug_info(result, lb, "GC_debug_generic_malloc", + OPT_RA s, i); } #ifdef DBG_HDRS_ALL /* An allocation function for internal use. Normally internally */ /* allocated objects do not have debug information. But in this */ /* case, we need to make sure that all objects have debug headers. */ - /* We assume debugging was started in collector initialization, and */ - /* we already hold the GC lock. */ + /* We assume we already hold the GC lock. */ GC_INNER void * GC_debug_generic_malloc_inner(size_t lb, int k) { - void * result = GC_generic_malloc_inner(lb + DEBUG_BYTES, k); + void * result = GC_generic_malloc_inner( + SIZET_SAT_ADD(lb, DEBUG_BYTES), k); if (result == 0) { GC_err_printf("GC internal allocation (%lu bytes) returning NULL\n", @@ -609,7 +592,7 @@ STATIC void * GC_debug_generic_malloc(size_t lb, int knd, GC_EXTRA_PARAMS) int k) { void * result = GC_generic_malloc_inner_ignore_off_page( - lb + DEBUG_BYTES, k); + SIZET_SAT_ADD(lb, DEBUG_BYTES), k); if (result == 0) { GC_err_printf("GC internal allocation (%lu bytes) returning NULL\n", @@ -628,18 +611,10 @@ STATIC void * GC_debug_generic_malloc(size_t lb, int knd, GC_EXTRA_PARAMS) GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS) { - void * result = GC_malloc_stubborn(lb + DEBUG_BYTES); + void * result = GC_malloc_stubborn(SIZET_SAT_ADD(lb, DEBUG_BYTES)); - if (result == 0) { - GC_err_printf("GC_debug_malloc_stubborn(%lu)" - " returning NULL (%s:%d)\n", (unsigned long)lb, s, i); - return(0); - } - if (!GC_debugging_started) { - GC_start_debugging(); - } - ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, i)); + return store_debug_info(result, lb, "GC_debug_malloc_stubborn", + OPT_RA s, i); } GC_API void GC_CALL GC_debug_change_stubborn(const void *p) @@ -657,22 +632,6 @@ STATIC void * GC_debug_generic_malloc(size_t lb, int knd, GC_EXTRA_PARAMS) GC_change_stubborn(q); } - GC_API void GC_CALL GC_debug_end_stubborn_change(const void *p) - { - const void * q = GC_base_C(p); - hdr * hhdr; - - if (q == 0) { - ABORT_ARG1("GC_debug_end_stubborn_change: bad arg", ": %p", p); - } - hhdr = HDR(q); - if (hhdr -> hb_obj_kind != STUBBORN) { - ABORT_ARG1("GC_debug_end_stubborn_change: arg not stubborn", - ": %p", p); - } - GC_end_stubborn_change(q); - } - #else /* !STUBBORN_ALLOC */ GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_stubborn(size_t lb, @@ -683,26 +642,30 @@ STATIC void * GC_debug_generic_malloc(size_t lb, int knd, GC_EXTRA_PARAMS) GC_API void GC_CALL GC_debug_change_stubborn( const void * p GC_ATTR_UNUSED) {} - - GC_API void GC_CALL GC_debug_end_stubborn_change( - const void * p GC_ATTR_UNUSED) {} #endif /* !STUBBORN_ALLOC */ +GC_API void GC_CALL GC_debug_end_stubborn_change(const void *p) +{ + const void * q = GC_base_C(p); + + if (NULL == q) { + ABORT_ARG1("GC_debug_end_stubborn_change: bad arg", ": %p", p); + } +# ifdef STUBBORN_ALLOC + if (HDR(q) -> hb_obj_kind != STUBBORN) + ABORT_ARG1("GC_debug_end_stubborn_change: arg not stubborn", + ": %p", p); +# endif + GC_end_stubborn_change(q); +} + GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS) { - void * result = GC_malloc_atomic(lb + DEBUG_BYTES); + void * result = GC_malloc_atomic(SIZET_SAT_ADD(lb, DEBUG_BYTES)); - if (result == 0) { - GC_err_printf("GC_debug_malloc_atomic(%lu) returning NULL (%s:%d)\n", - (unsigned long)lb, s, i); - return(0); - } - if (!GC_debugging_started) { - GC_start_debugging(); - } - ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, i)); + return store_debug_info(result, lb, "GC_debug_malloc_atomic", + OPT_RA s, i); } GC_API GC_ATTR_MALLOC char * GC_CALL GC_debug_strdup(const char *str, @@ -769,39 +732,25 @@ GC_API GC_ATTR_MALLOC char * GC_CALL GC_debug_strndup(const char *str, GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS) { - void * result = GC_malloc_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES); + void * result = GC_malloc_uncollectable( + SIZET_SAT_ADD(lb, UNCOLLECTABLE_DEBUG_BYTES)); - if (result == 0) { - GC_err_printf("GC_debug_malloc_uncollectable(%lu)" - " returning NULL (%s:%d)\n", (unsigned long)lb, s, i); - return(0); - } - if (!GC_debugging_started) { - GC_start_debugging(); - } - ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, i)); + return store_debug_info(result, lb, "GC_debug_malloc_uncollectable", + OPT_RA s, i); } -#ifdef ATOMIC_UNCOLLECTABLE +#ifdef GC_ATOMIC_UNCOLLECTABLE GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_atomic_uncollectable(size_t lb, GC_EXTRA_PARAMS) { - void * result = - GC_malloc_atomic_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES); + void * result = GC_malloc_atomic_uncollectable( + SIZET_SAT_ADD(lb, UNCOLLECTABLE_DEBUG_BYTES)); - if (result == 0) { - GC_err_printf("GC_debug_malloc_atomic_uncollectable(%lu)" - " returning NULL (%s:%d)\n", (unsigned long)lb, s, i); - return(0); - } - if (!GC_debugging_started) { - GC_start_debugging(); - } - ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, i)); + return store_debug_info(result, lb, + "GC_debug_malloc_atomic_uncollectable", + OPT_RA s, i); } -#endif /* ATOMIC_UNCOLLECTABLE */ +#endif /* GC_ATOMIC_UNCOLLECTABLE */ #ifndef GC_FREED_MEM_MARKER # if CPP_WORDSZ == 32 @@ -818,6 +767,14 @@ GC_API void GC_CALL GC_debug_free(void * p) base = GC_base(p); if (base == 0) { +# if defined(REDIRECT_MALLOC) \ + && ((defined(NEED_CALLINFO) && defined(GC_HAVE_BUILTIN_BACKTRACE)) \ + || defined(GC_LINUX_THREADS) || defined(GC_SOLARIS_THREADS) \ + || defined(MSWIN32)) + /* In some cases, we should ignore objects that do not belong */ + /* to the GC heap. See the comment in GC_free. */ + if (!GC_is_heap_ptr(p)) return; +# endif ABORT_ARG1("Invalid pointer passed to free()", ": %p", p); } if ((ptr_t)p - (ptr_t)base != sizeof(oh)) { @@ -852,7 +809,7 @@ GC_API void GC_CALL GC_debug_free(void * p) } else { hdr * hhdr = HDR(p); if (hhdr -> hb_obj_kind == UNCOLLECTABLE -# ifdef ATOMIC_UNCOLLECTABLE +# ifdef GC_ATOMIC_UNCOLLECTABLE || hhdr -> hb_obj_kind == AUNCOLLECTABLE # endif ) { @@ -894,6 +851,11 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) if (p == 0) { return GC_debug_malloc(lb, OPT_RA s, i); } + if (0 == lb) /* and p != NULL */ { + GC_debug_free(p); + return NULL; + } + # ifdef GC_ADD_CALLER if (s == NULL) { GC_caller_func_offset(ra, &s, &i); @@ -924,7 +886,7 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) case UNCOLLECTABLE: result = GC_debug_malloc_uncollectable(lb, OPT_RA s, i); break; -# ifdef ATOMIC_UNCOLLECTABLE +# ifdef GC_ATOMIC_UNCOLLECTABLE case AUNCOLLECTABLE: result = GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i); break; @@ -961,7 +923,7 @@ GC_API GC_ATTR_MALLOC void * GC_CALL return GC_debug_malloc(lb, OPT_RA s, i); case UNCOLLECTABLE: return GC_debug_malloc_uncollectable(lb, OPT_RA s, i); -# ifdef ATOMIC_UNCOLLECTABLE +# ifdef GC_ATOMIC_UNCOLLECTABLE case AUNCOLLECTABLE: return GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i); # endif @@ -1109,7 +1071,7 @@ STATIC void GC_CALLBACK GC_debug_invoke_finalizer(void * obj, void * data) } /* Special finalizer_proc value to detect GC_register_finalizer() failure. */ -#define OFN_UNSET (GC_finalization_proc)(signed_word)-1 +#define OFN_UNSET ((GC_finalization_proc)~(signed_word)0) /* Set ofn and ocd to reflect the values we got back. */ static void store_old(void *obj, GC_finalization_proc my_old_fn, diff --git a/src/bdwgc/digimars.mak b/src/bdwgc/digimars.mak index 7c75eb42d..323647208 100644 --- a/src/bdwgc/digimars.mak +++ b/src/bdwgc/digimars.mak @@ -2,9 +2,8 @@ # compiler from www.digitalmars.com # Written by Walter Bright - -DEFINES=-DNDEBUG -D_WINDOWS -DGC_DLL -DALL_INTERIOR_POINTERS -DWIN32_THREADS -CFLAGS=-Iinclude $(DEFINES) -wx -g +DEFINES=-D_WINDOWS -DGC_DLL -DGC_THREADS -DGC_DISCOVER_TASK_THREADS -DALL_INTERIOR_POINTERS +CFLAGS=-Iinclude -Ilibatomic_ops\src $(DEFINES) -wx -g LFLAGS=/ma/implib/co CC=sc @@ -40,31 +39,35 @@ OBJS= \ typd_mlc.obj\ win32_threads.obj -targets: gc.dll gc.lib gctest.exe +targets: gc.dll gc.lib gctest.exe test_cpp.exe gc.dll: $(OBJS) gc.def digimars.mak - sc -ogc.dll $(OBJS) -L$(LFLAGS) gc.def kernel32.lib user32.lib + $(CC) -ogc.dll $(OBJS) -L$(LFLAGS) gc.def kernel32.lib user32.lib gc.def: digimars.mak echo LIBRARY GC >gc.def - echo DESCRIPTION "Hans Boehm Garbage Collector" >>gc.def + echo DESCRIPTION "Boehm-Demers-Weiser Garbage Collector" >>gc.def echo EXETYPE NT >>gc.def echo EXPORTS >>gc.def echo GC_is_visible_print_proc >>gc.def echo GC_is_valid_displacement_print_proc >>gc.def clean: - del gc.def + del *.log gc.def gc.dll gc.lib gc.map gctest.map test_cpp.map + del tests\test.obj gctest.exe tests\test_cpp.obj test_cpp.exe del $(OBJS) +gctest.exe: gc.lib tests\test.obj + $(CC) -ogctest.exe tests\test.obj gc.lib -gctest.exe : gc.lib tests\test.obj - sc -ogctest.exe tests\test.obj gc.lib +tests\test.obj: tests\test.c + $(CC) -c $(CFLAGS) tests\test.c -otests\test.obj -tests\test.obj : tests\test.c - $(CC) -c -g -DNDEBUG -D_WINDOWS -DGC_DLL \ - -DALL_INTERIOR_POINTERS -DWIN32_THREADS \ - -Iinclude tests\test.c -otests\test.obj +test_cpp.exe: gc.lib tests\test_cpp.obj + $(CC) -otest_cpp.exe tests\test_cpp.obj gc.lib + +tests\test_cpp.obj: tests\test_cpp.cc + $(CC) -c $(CFLAGS) -cpp tests\test_cpp.cc -otests\test_cpp.obj allchblk.obj: allchblk.c alloc.obj: alloc.c @@ -74,7 +77,7 @@ dbg_mlc.obj: dbg_mlc.c dyn_load.obj: dyn_load.c finalize.obj: finalize.c fnlz_mlc.obj: fnlz_mlc.c -gc_cpp.obj: gc_cpp.cpp +gc_cpp.obj: gc_cpp.cc gc_cpp.cpp headers.obj: headers.c mach_dep.obj: mach_dep.c malloc.obj: malloc.c diff --git a/src/bdwgc/doc/README.DGUX386 b/src/bdwgc/doc/README.DGUX386 index 0aa89bdfc..2683f147c 100644 --- a/src/bdwgc/doc/README.DGUX386 +++ b/src/bdwgc/doc/README.DGUX386 @@ -1,4 +1,4 @@ - Garbage Collector (parallel iversion) for ix86 DG/UX Release R4.20MU07 + Garbage Collector (parallel version) for x86 DG/UX Release R4.20MU07 *READ* the file README.QUICK. @@ -7,7 +7,7 @@ This compiler has the new "dgux386" threads package implemented. It also supports the switch "-pthread" needed to link correctly the DG/UX's -lrte -lthread with -lgcc and the system's -lc. - Finally we support parralleli-mark for the SMP DG/UX machines. + Finally, we support parallel mark for the SMP DG/UX machines. To build the garbage collector do: ./configure --enable-parallel-mark @@ -24,13 +24,7 @@ To enable debugging messages please do: 1) Add the "--enable-gc-debug" flag during configuration. - 2) Edit the file linux-threads.c and uncomment the line: - - /* #define DEBUG_THREADS 1 */ to ---> - - #define DEBUG_THREADS 1 - - Then give "make" as usual. + 2) Pass "CFLAGS=-DDEBUG_THREADS" to "make". In a machine with 4 CPUs (my own machine) the option parallel mark (aka --enable-parallel-mark) makes a BIG difference. diff --git a/src/bdwgc/doc/README.Mac b/src/bdwgc/doc/README.Mac index 55906697d..aea1d172d 100644 --- a/src/bdwgc/doc/README.Mac +++ b/src/bdwgc/doc/README.Mac @@ -126,7 +126,7 @@ o 68K Linker Prefix Files to configure the GC sources ---------------------------------------- -The Codewarrior equivalent of commandline compilers -DNAME=X is to use +The Codewarrior equivalent of command-line compilers -DNAME=X is to use prefix-files. A TEXT file that is automatically #included before the first byte of every source file. I used these: @@ -161,7 +161,7 @@ of every source file. I used these: #define ALL_INTERIOR_POINTERS // follows interior pointers. //#define DONT_ADD_BYTE_AT_END // disables the padding if defined. //#define SMALL_CONFIG // whether to use a smaller heap. - #define ATOMIC_UNCOLLECTABLE // GC_malloc_atomic_uncollectable() + #define GC_ATOMIC_UNCOLLECTABLE // GC_malloc_atomic_uncollectable() // define either or none as per personal preference // used in malloc.c @@ -271,7 +271,7 @@ action! malloc will call GC_malloc and free GC_free, new/delete too. You don't have to call free or delete. You may have to be a bit cautious about delete if you're freeing other resources than RAM. See gc_cpp.h. You can also keep coding as always with delete/free. That works too. If you want, -"include and tweak it's use a bit. +include "gc.h" and tweak its use a bit. == Symantec SPM == diff --git a/src/bdwgc/doc/README.amiga b/src/bdwgc/doc/README.amiga index d4b825ac3..fb9aacc99 100644 --- a/src/bdwgc/doc/README.amiga +++ b/src/bdwgc/doc/README.amiga @@ -48,7 +48,7 @@ WHATS NEW: It is also the most important flag to set to prevent GC from returning chip-mem. Beware that it slows down a lot when a program is rapidly allocating/deallocating when - theres either very little fast-memory left or verly little + there's either very little fast-memory left or very little chip-memory left. Its not a very common situation, but gctest sometimes (very rare) use many minutes because of this. @@ -62,7 +62,7 @@ WHATS NEW: program, and prints out the info when the atexit-handler is called. - My reccomendation is to set all this flags, except GC_AMIGA_PRINTSTATS and + My recommendation is to set all this flags, except GC_AMIGA_PRINTSTATS and GC_AMIGA_ONLYFAST. If your program demands high response-time, you should @@ -70,7 +70,7 @@ WHATS NEW: GC_AMIGA_RETRY does not seem to slow down much. Also, when compiling up programs, and GC_AMIGA_FASTALLOC was not defined when - compilling gc, you can define GC_AMIGA_MAKINGLIB to avoid having these allocation- + compiling gc, you can define GC_AMIGA_MAKINGLIB to avoid having these allocation- functions wrapped. (see gc.h) Note that GC_realloc must not be called before any of @@ -249,7 +249,7 @@ will not behave well with Amiga specific code. Especially not inter- process comms via messages, and setting up public structures like Intuition objects or anything else in the system lists. For the time being the use of this library is limited to single threaded -ANSI/POSIX compliant or near-complient code. (ie. Stick to stdio +ANSI/POSIX compliant or near-compliant code. (ie. Stick to stdio for now). Given this limitation there is currently no mechanism for allocating "CHIP" or "PUBLIC" memory under the garbage collector. I'll add this after giving it considerable thought. The major @@ -260,7 +260,7 @@ If you allocate your own stack in client code, you will have to assign the pointer plus stack size to GC_stackbottom. The initial stack size of the target program can be compiled in by -setting the __stack symbol (see SAS documentaion). It can be over- +setting the __stack symbol (see SAS documentation). It can be over- ridden from the CLI by running the AmigaDOS "stack" program, or from the WorkBench by setting the stack size in the tool types window. @@ -282,7 +282,7 @@ The library as it stands is compatible with the GigaMem commercial virtual memory software, and probably similar PD software. The performance of "gctest" on an Amiga 2630 (68030 @ 25Mhz) -compares favourably with an HP9000 with similar architecture (a 325 +compares favorably with an HP9000 with similar architecture (a 325 with a 68030 I think). ----------------------------------------------------------------------- diff --git a/src/bdwgc/doc/README.cords b/src/bdwgc/doc/README.cords index f64dd2e8b..8904cd3a2 100644 --- a/src/bdwgc/doc/README.cords +++ b/src/bdwgc/doc/README.cords @@ -9,8 +9,6 @@ Permission to modify the code and to distribute modified code is granted, provided the above notices are retained, and a notice that the code was modified is included with the above copyright notice. -Please send bug reports to Hans-J. Boehm. - This is a string packages that uses a tree-based representation. See cord.h for a description of the functions provided. Ec.h describes "extensible cords", which are essentially output streams that write @@ -43,7 +41,7 @@ To build the editor, type "make cord/de" in the gc directory. This package assumes an ANSI C compiler such as gcc. It will not compile with an old-style K&R compiler. -Note that CORD_printf iand friends use C functions with variable numbers +Note that CORD_printf and friends use C functions with variable numbers of arguments in non-standard-conforming ways. This code is known to break on some platforms, notably PowerPC. It should be possible to build the remainder of the library (everything but cordprnt.c) on diff --git a/src/bdwgc/doc/README.darwin b/src/bdwgc/doc/README.darwin index 7de01e87a..11bb7e2e6 100644 --- a/src/bdwgc/doc/README.darwin +++ b/src/bdwgc/doc/README.darwin @@ -21,7 +21,7 @@ cannot call GC_init() before your libraries' static initializers have run and perhaps called GC_malloc(), create an initialization routine for each library to call GC_init(): -#include +#include "gc.h" extern "C" void my_library_init() { GC_init(); } Compile this code into a my_library_init.o, and link it into your diff --git a/src/bdwgc/doc/README.environment b/src/bdwgc/doc/README.environment index 7c7096c52..7d4d96c40 100644 --- a/src/bdwgc/doc/README.environment +++ b/src/bdwgc/doc/README.environment @@ -97,7 +97,7 @@ GC_PRINT_BACK_HEIGHT - Print max length of chain through unreachable objects (http://www.hpl.hp.com/techreports/2001/HPL-2001-251.html). GC_RETRY_SIGNALS, GC_NO_RETRY_SIGNALS - Try to compensate for lost - thread suspend signals in linux_threads.c. On by + thread suspend signals (Pthreads only). On by default for GC_OSF1_THREADS, off otherwise. Note that this does not work around a possible loss of thread restart signals. This seems to be necessary for diff --git a/src/bdwgc/doc/README.ews4800 b/src/bdwgc/doc/README.ews4800 index d4ea32aa1..da4cff398 100644 --- a/src/bdwgc/doc/README.ews4800 +++ b/src/bdwgc/doc/README.ews4800 @@ -2,27 +2,28 @@ GC on EWS4800 ------------- 1. About EWS4800 - EWS4800 is 32bit/64bit workstation. - Vender: NEC Corporation + EWS4800 is a 32/64-bit workstation. + + Vendor: NEC Corporation OS: UX/4800 R9.* - R13.* (SystemV R4.2) CPU: R4000, R4400, R10000 (MIPS) 2. Compiler - 32bit: + 32-bit: Use ANSI C compiler. CC = /usr/abiccs/bin/cc - 64bit: - Use 64bit ANSI C compiler. + 64-bit: + Use the 64-bit ANSI C compiler. CC = /usr/ccs64/bin/cc AR = /usr/ccs64/bin/ar 3. ELF file format - *** Caution: The following infomation is empirical. *** + *** Caution: The following information is empirical. *** - 32bit: + 32-bit: ELF file has an unique format. (See a.out(4) and end(3C).) &_start @@ -57,7 +58,7 @@ GC on EWS4800 &edata and DATASTART2. The global symbol &_DYNAMIC_LINKING is used for the detection. - 64bit: + 64-bit: ELF file has a simple format. (See end(3C).) _ftext @@ -76,5 +77,5 @@ Hironori SAKAMOTO When using the new "configure; make" build process, please run configure with the --disable-shared option. "Make check" does not -yet pass with dynamic libraries. Ther reasons for that are not yet +yet pass with dynamic libraries. The reasons for that are not yet understood. (HB, paraphrasing message from Hironori SAKAMOTO.) diff --git a/src/bdwgc/doc/README.hp b/src/bdwgc/doc/README.hp index d9fe7c8ba..bb583bbc0 100644 --- a/src/bdwgc/doc/README.hp +++ b/src/bdwgc/doc/README.hp @@ -8,7 +8,7 @@ The collector should compile with either plain cc or cc -Ae. Cc -Aa fails to define _HPUX_SOURCE and thus will not configure the collector correctly. -Incremental collection support was reccently added, and should now work. +Incremental collection support was added recently, and should now work. In spite of past claims, pthread support under HP/UX 11 should now work. Define GC_HPUX_THREADS for the build. Incremental collection still does not diff --git a/src/bdwgc/doc/README.linux b/src/bdwgc/doc/README.linux index f490365ca..bfa8b1853 100644 --- a/src/bdwgc/doc/README.linux +++ b/src/bdwgc/doc/README.linux @@ -8,8 +8,7 @@ See below for M68K specific notes. Incremental GC is generally supported. -Dynamic libraries are supported on an ELF system. A static executable -should be linked with the gcc option "-Wl,-defsym,_DYNAMIC=0". +Dynamic libraries are supported on an ELF system. The collector appears to work reliably with Linux threads, but beware of older versions of glibc and gdb. diff --git a/src/bdwgc/doc/README.macros b/src/bdwgc/doc/README.macros index 3cc302e7b..acf609c04 100644 --- a/src/bdwgc/doc/README.macros +++ b/src/bdwgc/doc/README.macros @@ -43,6 +43,10 @@ GC_NO_THREAD_REDIRECTS Tested by gc.h. Prevents redirection of thread GC_NO_THREAD_DECLS Tested by gc.h. MS Windows only. Do not declare Windows thread creation routines and do not include windows.h. +GC_DONT_INCLUDE_WINDOWS_H Tested by gc.h. MS Windows only. Do not include + windows.h from gc.h (but Windows-specific thread creation + routines are declared). + GC_UNDERSCORE_STDCALL Tested by gc.h. Explicitly prefix exported/imported WINAPI (__stdcall) symbols with '_' (underscore). Could be used with MinGW (for x86) compiler (in conjunction with @@ -107,10 +111,6 @@ SUNOS5SIGS Solaris-like signal handling. This is probably misnamed, PCR Set if the collector is being built as part of the Xerox Portable Common Runtime. -USE_COMPILER_TLS Assume the existence of __thread-style thread-local storage. - Set automatically for thread-local allocation with the HP/UX vendor - compiler. Usable with gcc on sufficiently up-to-date ELF platforms. - IMPORTANT: Any of the _THREADS options must normally also be defined in the client before including gc.h. This redefines thread primitives to invoke the GC_ versions instead. Alternatively, linker-based symbol @@ -257,9 +257,11 @@ FINALIZE_ON_DEMAND Causes finalizers to be run only in response In 5.0 this became runtime adjustable, and this only determines the initial value of GC_finalize_on_demand. -GC_NO_FINALIZATION Exclude finalization support (for smaller code size) +GC_NO_FINALIZATION Exclude finalization support (for smaller code size). -ATOMIC_UNCOLLECTABLE Includes code for GC_malloc_atomic_uncollectable. +GC_TOGGLE_REFS_NOT_NEEDED Exclude toggle-refs support. + +GC_ATOMIC_UNCOLLECTABLE Includes code for GC_malloc_atomic_uncollectable. This is useful if either the vendor malloc implementation is poor, or if REDIRECT_MALLOC is used. @@ -392,12 +394,18 @@ USE_COMPILER_TLS Causes thread local allocation to use default in HP/UX. It may help performance on recent Linux installations. (It failed for me on RedHat 8, but appears to work on RedHat 9.) +GC_ATTR_TLS_FAST Use specific attributes for GC_thread_key like + __attribute__((tls_model("local-exec"))). + PARALLEL_MARK Allows the marker to run in multiple threads. Recommended for multiprocessors. GC_ALWAYS_MULTITHREADED Force multi-threaded mode at GC initialization. (Turns GC_allow_register_threads into a no-op routine.) +GC_ENABLE_SUSPEND_THREAD (Linux only) Turn on thread suspend/resume API +support. + GC_WINMAIN_REDIRECT (Win32 only) Redirect (rename) an application WinMain to GC_WinMain; implement the "real" WinMain which starts a new thread to call GC_WinMain after initializing the GC. Useful for WinCE. @@ -557,7 +565,7 @@ GC_FULL_FREQ= Set alternate default number of partial collections NO_CANCEL_SAFE (Posix platforms with threads only) Don't bother trying to make the collector safe for thread cancellation; cancellation is not used. (Note that if cancellation is used anyway, threads may end up - getting cancelled in unexpected places.) Even without this option, + getting canceled in unexpected places.) Even without this option, PTHREAD_CANCEL_ASYNCHRONOUS is never safe with the collector. (We could argue about its safety without the collector.) diff --git a/src/bdwgc/doc/README.sgi b/src/bdwgc/doc/README.sgi index d9e989388..eceb3454d 100644 --- a/src/bdwgc/doc/README.sgi +++ b/src/bdwgc/doc/README.sgi @@ -26,8 +26,8 @@ will run on other pthreads platforms. But please tell me if it does.) include gc.h. Gc.h redefines some of the pthread primitives as macros which also provide the collector with information it requires. -4) pthread_cond_wait and pthread_cond_timed_wait should be prepared for -premature wakeups. (I believe the pthreads and realted standards require this +4) pthread_cond_wait and pthread_cond_timedwait should be prepared for +premature wakeups. (I believe the pthreads and related standards require this anyway. Irix pthreads often terminate a wait if a signal arrives. The garbage collector uses signals to stop threads.) diff --git a/src/bdwgc/doc/README.solaris2 b/src/bdwgc/doc/README.solaris2 index ba7bb2b2b..8a2669bf6 100644 --- a/src/bdwgc/doc/README.solaris2 +++ b/src/bdwgc/doc/README.solaris2 @@ -60,7 +60,7 @@ have it invoke the garbage-collector's allocators only after main has started. (Note that the latter requires a moderately expensive test in operator delete.) -I encountered "symbol : offet .... is non-aligned" errors. These +I encountered "symbol : offset .... is non-aligned" errors. These appear to be traceable to the use of the GNU assembler with the Sun linker. The former appears to generate a relocation not understood by the latter. The fix appears to be to use a consistent tool chain. (As a non-Solaris-expert diff --git a/src/bdwgc/doc/README.win32 b/src/bdwgc/doc/README.win32 index 0a32c2044..8bb2f374a 100644 --- a/src/bdwgc/doc/README.win32 +++ b/src/bdwgc/doc/README.win32 @@ -1,6 +1,6 @@ The collector has at various times been compiled under Windows 95 & later, NT, and XP, with the original Microsoft SDK, with Visual C++ 2.0, 4.0, and 6, with -the GNU win32 tools, with Borland 4.5, with Watcom C, and recently +the GNU win32 tools, with Borland C++ Builder, with Watcom C, and with the Digital Mars compiler. It is likely that some of these have been broken in the meantime. Patches are appreciated. @@ -41,10 +41,13 @@ in 6.1alpha4, since we now separate heap sections with an unused page.) Microsoft Tools --------------- -For Microsoft development tools, rename NT_MAKEFILE as -MAKEFILE. (Make sure that the CPU environment variable is defined -to be i386.) In order to use the gc_cpp.h C++ interface, all -client code should include gc_cpp.h. +For Microsoft development tools, type +"nmake -f NT_MAKEFILE cpu=i386 make_as_lib=1 nothreads=1 nodebug=1" +to build the release variant of the collector as a static library without +threads support. + +In order to use the gc_cpp.h C++ interface, all client code should include +gc_cpp.h. For historical reasons, the collector test program "gctest" is linked as a GUI application, @@ -93,10 +96,8 @@ I expect that -a1 introduces major performance penalties on a 486 or Pentium.) Note that this changes structure layouts. (As a last resort, gcconfig.h can be changed to allow 1 byte alignment. But this has significant negative performance implications.) -The Makefile is set up to assume Borland 4.5. If you have another -version, change the line near the top. By default, it does not -require the assembler. If you do have the assembler, I recommend -removing the -DUSE_GENERIC. +The Makefile is set up to assume Borland 5.5. If you have another +version, change the line near the top. Digital Mars compiler --------------------- @@ -180,10 +181,15 @@ to the collector DLL still exists, but requires that both We generally recommend avoiding this if possible, since it seems to be less than 100% reliable. -Use gc.mak (a.k.a NT_THREADS_MAKEFILE) instead of NT_MAKEFILE -to build a version that supports both kinds of thread tracking. -To build the garbage collector -test with VC++ from the command line, use +To build the collector as a dynamic library which handles threads similarly +to other platforms, type "nmake -f NT_MAKEFILE". If automatic tracking of +threads attached to the collector DLL (i.e. support of both kinds of thread +tracking) is needed then delete "-DTHREAD_LOCAL_ALLOC" from NT_MAKEFILE +manually before the build. + +The alternate way (not well tested) to build the dynamic library that supports +both kinds of thread tracking is to use gc.mak instead of NT_MAKEFILE. +To build the garbage collector test with VC++ from the command line, use nmake /F ".\gc.mak" CFG="gctest - Win32 Release" @@ -194,10 +200,9 @@ This version currently supports incremental collection only if it is enabled before any additional threads are created. Since 6.3alpha2, threads are also better supported in static library builds -with Microsoft tools (use NT_STATIC_THREADS_MAKEFILE) and with the GNU -tools. The collector must be built with GC_THREADS defined. -(NT_STATIC_THREADS_MAKEFILE does this implicitly. Under Cygwin, -./configure --enable-threads=posix should be used.) +with Microsoft tools (e.g., NT_MAKEFILE) and with the GNU +tools. The collector must be built with GC_THREADS defined (this is the +default in NT_MAKEFILE, ./configure and CMakeLists.txt). For the normal, non-dll-based thread tracking to work properly, threads should be created with GC_CreateThread or GC_beginthreadex, diff --git a/src/bdwgc/doc/README.win64 b/src/bdwgc/doc/README.win64 index 416f0348c..7714b5bc5 100644 --- a/src/bdwgc/doc/README.win64 +++ b/src/bdwgc/doc/README.win64 @@ -1,26 +1,27 @@ 64-bit Windows on AMD64/Intel EM64T is somewhat supported in the 7.0 and later release. A collector can be built with Microsoft Visual C++ 2005 or with mingw-w64 gcc. -More testing would clearly be helpful. -NT_X64_STATIC_THREADS_MAKEFILE has been used in -this environment. Copy this file to MAKEFILE, and then type "nmake" -in a Visual C++ command line window to build the static library -and the usual test programs. To verify that the collector is -at least somewhat functional, run gctest.exe. This should create -gctest.gc.log after a few seconds. +NT_MAKEFILE has been used in this environment. Type +"nmake -f NT_MAKEFILE cpu=AMD64 nodebug=1" in a Visual C++ command line +window to build the release variant of the dynamic library with threads +support and the usual test programs. +To verify that the collector is at least somewhat functional, run gctest.exe. +This should create gctest.gc.log after a few seconds. -This process is completely analogous to NT_STATIC_THREADS_MAKEFILE -for the 32-bit version. +Test_cpp.exe might not run correctly in case of dynamic GC linking. (It seems +that we're getting wrong instances of operator new/delete in some cases.) -A similar procedure using NT_X64_THREADS_MAKEFILE should be usable to -build the dynamic library. Test_cpp.exe did not seem to run correctly this -way. It seems that we're getting the wrong instances of operator new/delete -in some cases. The C tests seemed OK. +This process is completely analogous to NT_MAKEFILE usage +for the 32-bit library version. -Note that currently a few warnings are still generated by default, -and a number of others have been explicitly turned off in the makefile. +A similar procedure using NT_MAKEFILE is applicable to build the static +library - just pass "make_as_lib=1" as an extra argument to nmake. +If needed, it is also possible to build the library without threads +support - this could be done by passing "nothreads=1" argument to nmake. -VC++ note: to suppress warnings use -D_CRT_SECURE_NO_DEPRECATE. +Note that some warnings have been explicitly turned off in the makefile. + +VC++ note: to suppress warnings -D_CRT_SECURE_NO_DEPRECATE is used. gcc note: -fno-strict-aliasing should be used if optimizing. diff --git a/src/bdwgc/doc/debugging.html b/src/bdwgc/doc/debugging.html index 241875ce7..5c24862b9 100644 --- a/src/bdwgc/doc/debugging.html +++ b/src/bdwgc/doc/debugging.html @@ -160,7 +160,7 @@ before including gc.h and allocating with GC_MALLOC), so that objects will be identified by their allocation site,
  • Running the application long enough so that most of the heap is composed of "leaked" memory, and -
  • Then calling GC_generate_random_backtrace() from backptr.h +
  • Then calling GC_generate_random_backtrace() from gc_backptr.h a few times to determine why some randomly sampled objects in the heap are being retained. @@ -285,7 +285,7 @@ collector's layout description for s is such that the pointer field will be scanned. Call *GC_find_header(s) to look at the descriptor for the heap chunk. The hb_descr field specifies the layout of objects in that chunk. See gc_mark.h for the meaning of the descriptor. -(If it's low order 2 bits are zero, then it is just the length of the +(If its low order 2 bits are zero, then it is just the length of the object prefix to be scanned. This form is always used for objects allocated with GC_malloc or GC_malloc_atomic.)
  • If the failure is not deterministic, you may still be able to apply some diff --git a/src/bdwgc/doc/doc.am b/src/bdwgc/doc/doc.am index 382dbdd5d..af2e5222f 100644 --- a/src/bdwgc/doc/doc.am +++ b/src/bdwgc/doc/doc.am @@ -11,8 +11,8 @@ ## Process this file with automake to produce Makefile.in. # installed documentation -# -dist_pkgdata_DATA = \ +if ENABLE_DOCS +dist_doc_DATA = \ AUTHORS \ README.md \ doc/README.DGUX386 \ @@ -38,7 +38,6 @@ dist_pkgdata_DATA = \ doc/README.win64 \ doc/debugging.html \ doc/finalization.html \ - doc/gc.man \ doc/gcdescr.html \ doc/gcinterface.html \ doc/leak.html \ @@ -47,3 +46,6 @@ dist_pkgdata_DATA = \ doc/scale.html \ doc/simple_example.html \ doc/tree.html + +dist_man3_MANS = doc/gc.man +endif diff --git a/src/bdwgc/doc/gc.man b/src/bdwgc/doc/gc.man index 455373760..23af132ff 100644 --- a/src/bdwgc/doc/gc.man +++ b/src/bdwgc/doc/gc.man @@ -1,4 +1,4 @@ -.TH GC_MALLOC 1L "2 October 2003" +.TH BDWGC 3 "22 July 2018" .SH NAME GC_malloc, GC_malloc_atomic, GC_free, GC_realloc, GC_enable_incremental, GC_register_finalizer, GC_malloc_ignore_off_page, GC_malloc_atomic_ignore_off_page, GC_set_warn_proc \- Garbage collecting malloc replacement .SH SYNOPSIS @@ -11,7 +11,7 @@ void GC_free(void *ptr); void * GC_realloc(void *ptr, size_t size); .br .sp -cc ... gc.a +cc ... -lgc .LP .SH DESCRIPTION .I GC_malloc @@ -91,7 +91,7 @@ Other facilities not discussed here include limited facilities to support increm .SH "SEE ALSO" The README and gc.h files in the distribution. More detailed definitions of the functions exported by the collector are given there. (The above list is not complete.) .LP -The web site at http://www.hboehm.info/gc/ . +The web site at http://www.hboehm.info/gc/ (or https://github.com/ivmai/bdwgc/). .LP Boehm, H., and M. Weiser, "Garbage Collection in an Uncooperative Environment", "Software Practice & Experience", September 1988, pp. 807-820. @@ -100,4 +100,4 @@ The malloc(3) man page. .LP .SH AUTHOR Hans-J. Boehm (boehm@acm.org). -Some of the code was written by others, most notably Alan Demers. +Some of the code was written by others (see the AUTHORS file for the details), most notably by Alan Demers, and, recently, Ivan Maidanski. diff --git a/src/bdwgc/doc/gcdescr.html b/src/bdwgc/doc/gcdescr.html index 07afd7cc8..524a14f3a 100644 --- a/src/bdwgc/doc/gcdescr.html +++ b/src/bdwgc/doc/gcdescr.html @@ -92,8 +92,8 @@ One (STUBBORN) is immutable without special precautions. In spite of that, it is very likely that most C clients of the collector currently use at most two kinds: NORMAL and PTRFREE objects. -The gcj runtime also makes -heavy use of a kind (allocated with GC_gcj_malloc) that stores +The GCJ runtime +also makes heavy use of a kind (allocated with GC_gcj_malloc) that stores type information at a known offset in method tables.

    The collector uses a two level allocator. A large block is defined to @@ -133,7 +133,7 @@ large block free list.

    In order to avoid allocating blocks for too many distinct object sizes, the collector normally does not directly allocate objects of every possible -request size. Instead request are rounded up to one of a smaller number +request size. Instead, the request is rounded up to one of a smaller number of allocated sizes, for which free lists are maintained. The exact allocated sizes are computed on demand, but subject to the constraint that they increase roughly in geometric progression. Thus objects @@ -230,7 +230,7 @@ At the beginning of the mark phase, all root segments (as described above) are pushed on the stack by GC_push_roots. (Registers and eagerly processed stack sections are processed by pushing the referenced objects instead -of the stack section itself.) If ALL_INTERIOR_PTRS is not +of the stack section itself.) If ALL_INTERIOR_POINTERS is not defined, then stack roots require special treatment. In this case, the normal marking code ignores interior pointers, but GC_push_all_stack explicitly checks for interior pointers and pushes descriptors for target @@ -272,7 +272,7 @@ each call, so that it can also be used by the incremental collector. It is fairly carefully tuned, since it usually consumes a large majority of the garbage collection time.

    -The fact that it perform a only a small amount of work per call also +The fact that it performs only a small amount of work per call also allows it to be used as the core routine of the parallel marker. In that case it is normally invoked on thread-private mark stacks instead of the global mark stack. More details can be found in @@ -471,6 +471,9 @@ catching write faults. This is implemented for many Unix-like systems and for win32. It is not possible in a few environments.

  • +(GWW_VDB) By using the Win32 GetWriteWatch function to read dirty +bits. +
  • (PROC_VDB) By retrieving dirty bit information from /proc. (Currently only Sun's Solaris supports this. Though this is considerably cleaner, performance @@ -489,9 +492,9 @@ the vast majority of objects use GC_malloc_stubborn. The collector implements black-listing of pages, as described in - + Boehm, ``Space Efficient Conservative Collection'', PLDI '93, also available -here. +here.

    During the mark phase, the collector tracks ``near misses'', i.e. attempts to follow a ``pointer'' to just outside the garbage-collected heap, or @@ -534,23 +537,16 @@ common Pthreads implementations. In particular, it is very difficult for the collector to stop all other threads in the system and examine the register contents. This is currently accomplished with very different mechanisms for some Pthreads -implementations. The Solaris implementation temporarily disables much -of the user-level threads implementation by stopping kernel-level threads -("lwp"s). The Linux/HPUX/OSF1 and Irix implementations sends signals to +implementations. For Linux/HPUX/OSF1, Solaris and Irix it sends signals to individual Pthreads and has them wait in the signal handler.

    The Linux and Irix implementations use only documented Pthreads calls, but rely on extensions to their semantics. -The Linux implementation linux_threads.c relies on only very +The Linux implementation pthread_stop_world.c relies on only very mild extensions to the pthreads semantics, and already supports a large number of other Unix-like pthreads implementations. Our goal is to make this the only pthread support in the collector.

    -(The Irix implementation is separate only for historical reasons and should -clearly be merged. The current Solaris implementation probably performs -better in the uniprocessor case, but does not support thread operations in the -collector. Hence it cannot support the parallel marker.) -

    All implementations must intercept thread creation and a few other thread-specific calls to allow enumeration of threads and location of thread stacks. This is current @@ -617,12 +613,5 @@ For some more details see here, and the technical report entitled "Fast Multiprocessor Memory Allocation and Garbage Collection" -

    -


    -

    -Comments are appreciated. Please send mail to -bdwgc@lists.opendylan.org -(GC mailing list) or -boehm@acm.org diff --git a/src/bdwgc/doc/gcinterface.html b/src/bdwgc/doc/gcinterface.html index c315af88c..de014f0ce 100644 --- a/src/bdwgc/doc/gcinterface.html +++ b/src/bdwgc/doc/gcinterface.html @@ -129,7 +129,7 @@ allocation is used (see gc.h). On many platforms this interacts poorly with system calls that write to the garbage collected heap. -

    GC_warn_proc GC_set_warn_proc(GC_warn_proc p) +
    void GC_set_warn_proc(GC_warn_proc p)
    Replace the default procedure used by the collector to print warnings. The collector diff --git a/src/bdwgc/doc/leak.html b/src/bdwgc/doc/leak.html index d6e8a4c5a..43bc66d56 100644 --- a/src/bdwgc/doc/leak.html +++ b/src/bdwgc/doc/leak.html @@ -68,7 +68,7 @@ at least the file name and line number at the allocation point to be saved as part of the object. Leak reports will then also include this information.

    -Many collector features (e.g stubborn objects, finalization, +Many collector features (e.g. stubborn objects, finalization, and disappearing links) are less useful in this context, and are not fully supported. Their use will usually generate additional bogus leak reports, since the collector itself drops some associated objects. diff --git a/src/bdwgc/doc/overview.html b/src/bdwgc/doc/overview.html index 003ed7a60..16f561703 100644 --- a/src/bdwgc/doc/overview.html +++ b/src/bdwgc/doc/overview.html @@ -7,7 +7,7 @@ Tutorial Slides FAQ Example - Download + Download License @@ -27,11 +27,10 @@ before that at http://reality.sgi.com/boehm/gc.html and before that at - -ftp://ftp.parc.xerox.com/pub/gc/gc.html. ] +ftp://ftp.parc.xerox.com/pub/gc/gc.html. ]

    -The Boehm-Demers-Weiser -conservative garbage collector can +The Boehm-Demers-Weiser +conservative Garbage Collector (BDWGC) can be used as a garbage collecting replacement for C malloc or C++ new. It allows you to allocate memory basically as you normally would, @@ -52,23 +51,14 @@ Alternatively, the garbage collector may be used as a leak detector for C or C++ programs, though that is not its primary goal.

    -Typically several versions will be available. -Usually you should first try to use -gc_source/gc.tar.gz, -which is normally an older, more stable version. -

    -If that fails, try the latest explicitly numbered version -in -gc_source/. -Later versions may contain additional features, platform support, -or bug fixes, but are likely to be less well tested. -

    -A slightly older version of the garbage collector is now also -included as part of the -GNU compiler -distribution. The source -code for that version is available for browsing -here. +Typically several versions are offered for +downloading: +preview, stable, legacy. +Usually you should use the one marked as the latest stable release. +Preview versions may contain additional features, platform support, +but are likely to be less well tested. +The list of changes for each version is specified on the +releases page.

    The arguments for and against conservative garbage collection in C and C++ are briefly @@ -110,8 +100,7 @@ HP/UX 11 pthreads, Tru64 pthreads, and MacOS X threads are supported in recent versions.

    Separately distributed ports

    For MacOS 9/Classic use, Patrick Beard's latest port is available from - -http://homepage.mac.com/pcbeard/gc/. +http://homepage.mac.com/pcbeard/gc/. (Unfortunately, that's now quite dated. I'm not in a position to test under MacOS. Although I try to incorporate changes, it is impossible for @@ -124,7 +113,7 @@ Precompiled versions of the collector for NetBSD are available versions of the collector.

    Scalable multiprocessor versions

    Kenjiro Taura, Toshio Endo, and Akinori Yonezawa have made available -a parallel collector +a parallel collector based on this one. Their collector takes advantage of multiple processors during a collection. Starting with collector version 6.0alpha1 we also do this, though with more modest processor scalability goals. @@ -265,7 +254,7 @@ Proceedings of the ACM SIGPLAN '96 Conference on Programming Language Design and Implementation.

    Boehm, H., and D. Chase, "A Proposal for Garbage-Collector-Safe C Compilation", -Journal of C Language Translation 4, 2 (Decemeber 1992), pp. 126-141. +Journal of C Language Translation 4, 2 (December 1992), pp. 126-141.

    Other related information:

    @@ -275,7 +264,9 @@ using programs written for malloc/free.

    Joel Bartlett's mostly copying conservative garbage collector for C++.

    -John Ellis and David Detlef's Safe Efficient Garbage Collection for C++ proposal. +John Ellis and David Detlef's +Safe Efficient Garbage Collection for C++ +proposal.

    Henry Baker's paper collection.

    @@ -283,7 +274,8 @@ Slides for Hans Boehm's Allocation

    Current users:

    Known current users of some variant of this collector include:

    -The runtime system for GCJ, +The runtime system for +GCJ, the static GNU java compiler.

    W3m, a text-based web browser. @@ -335,11 +327,11 @@ research in algebraic geometry and commutative algebra. The Vesta configuration management system.

    -Visual Prolog 6. +Visual Prolog 6.

    Asymptote LaTeX-compatible vector graphics language. -

    More collector information at this site

    +

    More information on the BDWGC primary site

    A simple illustration of how to build and use the collector.

    @@ -362,8 +354,12 @@ garbage collector.

    Scalability of the collector to multiprocessors.

    -Directory containing garbage collector source. -

    More background information at this site

    +Directory containing +the distribution files of all garbage collector releases. +It duplicates +Download page on +GitHub. +

    More background information

    An attempt to establish a bound on space usage of conservative garbage collectors.

    @@ -398,37 +394,38 @@ Technical Report version). Slides for OOPSLA 98 garbage collection talk.

    Related papers. -

    Contacts and Mailing List

    -We have recently set up two mailing list for collector announcements -and discussions: -
      -
    • bdwgc-announce@lists.opendylan.org -is used for announcements of new versions. Postings are restricted. -We expect this to always remain a very low volume list. -
    • bdwgc@lists.opendylan.org -is used for discussions, bug reports, and the like. Subscribers may post. -On-topic posts by nonsubscribers will usually also be accepted, but -it may take some time to review them. -
    -To subscribe to these lists, please visit -lists.opendylan.org/mailman/listinfo/bdwgc-announce -and -lists.opendylan.org/mailman/listinfo/bdwgc, -respectively. +

    Contacts and new release announcements

    +GitHub and Stack Overflow are the major two places for communication.

    -The archives for these lists appear -here and -here, -respectively. +Technical questions (how to, how does it work, etc.) should be posted to +Stack Overflow +with "boehm-gc" tag. +

    +To contribute, please rebase your code to the latest +master and submit +a pull request to GitHub. +

    +To report a bug, or propose (request) a new feature, create +a GitHub issue. +Please make sure it has not been reported yet by someone else. +

    +To receive notifications on every release, please subscribe to +Releases RSS feed. +Notifications on all issues and pull requests are available by +watching the project. +

    +Mailing lists (bdwgc-announce@lists.opendylan.org, bdwgc@lists.opendylan.org, +and the former gc-announce@linux.hpl.hp.com and gc@linux.hpl.hp.com) are not +used at this moment. Their content is available in +bdwgc-announce +and +bdwgc +archive files, respectively. The gc list archive may also be read at -gmane.org. +Narkive.

    Some prior discussion of the collector has taken place on the gcc java mailing list, whose archives appear here, and also on gclist@iecc.com. -

    -Comments and bug reports may also be sent to -(boehm@acm.org), but the gc -mailing list is usually preferred.

    diff --git a/src/bdwgc/doc/porting.html b/src/bdwgc/doc/porting.html index f22f654e9..86349eaed 100644 --- a/src/bdwgc/doc/porting.html +++ b/src/bdwgc/doc/porting.html @@ -131,7 +131,7 @@ should be defined to the limits of the second main data segment.
    Should be defined if the stack (or thread stacks) grow towards higher addresses. (This appears to be true only on PA-RISC. If your architecture -has more than one stack per thread, and is not already supported, you will +has more than one stack per thread, and is not supported yet, you will need to do more work. Grep for "IA64" in the source for an example.)
    STACKBOTTOM
    @@ -166,7 +166,7 @@ The cold end of the stack is determined by taking an address inside GC_init's frame, incrementing it repeatedly in small steps (decrement if STACK_GROWS_UP), and reading the value at each location. We remember the value when the first -Segmentation violation or Bus error is signalled, round that +Segmentation violation or Bus error is signaled, round that to the nearest plausible page boundary, and use that as the stack base.
    DYNAMIC_LOADING @@ -181,7 +181,7 @@ allows incremental/generational garbage collection. MPROTECT_VDB identifies modified pages by write protecting the heap and catching faults. PROC_VDB uses the /proc primitives to read dirty bits. -
    PREFETCH, PREFETCH_FOR_WRITE +
    PREFETCH, GC_PREFETCH_FOR_WRITE
    The collector uses PREFETCH(x) to preload the cache with *x. @@ -196,12 +196,6 @@ word stores of 0 are used instead.
    HEAP_START may be defined as the initial address hint for mmap-based allocation. -
    ALIGN_DOUBLE -
    -Should be defined if the architecture requires double-word alignment -of GC_malloced memory, e.g. 8-byte alignment with a -32-bit ABI. Most modern machines are likely to require this. -This is no longer needed for GC7 and later.

    Additional requirements for a basic port

    In some cases, you may have to add additional platform-specific code @@ -214,7 +208,7 @@ tweaking of conditional compilation tests.

    For GC7, if your platform supports getcontext(), then defining the macro UNIX_LIKE for your OS in gcconfig.h -(if it isn't defined there already) is likely to solve the problem. +(if it isn't defined there yet) is likely to solve the problem. otherwise, if you are using gcc, _builtin_unwind_init() will be used, and should work fine. If that is not applicable either, the implementation will try to use setjmp(). This will work if your diff --git a/src/bdwgc/doc/scale.html b/src/bdwgc/doc/scale.html index 9faff6cb0..ae40ccf11 100644 --- a/src/bdwgc/doc/scale.html +++ b/src/bdwgc/doc/scale.html @@ -64,23 +64,12 @@ locking. The thread-local free lists are refilled using GC_malloc_many.

    An important side effect of this flag is to replace the default -spin-then-sleep lock to be replace by a spin-then-queue based implementation. +spin-then-sleep lock to be replaced by a spin-then-queue based implementation. This reduces performance for the standard allocation functions, though it usually improves performance when thread-local allocation is used heavily, and thus the number of short-duration lock acquisitions is greatly reduced. -

    -The easiest way to switch an application to thread-local allocation -in a pre-version-7.0 collector was to -

      -
    1. Define the macro GC_REDIRECT_TO_LOCAL, -and then include the gc.h -header in each client source file. -
    2. Invoke GC_thr_init() before any allocation. -
    3. Allocate using GC_MALLOC, GC_MALLOC_ATOMIC, -and/or GC_GCJ_MALLOC. -

    The Parallel Marking Algorithm

    We use an algorithm similar to that developed by @@ -145,7 +134,7 @@ Running with a thread-unsafe collector, the benchmark ran in 9 seconds. With the simple thread-safe collector, built with -DLINUX_THREADS, the execution time increased to 10.3 seconds, or 23.5 elapsed seconds with two clients. -(The times for the malloc/ifree version +(The times for the malloc/free version with glibc malloc are 10.51 (standard library, pthreads not linked), 20.90 (one thread, pthreads linked), @@ -167,7 +156,7 @@ avoided in time-critical code. directly for allocation locking would have been worse still, at least for older versions of linuxthreads. With THREAD_LOCAL_ALLOC, we first repeatedly try to acquire the -lock with pthread_mutex_try_lock(), busy_waiting between attempts. +lock with pthread_mutex_try_lock(), busy-waiting between attempts. After a fixed number of attempts, we use pthread_mutex_lock().)

    These measurements do not use incremental collection, nor was prefetching diff --git a/src/bdwgc/doc/simple_example.html b/src/bdwgc/doc/simple_example.html index 98ae4244b..8d605f3aa 100644 --- a/src/bdwgc/doc/simple_example.html +++ b/src/bdwgc/doc/simple_example.html @@ -12,7 +12,7 @@ a single-threaded application. The green text contains information about other platforms or scenarios. It can be skipped, especially on first reading.

    Building the collector

    -If you haven't already so, unpack the collector and enter +If you have not so yet, unpack the collector and enter the newly created directory with
     tar xvfz gc<version>.tar.gz
    @@ -55,7 +55,7 @@ strong preference of the would-be maintainer of those project files.)
     If you need thread support, configure the collector with
     
     
    ---enable-threads=posix --enable-thread-local-alloc --enable-parallel-mark
    +--enable-threads=posix --enable-parallel-mark
     
    instead of @@ -143,22 +143,6 @@ should first define the macro GC_THREADS, and then include "gc.h". On some platforms this will redefine some threads primitives, e.g. to let the collector keep track of thread creation. -
  • - -To take advantage of fast thread-local allocation in versions before 7.0, -use the following instead -of including gc.h: - -
    -#define GC_REDIRECT_TO_LOCAL
    -#include "gc_local_alloc.h"
    -
    - -This will cause GC_MALLOC and GC_MALLOC_ATOMIC to keep per-thread allocation -caches, and greatly reduce the number of lock acquisitions during allocation. -For versions after 7.0, this happens implicitly if the collector is built -with thread-local allocation enabled. -

    C++

    diff --git a/src/bdwgc/doc/tree.html b/src/bdwgc/doc/tree.html index f1c6e269f..2bfd5834d 100644 --- a/src/bdwgc/doc/tree.html +++ b/src/bdwgc/doc/tree.html @@ -185,7 +185,7 @@ freed; free lists are used (e.g. alloc_hdr). HBLK's below are collected. HBLKSIZE | |--------------- | (words) (bytes) | | v MAX_OFFSET | + - - - - - - - - - - -+ --- (bytes) - | | | !All_INTERIOR_PTRS ^ | + | | | !ALL_INTERIOR_POINTERS ^ | | | | sets j only for hb_sz | | | Object N | valid object offsets. | | v | | All objects WORDSZ v v diff --git a/src/bdwgc/dyn_load.c b/src/bdwgc/dyn_load.c index 3b9071856..ba09ab315 100644 --- a/src/bdwgc/dyn_load.c +++ b/src/bdwgc/dyn_load.c @@ -52,18 +52,18 @@ STATIC GC_has_static_roots_func GC_has_static_roots = 0; #if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \ || defined(CYGWIN32)) && !defined(PCR) -#if !defined(SOLARISDL) && !defined(IRIX5) && \ - !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) && \ - !(defined(ALPHA) && defined(OSF1)) && \ - !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \ - !defined(AIX) && !defined(SCO_ELF) && !defined(DGUX) && \ - !(defined(FREEBSD) && defined(__ELF__)) && \ - !(defined(OPENBSD) && (defined(__ELF__) || defined(M68K))) && \ - !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \ - !defined(DARWIN) && !defined(CYGWIN32) - --> We only know how to find data segments of dynamic libraries for the - --> above. Additional SVR4 variants might not be too - --> hard to add. +#if !defined(DARWIN) && !defined(SCO_ELF) && !defined(SOLARISDL) \ + && !defined(AIX) && !defined(DGUX) && !defined(IRIX5) && !defined(HPUX) \ + && !defined(CYGWIN32) && !defined(MSWIN32) && !defined(MSWINCE) \ + && !(defined(ALPHA) && defined(OSF1)) \ + && !(defined(FREEBSD) && defined(__ELF__)) \ + && !((defined(LINUX) || defined(NACL)) && defined(__ELF__)) \ + && !(defined(NETBSD) && defined(__ELF__)) \ + && !defined(HAIKU) && !defined(HURD) \ + && !(defined(OPENBSD) && (defined(__ELF__) || defined(M68K))) \ + && !defined(CPPCHECK) +# error We only know how to find data segments of dynamic libraries for above. +# error Additional SVR4 variants might not be too hard to add. #endif #include @@ -82,14 +82,15 @@ STATIC GC_has_static_roots_func GC_has_static_roots = 0; #if defined(OPENBSD) # include -# if OpenBSD >= 200519 +# if (OpenBSD >= 200519) && !defined(HAVE_DL_ITERATE_PHDR) # define HAVE_DL_ITERATE_PHDR # endif #endif /* OPENBSD */ #if defined(SCO_ELF) || defined(DGUX) || defined(HURD) \ || (defined(__ELF__) && (defined(LINUX) || defined(FREEBSD) \ - || defined(NETBSD) || defined(OPENBSD))) + || defined(NACL) || defined(NETBSD) \ + || defined(OPENBSD))) # include # if !defined(OPENBSD) && !defined(PLATFORM_ANDROID) /* OpenBSD does not have elf.h file; link.h below is sufficient. */ @@ -109,9 +110,9 @@ STATIC GC_has_static_roots_func GC_has_static_roots = 0; # undef EM_ALPHA # endif # include -# if !defined(GC_DONT_DEFINE_LINK_MAP) - /* link_map and r_debug should be defined explicitly, */ - /* as only bionic/linker/linker.h defines them but the header */ +# if !defined(GC_DONT_DEFINE_LINK_MAP) && !(__ANDROID_API__ >= 21) + /* link_map and r_debug are defined in link.h of NDK r10+. */ + /* bionic/linker/linker.h defines them too but the header */ /* itself is a C++ one starting from Android 4.3. */ struct link_map { uintptr_t l_addr; @@ -179,23 +180,26 @@ GC_FirstDLOpenedLinkMap(void) /* at program startup. */ if( dynStructureAddr == 0 ) { void* startupSyms = dlopen(0, RTLD_LAZY); - dynStructureAddr = (ElfW(Dyn)*)dlsym(startupSyms, "_DYNAMIC"); + dynStructureAddr = (ElfW(Dyn)*)(word)dlsym(startupSyms, "_DYNAMIC"); } # else dynStructureAddr = &_DYNAMIC; # endif - if (dynStructureAddr == 0) { + if (0 == COVERT_DATAFLOW(dynStructureAddr)) { /* _DYNAMIC symbol not resolved. */ return(0); } - if( cachedResult == 0 ) { + if (cachedResult == 0) { int tag; for( dp = ((ElfW(Dyn) *)(&_DYNAMIC)); (tag = dp->d_tag) != 0; dp++ ) { - if( tag == DT_DEBUG ) { - struct link_map *lm - = ((struct r_debug *)(dp->d_un.d_ptr))->r_map; - if( lm != 0 ) cachedResult = lm->l_next; /* might be NULL */ + if (tag == DT_DEBUG) { + struct r_debug *rd = (struct r_debug *)dp->d_un.d_ptr; + if (rd != NULL) { + struct link_map *lm = rd->r_map; + if (lm != NULL) + cachedResult = lm->l_next; /* might be NULL */ + } break; } } @@ -213,8 +217,9 @@ GC_FirstDLOpenedLinkMap(void) # if defined(SOLARISDL) /* Add dynamic library data sections to the root set. */ -# if !defined(PCR) && !defined(GC_SOLARIS_THREADS) && defined(THREADS) - --> fix mutual exclusion with dlopen +# if !defined(PCR) && !defined(GC_SOLARIS_THREADS) && defined(THREADS) \ + && !defined(CPPCHECK) +# error Fix mutual exclusion with dlopen # endif # ifndef USE_PROC_FOR_LIBRARIES @@ -257,7 +262,8 @@ GC_INNER void GC_register_dynamic_libraries(void) #if defined(SCO_ELF) || defined(DGUX) || defined(HURD) \ || (defined(__ELF__) && (defined(LINUX) || defined(FREEBSD) \ - || defined(NETBSD) || defined(OPENBSD))) + || defined(NACL) || defined(NETBSD) \ + || defined(OPENBSD))) #ifdef USE_PROC_FOR_LIBRARIES @@ -279,9 +285,10 @@ static void sort_heap_sects(struct HeapSect *base, size_t number_of_elements) { signed_word n = (signed_word)number_of_elements; signed_word nsorted = 1; - signed_word i; while (nsorted < n) { + signed_word i; + while (nsorted < n && (word)base[nsorted-1].hs_start < (word)base[nsorted].hs_start) ++nsorted; @@ -299,7 +306,7 @@ static void sort_heap_sects(struct HeapSect *base, size_t number_of_elements) } } -STATIC word GC_register_map_entries(char *maps) +STATIC void GC_register_map_entries(char *maps) { char *prot; char *buf_ptr = maps; @@ -307,19 +314,6 @@ STATIC word GC_register_map_entries(char *maps) unsigned int maj_dev; ptr_t least_ha, greatest_ha; unsigned i; - ptr_t datastart; - -# ifdef DATASTART_IS_FUNC - static ptr_t datastart_cached = (ptr_t)(word)-1; - - /* Evaluate DATASTART only once. */ - if (datastart_cached == (ptr_t)(word)-1) { - datastart_cached = (ptr_t)(DATASTART); - } - datastart = datastart_cached; -# else - datastart = (ptr_t)(DATASTART); -# endif GC_ASSERT(I_HOLD_LOCK()); sort_heap_sects(GC_our_memory, GC_n_memory); @@ -330,7 +324,8 @@ STATIC word GC_register_map_entries(char *maps) for (;;) { buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, &prot, &maj_dev, 0); - if (buf_ptr == NULL) return 1; + if (NULL == buf_ptr) + break; if (prot[1] == 'w') { /* This is a writable mapping. Add it to */ /* the root set unless it is already otherwise */ @@ -395,15 +390,21 @@ STATIC word GC_register_map_entries(char *maps) } if ((word)start < (word)end) GC_add_roots_inner((char *)start, (char *)end, TRUE); + } else if (prot[0] == '-' && prot[1] == '-' && prot[2] == '-') { + /* Even roots added statically might disappear partially */ + /* (e.g. the roots added by INCLUDE_LINUX_THREAD_DESCR). */ + GC_remove_roots_subregion(start, end); } } - return 1; } GC_INNER void GC_register_dynamic_libraries(void) { - if (!GC_register_map_entries(GC_get_maps())) + char *maps = GC_get_maps(); + + if (NULL == maps) ABORT("Failed to read /proc for library registration"); + GC_register_map_entries(maps); } /* We now take care of the main data segment ourselves: */ @@ -423,23 +424,28 @@ GC_INNER GC_bool GC_register_main_static_data(void) #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)) \ || defined(PLATFORM_ANDROID) /* Are others OK here, too? */ -/* We have the header files for a glibc that includes dl_iterate_phdr. */ -/* It may still not be available in the library on the target system. */ -/* Thus we also treat it as a weak symbol. */ -# define HAVE_DL_ITERATE_PHDR +# ifndef HAVE_DL_ITERATE_PHDR +# define HAVE_DL_ITERATE_PHDR +# endif # ifdef PLATFORM_ANDROID /* Android headers might have no such definition for some targets. */ int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *data); # endif -# pragma weak dl_iterate_phdr -#endif +#endif /* __GLIBC__ >= 2 || PLATFORM_ANDROID */ -#if (defined(FREEBSD) && __FreeBSD__ >= 7) +#if (defined(FREEBSD) && __FreeBSD__ >= 7) || defined(__DragonFly__) /* On the FreeBSD system, any target system at major version 7 shall */ - /* have dl_iterate_phdr; therefore, we need not make it weak as above. */ -# define HAVE_DL_ITERATE_PHDR + /* have dl_iterate_phdr; therefore, we need not make it weak as below. */ +# ifndef HAVE_DL_ITERATE_PHDR +# define HAVE_DL_ITERATE_PHDR +# endif # define DL_ITERATE_PHDR_STRONG +#elif defined(HAVE_DL_ITERATE_PHDR) + /* We have the header files for a glibc that includes dl_iterate_phdr.*/ + /* It may still not be available in the library on the target system. */ + /* Thus we also treat it as a weak symbol. */ +# pragma weak dl_iterate_phdr #endif #if defined(HAVE_DL_ITERATE_PHDR) @@ -464,6 +470,7 @@ GC_INNER GC_bool GC_register_main_static_data(void) } load_segs[MAX_LOAD_SEGS]; static int n_load_segs; + static GC_bool load_segs_overflow; # endif /* PT_GNU_RELRO */ STATIC int GC_register_dynlib_callback(struct dl_phdr_info * info, @@ -479,75 +486,80 @@ STATIC int GC_register_dynlib_callback(struct dl_phdr_info * info, return -1; p = info->dlpi_phdr; - for( i = 0; i < (int)info->dlpi_phnum; i++, p++ ) { - switch( p->p_type ) { + for (i = 0; i < (int)info->dlpi_phnum; i++, p++) { + if (p->p_type == PT_LOAD) { + GC_has_static_roots_func callback = GC_has_static_roots; + if ((p->p_flags & PF_W) == 0) continue; + + start = (ptr_t)p->p_vaddr + info->dlpi_addr; + end = start + p->p_memsz; + if (callback != 0 && !callback(info->dlpi_name, start, p->p_memsz)) + continue; # ifdef PT_GNU_RELRO - case PT_GNU_RELRO: - /* This entry is known to be constant and will eventually be remapped - read-only. However, the address range covered by this entry is - typically a subset of a previously encountered "LOAD" segment, so - we need to exclude it. */ - { - int j; - - start = ((ptr_t)(p->p_vaddr)) + info->dlpi_addr; - end = start + p->p_memsz; - for (j = n_load_segs; --j >= 0; ) { - if ((word)start >= (word)load_segs[j].start - && (word)start < (word)load_segs[j].end) { - if (load_segs[j].start2 != 0) { - WARN("More than one GNU_RELRO segment per load seg\n",0); - } else { - GC_ASSERT((word)end <= (word)load_segs[j].end); - /* Remove from the existing load segment */ - load_segs[j].end2 = load_segs[j].end; - load_segs[j].end = start; - load_segs[j].start2 = end; - } - break; - } - if (j == 0) WARN("Failed to find PT_GNU_RELRO segment" - " inside PT_LOAD region", 0); - } +# if CPP_WORDSZ == 64 + /* TODO: GC_push_all eventually does the correct */ + /* rounding to the next multiple of ALIGNMENT, so, most */ + /* probably, we should remove the corresponding assertion */ + /* check in GC_add_roots_inner along with this code line. */ + /* start pointer value may require aligning. */ + start = (ptr_t)((word)start & ~(word)(sizeof(word) - 1)); +# endif + if (n_load_segs >= MAX_LOAD_SEGS) { + if (!load_segs_overflow) { + WARN("Too many PT_LOAD segments;" + " registering as roots directly...\n", 0); + load_segs_overflow = TRUE; + } + GC_add_roots_inner(start, end, TRUE); + } else { + load_segs[n_load_segs].start = start; + load_segs[n_load_segs].end = end; + load_segs[n_load_segs].start2 = 0; + load_segs[n_load_segs].end2 = 0; + ++n_load_segs; } - - break; -# endif - - case PT_LOAD: - { - GC_has_static_roots_func callback = GC_has_static_roots; - if( !(p->p_flags & PF_W) ) break; - start = ((char *)(p->p_vaddr)) + info->dlpi_addr; - end = start + p->p_memsz; - - if (callback != 0 && !callback(info->dlpi_name, start, p->p_memsz)) - break; -# ifdef PT_GNU_RELRO - if (n_load_segs >= MAX_LOAD_SEGS) ABORT("Too many PT_LOAD segs"); -# if CPP_WORDSZ == 64 - /* FIXME: GC_push_all eventually does the correct */ - /* rounding to the next multiple of ALIGNMENT, so, most */ - /* probably, we should remove the corresponding assertion */ - /* check in GC_add_roots_inner along with this code line. */ - /* start pointer value may require aligning */ - start = (ptr_t)((word)start & ~(sizeof(word) - 1)); -# endif - load_segs[n_load_segs].start = start; - load_segs[n_load_segs].end = end; - load_segs[n_load_segs].start2 = 0; - load_segs[n_load_segs].end2 = 0; - ++n_load_segs; -# else - GC_add_roots_inner(start, end, TRUE); -# endif /* PT_GNU_RELRO */ - } - break; - default: - break; +# else + GC_add_roots_inner(start, end, TRUE); +# endif /* !PT_GNU_RELRO */ } } +# ifdef PT_GNU_RELRO + p = info->dlpi_phdr; + for (i = 0; i < (int)info->dlpi_phnum; i++, p++) { + if (p->p_type == PT_GNU_RELRO) { + /* This entry is known to be constant and will eventually be */ + /* remapped as read-only. However, the address range covered */ + /* by this entry is typically a subset of a previously */ + /* encountered "LOAD" segment, so we need to exclude it. */ + int j; + + start = (ptr_t)p->p_vaddr + info->dlpi_addr; + end = start + p->p_memsz; + for (j = n_load_segs; --j >= 0; ) { + if ((word)start >= (word)load_segs[j].start + && (word)start < (word)load_segs[j].end) { + if (load_segs[j].start2 != 0) { + WARN("More than one GNU_RELRO segment per load one\n",0); + } else { + GC_ASSERT((word)end <= (word)load_segs[j].end); + /* Remove from the existing load segment */ + load_segs[j].end2 = load_segs[j].end; + load_segs[j].end = start; + load_segs[j].start2 = end; + } + break; + } + if (0 == j && 0 == GC_has_static_roots) + WARN("Failed to find PT_GNU_RELRO segment" + " inside PT_LOAD region\n", 0); + /* No warning reported in case of the callback is present */ + /* because most likely the segment has been excluded. */ + } + } + } +# endif + *(int *)ptr = 1; /* Signal that we were called */ return 0; } @@ -560,7 +572,7 @@ GC_INNER GC_bool GC_register_main_static_data(void) /* zero (otherwise a compiler might issue a warning). */ return FALSE; # else - return (dl_iterate_phdr == 0); /* implicit conversion to function ptr */ + return 0 == COVERT_DATAFLOW(dl_iterate_phdr); # endif } @@ -575,6 +587,7 @@ STATIC GC_bool GC_register_dynamic_libraries_dl_iterate_phdr(void) { static GC_bool excluded_segs = FALSE; n_load_segs = 0; + load_segs_overflow = FALSE; if (!EXPECT(excluded_segs, TRUE)) { GC_exclude_static_roots_inner((ptr_t)load_segs, (ptr_t)load_segs + sizeof(load_segs)); @@ -606,7 +619,7 @@ STATIC GC_bool GC_register_dynamic_libraries_dl_iterate_phdr(void) /* Evaluate DATASTART only once. */ if (datastart_cached == (ptr_t)(word)-1) { - datastart_cached = (ptr_t)(DATASTART); + datastart_cached = DATASTART; } datastart = (char *)datastart_cached; # else @@ -617,19 +630,29 @@ STATIC GC_bool GC_register_dynamic_libraries_dl_iterate_phdr(void) static ptr_t dataend_cached = 0; /* Evaluate DATAEND only once. */ if (dataend_cached == 0) { - dataend_cached = (ptr_t)(DATAEND); + dataend_cached = DATAEND; } dataend = (char *)dataend_cached; } # else dataend = DATAEND; # endif + if (NULL == *(char * volatile *)&datastart + || (word)datastart > (word)dataend) + ABORT_ARG2("Wrong DATASTART/END pair", + ": %p .. %p", (void *)datastart, (void *)dataend); /* dl_iterate_phdr may forget the static data segment in */ /* statically linked executables. */ GC_add_roots_inner(datastart, dataend, TRUE); -# if defined(DATASTART2) - GC_add_roots_inner(DATASTART2, (char *)(DATAEND2), TRUE); +# ifdef GC_HAVE_DATAREGION2 + if ((word)DATASTART2 - 1U >= (word)DATAEND2) { + /* Subtract one to check also for NULL */ + /* without a compiler warning. */ + ABORT_ARG2("Wrong DATASTART/END2 pair", + ": %p .. %p", (void *)DATASTART2, (void *)DATAEND2); + } + GC_add_roots_inner(DATASTART2, DATAEND2, TRUE); # endif } return TRUE; @@ -677,17 +700,21 @@ extern ElfW(Dyn) _DYNAMIC[]; STATIC struct link_map * GC_FirstDLOpenedLinkMap(void) { - ElfW(Dyn) *dp; static struct link_map *cachedResult = 0; - if (0 == (ptr_t)_DYNAMIC) { + if (0 == COVERT_DATAFLOW(_DYNAMIC)) { /* _DYNAMIC symbol not resolved. */ return(0); } if( cachedResult == 0 ) { # if defined(NETBSD) && defined(RTLD_DI_LINKMAP) +# if defined(CPPCHECK) +# define GC_RTLD_DI_LINKMAP 2 +# else +# define GC_RTLD_DI_LINKMAP RTLD_DI_LINKMAP +# endif struct link_map *lm = NULL; - if (!dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lm) && lm != NULL) { + if (!dlinfo(RTLD_SELF, GC_RTLD_DI_LINKMAP, &lm) && lm != NULL) { /* Now lm points link_map object of libgc. Since it */ /* might not be the first dynamically linked object, */ /* try to find it (object next to the main object). */ @@ -697,12 +724,18 @@ GC_FirstDLOpenedLinkMap(void) cachedResult = lm->l_next; } # else + ElfW(Dyn) *dp; int tag; + for( dp = _DYNAMIC; (tag = dp->d_tag) != 0; dp++ ) { - if( tag == DT_DEBUG ) { - struct link_map *lm - = ((struct r_debug *)(dp->d_un.d_ptr))->r_map; - if( lm != 0 ) cachedResult = lm->l_next; /* might be NULL */ + if (tag == DT_DEBUG) { + struct r_debug *rd = (struct r_debug *)dp->d_un.d_ptr; + /* d_ptr could be null if libs are linked statically. */ + if (rd != NULL) { + struct link_map *lm = rd->r_map; + if (lm != NULL) + cachedResult = lm->l_next; /* might be NULL */ + } break; } } @@ -776,7 +809,7 @@ GC_INNER void GC_register_dynamic_libraries(void) char buf[30]; static prmap_t * addr_map = 0; static int current_sz = 0; /* Number of records currently in addr_map */ - static int needed_sz; /* Required size of addr_map */ + int needed_sz = 0; /* Required size of addr_map */ int i; long flags; ptr_t start; @@ -803,17 +836,19 @@ GC_INNER void GC_register_dynamic_libraries(void) ": fd = %d, errno = %d", fd, errno); } if (needed_sz >= current_sz) { + GC_scratch_recycle_no_gww(addr_map, + (size_t)current_sz * sizeof(prmap_t)); current_sz = needed_sz * 2 + 1; /* Expansion, plus room for 0 record */ addr_map = (prmap_t *)GC_scratch_alloc( - (word)current_sz * sizeof(prmap_t)); + (size_t)current_sz * sizeof(prmap_t)); if (addr_map == NULL) ABORT("Insufficient memory for address map"); } if (ioctl(fd, PIOCMAP, addr_map) < 0) { ABORT_ARG3("/proc PIOCMAP ioctl failed", ": errcode= %d, needed_sz= %d, addr_map= %p", - errno, needed_sz, addr_map); + errno, needed_sz, (void *)addr_map); }; if (GC_n_heap_sects > 0) { heap_end = GC_heap_sects[GC_n_heap_sects-1].hs_start @@ -913,7 +948,7 @@ GC_INNER void GC_register_dynamic_libraries(void) # else char * stack_top = (char *)((word)GC_approx_sp() & - ~(GC_sysinfo.dwAllocationGranularity - 1)); + ~(word)(GC_sysinfo.dwAllocationGranularity - 1)); if (base == limit) return; if ((word)limit > (word)stack_top @@ -964,7 +999,6 @@ GC_INNER void GC_register_dynamic_libraries(void) GC_INNER void GC_register_dynamic_libraries(void) { MEMORY_BASIC_INFORMATION buf; - size_t result; DWORD protect; LPVOID p; char * base; @@ -975,7 +1009,8 @@ GC_INNER void GC_register_dynamic_libraries(void) # endif base = limit = p = GC_sysinfo.lpMinimumApplicationAddress; while ((word)p < (word)GC_sysinfo.lpMaximumApplicationAddress) { - result = VirtualQuery(p, &buf, sizeof(buf)); + size_t result = VirtualQuery(p, &buf, sizeof(buf)); + # ifdef MSWINCE if (result == 0) { /* Page is free; advance to the next possible allocation base */ @@ -992,7 +1027,9 @@ GC_INNER void GC_register_dynamic_libraries(void) protect = buf.Protect; if (buf.State == MEM_COMMIT && (protect == PAGE_EXECUTE_READWRITE - || protect == PAGE_READWRITE) + || protect == PAGE_EXECUTE_WRITECOPY + || protect == PAGE_READWRITE + || protect == PAGE_WRITECOPY) && (buf.Type == MEM_IMAGE # ifdef GC_REGISTER_MEM_PRIVATE || (protect == PAGE_READWRITE && buf.Type == MEM_PRIVATE) @@ -1033,29 +1070,18 @@ extern int errno; GC_INNER void GC_register_dynamic_libraries(void) { - int status; - ldr_process_t mypid; - - /* module */ - ldr_module_t moduleid = LDR_NULL_MODULE; - ldr_module_info_t moduleinfo; - size_t moduleinfosize = sizeof(moduleinfo); - size_t modulereturnsize; - - /* region */ - ldr_region_t region; - ldr_region_info_t regioninfo; - size_t regioninfosize = sizeof(regioninfo); - size_t regionreturnsize; - - /* Obtain id of this process */ - mypid = ldr_my_process(); + ldr_module_t moduleid = LDR_NULL_MODULE; + ldr_process_t mypid = ldr_my_process(); /* obtain id of this process */ /* For each module */ while (TRUE) { - - /* Get the next (first) module */ - status = ldr_next_module(mypid, &moduleid); + ldr_module_info_t moduleinfo; + size_t modulereturnsize; + ldr_region_t region; + ldr_region_info_t regioninfo; + size_t regionreturnsize; + int status = ldr_next_module(mypid, &moduleid); + /* Get the next (first) module */ /* Any more modules? */ if (moduleid == LDR_NULL_MODULE) @@ -1071,7 +1097,7 @@ GC_INNER void GC_register_dynamic_libraries(void) /* Get the module information */ status = ldr_inq_module(mypid, moduleid, &moduleinfo, - moduleinfosize, &modulereturnsize); + sizeof(moduleinfo), &modulereturnsize); if (status != 0 ) ABORT("ldr_inq_module failed"); @@ -1091,7 +1117,7 @@ GC_INNER void GC_register_dynamic_libraries(void) for (region = 0; region < moduleinfo.lmi_nregion; region++) { /* Get the region information */ status = ldr_inq_region(mypid, moduleid, region, ®ioninfo, - regioninfosize, ®ionreturnsize); + sizeof(regioninfo), ®ionreturnsize); if (status != 0 ) ABORT("ldr_inq_region failed"); @@ -1131,15 +1157,13 @@ extern int sys_nerr; GC_INNER void GC_register_dynamic_libraries(void) { - int status; int index = 1; /* Ordinal position in shared library search list */ - struct shl_descriptor *shl_desc; /* Shared library info, see dl.h */ /* For each dynamic library loaded */ while (TRUE) { - - /* Get info about next shared library */ - status = shl_get(index, &shl_desc); + struct shl_descriptor *shl_desc; /* Shared library info, see dl.h */ + int status = shl_get(index, &shl_desc); + /* Get info about next shared library */ /* Check if this is the end of the list or if some error occurred */ if (status != 0) { @@ -1186,18 +1210,24 @@ GC_INNER void GC_register_dynamic_libraries(void) # include GC_INNER void GC_register_dynamic_libraries(void) { + int ldibuflen = 8192; + + for (;;) { int len; - char *ldibuf; - int ldibuflen; struct ld_info *ldi; +# if defined(CPPCHECK) + char ldibuf[ldibuflen]; +# else + char *ldibuf = alloca(ldibuflen); +# endif - ldibuf = alloca(ldibuflen = 8192); - - while ( (len = loadquery(L_GETINFO,ldibuf,ldibuflen)) < 0) { + len = loadquery(L_GETINFO, ldibuf, ldibuflen); + if (len < 0) { if (errno != ENOMEM) { ABORT("loadquery failed"); } - ldibuf = alloca(ldibuflen *= 2); + ldibuflen *= 2; + continue; } ldi = (struct ld_info *)ldibuf; @@ -1210,6 +1240,8 @@ GC_INNER void GC_register_dynamic_libraries(void) TRUE); ldi = len ? (struct ld_info *)((char *)ldi + len) : 0; } + break; + } } #endif /* AIX */ @@ -1282,8 +1314,6 @@ STATIC void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr, const struct GC_MACH_SECTION *sec; const char *name; GC_has_static_roots_func callback = GC_has_static_roots; - char secnam[16]; - const char *fmt; DCL_LOCK_STATE; if (GC_no_dls) return; @@ -1315,9 +1345,12 @@ STATIC void GC_dyld_image_add(const struct GC_MACH_HEADER *hdr, /* Sections constructed on demand. */ for (j = 0; j < sizeof(GC_dyld_add_sect_fmts) / sizeof(char *); j++) { - fmt = GC_dyld_add_sect_fmts[j]; + const char *fmt = GC_dyld_add_sect_fmts[j]; + /* Add our manufactured aligned BSS sections. */ for (i = 0; i <= L2_MAX_OFILE_ALIGNMENT; i++) { + char secnam[16]; + (void)snprintf(secnam, sizeof(secnam), fmt, (unsigned)i); secnam[sizeof(secnam) - 1] = '\0'; sec = GC_GETSECTBYNAME(hdr, SEG_DATA, secnam); @@ -1347,8 +1380,6 @@ STATIC void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr, unsigned long start, end; unsigned i, j; const struct GC_MACH_SECTION *sec; - char secnam[16]; - const char *fmt; for (i = 0; i < sizeof(GC_dyld_sections)/sizeof(GC_dyld_sections[0]); i++) { sec = GC_GETSECTBYNAME(hdr, GC_dyld_sections[i].seg, @@ -1368,8 +1399,11 @@ STATIC void GC_dyld_image_remove(const struct GC_MACH_HEADER *hdr, /* Remove our on-demand sections. */ for (j = 0; j < sizeof(GC_dyld_add_sect_fmts) / sizeof(char *); j++) { - fmt = GC_dyld_add_sect_fmts[j]; + const char *fmt = GC_dyld_add_sect_fmts[j]; + for (i = 0; i <= L2_MAX_OFILE_ALIGNMENT; i++) { + char secnam[16]; + (void)snprintf(secnam, sizeof(secnam), fmt, (unsigned)i); secnam[sizeof(secnam) - 1] = '\0'; sec = GC_GETSECTBYNAME(hdr, SEG_DATA, secnam); @@ -1424,12 +1458,13 @@ GC_INNER void GC_init_dyld(void) This WILL properly register already linked libraries and libraries linked in the future. */ - - _dyld_register_func_for_add_image(GC_dyld_image_add); - _dyld_register_func_for_remove_image(GC_dyld_image_remove); - /* Ignore 2 compiler warnings here: passing argument 1 of */ - /* '_dyld_register_func_for_add/remove_image' from incompatible */ - /* pointer type. */ + _dyld_register_func_for_add_image( + (void (*)(const struct mach_header*, intptr_t))GC_dyld_image_add); + _dyld_register_func_for_remove_image( + (void (*)(const struct mach_header*, intptr_t))GC_dyld_image_remove); + /* Structure mach_header64 has the same fields */ + /* as mach_header except for the reserved one */ + /* at the end, so these casts are OK. */ /* Set this early to avoid reentrancy issues. */ initialized = TRUE; @@ -1465,6 +1500,21 @@ GC_INNER GC_bool GC_register_main_static_data(void) #endif /* DARWIN */ +#if defined(HAIKU) +# include + + GC_INNER void GC_register_dynamic_libraries(void) + { + image_info info; + int32 cookie = 0; + + while (get_next_image_info(0, &cookie, &info) == B_OK) { + ptr_t data = (ptr_t)info.data; + GC_add_roots_inner(data, data + info.data_size, TRUE); + } + } +#endif /* HAIKU */ + #elif defined(PCR) # include "il/PCR_IL.h" diff --git a/src/bdwgc/extra/AmigaOS.c b/src/bdwgc/extra/AmigaOS.c index 366ef94ec..d8311eed4 100644 --- a/src/bdwgc/extra/AmigaOS.c +++ b/src/bdwgc/extra/AmigaOS.c @@ -9,7 +9,7 @@ #if !defined(GC_AMIGA_DEF) && !defined(GC_AMIGA_SB) && !defined(GC_AMIGA_DS) && !defined(GC_AMIGA_AM) -# include "gc_priv.h" +# include "private/gc_priv.h" # include # include # define GC_AMIGA_DEF @@ -40,7 +40,7 @@ Find the base of the stack. ******************************************************************/ -ptr_t GC_get_main_stack_base() +ptr_t GC_get_main_stack_base(void) { struct Process *proc = (struct Process*)SysBase->ThisTask; @@ -65,16 +65,13 @@ ptr_t GC_get_main_stack_base() Register data segments. ******************************************************************/ - void GC_register_data_segments() + void GC_register_data_segments(void) { struct Process *proc; struct CommandLineInterface *cli; BPTR myseglist; ULONG *data; - int num; - - # ifdef __GNUC__ ULONG dataSegSize; GC_bool found_segment = FALSE; @@ -90,10 +87,9 @@ ptr_t GC_get_main_stack_base() /* Reference: Amiga Guru Book Pages: 538ff,565,573 and XOper.asm */ + myseglist = proc->pr_SegList; if (proc->pr_Task.tc_Node.ln_Type==NT_PROCESS) { - if (proc->pr_CLI == NULL) { - myseglist = proc->pr_SegList; - } else { + if (proc->pr_CLI != NULL) { /* ProcLoaded 'Loaded as a command: '*/ cli = BADDR(proc->pr_CLI); myseglist = cli->cli_Module; @@ -108,11 +104,11 @@ ptr_t GC_get_main_stack_base() /* xoper hunks Shell Process */ - num=0; for (data = (ULONG *)BADDR(myseglist); data != NULL; data = (ULONG *)BADDR(data[0])) { - if (((ULONG) GC_register_data_segments < (ULONG) &data[1]) || - ((ULONG) GC_register_data_segments > (ULONG) &data[1] + data[-1])) { + if ((ULONG)GC_register_data_segments < (ULONG)(&data[1]) + || (ULONG)GC_register_data_segments > (ULONG)(&data[1]) + + data[-1]) { # ifdef __GNUC__ if (dataSegSize == data[-1]) { found_segment = TRUE; @@ -121,7 +117,6 @@ ptr_t GC_get_main_stack_base() GC_add_roots_inner((char *)&data[1], ((char *)&data[1]) + data[-1], FALSE); } - ++num; } /* for */ # ifdef __GNUC__ if (!found_segment) { @@ -213,7 +208,6 @@ int ncur151=0; void GC_amiga_free_all_mem(void){ struct GC_Amiga_AllocedMemoryHeader *gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(GC_AMIGAMEM)); - struct GC_Amiga_AllocedMemoryHeader *temp; #ifdef GC_AMIGA_PRINTSTATS printf("\n\n" @@ -228,11 +222,11 @@ void GC_amiga_free_all_mem(void){ printf("GC_gcollect was called %d times to avoid returning NULL or start allocating with the MEMF_ANY flag.\n",numcollects); printf("%d of them was a success. (the others had to use allocation from the OS.)\n",nullretries); printf("\n"); - printf("Succeded forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",succ,succ2); + printf("Succeeded forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",succ,succ2); printf("Failed forcing %d gc-allocations (%d bytes) of chip-mem to be fast-mem.\n",nsucc,nsucc2); printf("\n"); printf( - "Number of retries before succeding a chip->fast force:\n" + "Number of retries before succeeding a chip->fast force:\n" "0: %d, 1: %d, 2-9: %d, 10-49: %d, 50-149: %d, >150: %d\n", cur0,cur1,cur10,cur50,cur150,cur151 ); @@ -244,7 +238,7 @@ void GC_amiga_free_all_mem(void){ #endif while(gc_am!=NULL){ - temp=gc_am->next; + struct GC_Amiga_AllocedMemoryHeader *temp = gc_am->next; FreeMem(gc_am,gc_am->size); gc_am=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(temp)); } @@ -267,6 +261,8 @@ size_t latestsize; #endif +#ifdef GC_AMIGA_FASTALLOC + /* * The actual function that is called with the GET_MEM macro. * @@ -277,11 +273,10 @@ void *GC_amiga_get_mem(size_t size){ #ifndef GC_AMIGA_ONLYFAST if(GC_amiga_dontalloc==TRUE){ -// printf("rejected, size: %d, latestsize: %d\n",size,latestsize); return NULL; } - // We really don't want to use chip-mem, but if we must, then as little as possible. + /* We really don't want to use chip-mem, but if we must, then as little as possible. */ if(GC_AMIGA_MEMF==(MEMF_ANY|MEMF_CLEAR) && size>100000 && latestsize<50000) return NULL; #endif @@ -292,8 +287,6 @@ void *GC_amiga_get_mem(size_t size){ gc_am->size=size + sizeof(struct GC_Amiga_AllocedMemoryHeader); GC_AMIGAMEM=(struct GC_Amiga_AllocedMemoryHeader *)(~(int)(gc_am)); -// printf("Allocated %d (%d) bytes at address: %x. Latest: %d\n",size,tot,gc_am,latestsize); - #ifdef GC_AMIGA_PRINTSTATS if((char *)gc_am500000?9:size/5000))){ ret=GC_amiga_rec_alloc(size,AllocFunction,rec+1); -// GC_free(ret2); } return ret; @@ -362,16 +354,16 @@ void *GC_amiga_rec_alloc(size_t size,void *(*AllocFunction)(size_t size2),const void *GC_amiga_allocwrapper_any(size_t size,void *(*AllocFunction)(size_t size2)){ - void *ret,*ret2; + void *ret; - GC_amiga_dontalloc=TRUE; // Pretty tough thing to do, but its indeed necessary. + GC_amiga_dontalloc=TRUE; /* Pretty tough thing to do, but its indeed necessary. */ latestsize=size; ret=(*AllocFunction)(size); if(((char *)ret) <= chipmax){ if(ret==NULL){ - //Give GC access to allocate memory. + /* Give GC access to allocate memory. */ #ifdef GC_AMIGA_GC if(!GC_dont_gc){ GC_gcollect(); @@ -380,8 +372,9 @@ void *GC_amiga_allocwrapper_any(size_t size,void *(*AllocFunction)(size_t size2) #endif ret=(*AllocFunction)(size); } + if(ret==NULL) #endif - if(ret==NULL){ + { GC_amiga_dontalloc=FALSE; ret=(*AllocFunction)(size); if(ret==NULL){ @@ -397,13 +390,13 @@ void *GC_amiga_allocwrapper_any(size_t size,void *(*AllocFunction)(size_t size2) } #ifdef GC_AMIGA_RETRY else{ + void *ret2; /* We got chip-mem. Better try again and again and again etc., we might get fast-mem sooner or later... */ /* Using gctest to check the effectiveness of doing this, does seldom give a very good result. */ /* However, real programs doesn't normally rapidly allocate and deallocate. */ -// printf("trying to force... %d bytes... ",size); if( AllocFunction!=GC_malloc_uncollectable -#ifdef ATOMIC_UNCOLLECTABLE +#ifdef GC_ATOMIC_UNCOLLECTABLE && AllocFunction!=GC_malloc_atomic_uncollectable #endif ){ @@ -423,12 +416,10 @@ void *GC_amiga_allocwrapper_any(size_t size,void *(*AllocFunction)(size_t size2) #endif } if(((char *)ret2)>chipmax){ -// printf("Succeeded.\n"); GC_free(ret); ret=ret2; }else{ GC_free(ret2); -// printf("But did not succeed.\n"); } } #endif @@ -447,7 +438,7 @@ void GC_amiga_set_toany(void (*func)(void)){ GC_amiga_toany=func; } -#endif // !GC_AMIGA_ONLYFAST +#endif /* !GC_AMIGA_ONLYFAST */ void *GC_amiga_allocwrapper_fast(size_t size,void *(*AllocFunction)(size_t size2)){ @@ -456,8 +447,7 @@ void *GC_amiga_allocwrapper_fast(size_t size,void *(*AllocFunction)(size_t size2 ret=(*AllocFunction)(size); if(ret==NULL){ - // Enable chip-mem allocation. -// printf("ret==NULL\n"); + /* Enable chip-mem allocation. */ #ifdef GC_AMIGA_GC if(!GC_dont_gc){ GC_gcollect(); @@ -466,8 +456,9 @@ void *GC_amiga_allocwrapper_fast(size_t size,void *(*AllocFunction)(size_t size2 #endif ret=(*AllocFunction)(size); } + if(ret==NULL) #endif - if(ret==NULL){ + { #ifndef GC_AMIGA_ONLYFAST GC_AMIGA_MEMF=MEMF_ANY | MEMF_CLEAR; if(GC_amiga_toany!=NULL) (*GC_amiga_toany)(); @@ -487,13 +478,13 @@ void *GC_amiga_allocwrapper_fast(size_t size,void *(*AllocFunction)(size_t size2 void *GC_amiga_allocwrapper_firsttime(size_t size,void *(*AllocFunction)(size_t size2)){ atexit(&GC_amiga_free_all_mem); - chipmax=(char *)SysBase->MaxLocMem; // For people still having SysBase in chip-mem, this might speed up a bit. + chipmax=(char *)SysBase->MaxLocMem; /* For people still having SysBase in chip-mem, this might speed up a bit. */ GC_amiga_allocwrapper_do=GC_amiga_allocwrapper_fast; return GC_amiga_allocwrapper_fast(size,AllocFunction); } -#endif //GC_AMIGA_FASTALLOC +#endif /* GC_AMIGA_FASTALLOC */ @@ -508,7 +499,8 @@ void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes){ void *ret; latestsize=new_size_in_bytes; ret=GC_realloc(old_object,new_size_in_bytes); - if(ret==NULL && GC_AMIGA_MEMF==(MEMF_FAST | MEMF_CLEAR)){ + if(ret==NULL && new_size_in_bytes != 0 + && GC_AMIGA_MEMF==(MEMF_FAST | MEMF_CLEAR)){ /* Out of fast-mem. */ #ifdef GC_AMIGA_GC if(!GC_dont_gc){ @@ -518,8 +510,9 @@ void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes){ #endif ret=GC_realloc(old_object,new_size_in_bytes); } + if(ret==NULL) #endif - if(ret==NULL){ + { #ifndef GC_AMIGA_ONLYFAST GC_AMIGA_MEMF=MEMF_ANY | MEMF_CLEAR; if(GC_amiga_toany!=NULL) (*GC_amiga_toany)(); @@ -533,7 +526,7 @@ void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes){ } #endif } - if(ret==NULL){ + if(ret==NULL && new_size_in_bytes != 0){ WARN("Out of Memory! Returning NIL!\n", 0); } #ifdef GC_AMIGA_PRINTSTATS @@ -545,4 +538,4 @@ void *GC_amiga_realloc(void *old_object,size_t new_size_in_bytes){ #endif } -#endif //GC_AMIGA_AM +#endif /* GC_AMIGA_AM */ diff --git a/src/bdwgc/extra/MacOS.c b/src/bdwgc/extra/MacOS.c index 27f07eb45..624b383d4 100644 --- a/src/bdwgc/extra/MacOS.c +++ b/src/bdwgc/extra/MacOS.c @@ -24,9 +24,9 @@ unloading shared library. #define GC_BUILD #include "gc.h" -#include "gc_priv.h" +#include "private/gc_priv.h" -// use 'CODE' resource 0 to get exact location of the beginning of global space. +/* use 'CODE' resource 0 to get exact location of the beginning of global space. */ typedef struct { unsigned long aboveA5; @@ -35,7 +35,7 @@ typedef struct { unsigned long JTOffset; } *CodeZeroPtr, **CodeZeroHandle; -void* GC_MacGetDataStart() +void* GC_MacGetDataStart(void) { CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0); if (code0) { @@ -48,6 +48,8 @@ void* GC_MacGetDataStart() return 0; } +#ifdef USE_TEMPORARY_MEMORY + /* track the use of temporary memory so it can be freed all at once. */ typedef struct TemporaryMemoryBlock TemporaryMemoryBlock, **TemporaryMemoryHandle; @@ -58,13 +60,14 @@ struct TemporaryMemoryBlock { }; static TemporaryMemoryHandle theTemporaryMemory = NULL; -static Boolean firstTime = true; void GC_MacFreeTemporaryMemory(void); Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory) { +# if !defined(SHARED_LIBRARY_BUILD) static Boolean firstTime = true; +# endif OSErr result; TemporaryMemoryHandle tempMemBlock; Ptr tempPtr = nil; @@ -76,13 +79,13 @@ Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory) if (clearMemory) memset(tempPtr, 0, size); tempPtr = StripAddress(tempPtr); - // keep track of the allocated blocks. + /* keep track of the allocated blocks. */ (**tempMemBlock).nextBlock = theTemporaryMemory; theTemporaryMemory = tempMemBlock; } # if !defined(SHARED_LIBRARY_BUILD) - // install an exit routine to clean up the memory used at the end. + /* install an exit routine to clean up the memory used at the end. */ if (firstTime) { atexit(&GC_MacFreeTemporaryMemory); firstTime = false; @@ -94,7 +97,7 @@ Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory) extern word GC_fo_entries; -static void perform_final_collection() +static void perform_final_collection(void) { unsigned i; word last_fo_entries = 0; @@ -111,7 +114,7 @@ static void perform_final_collection() } -void GC_MacFreeTemporaryMemory() +void GC_MacFreeTemporaryMemory(void) { # if defined(SHARED_LIBRARY_BUILD) /* if possible, collect all memory, and invoke all finalizers. */ @@ -119,11 +122,15 @@ void GC_MacFreeTemporaryMemory() # endif if (theTemporaryMemory != NULL) { +# if !defined(SHARED_LIBRARY_BUILD) long totalMemoryUsed = 0; +# endif TemporaryMemoryHandle tempMemBlock = theTemporaryMemory; while (tempMemBlock != NULL) { TemporaryMemoryHandle nextBlock = (**tempMemBlock).nextBlock; +# if !defined(SHARED_LIBRARY_BUILD) totalMemoryUsed += GetHandleSize((Handle)tempMemBlock); +# endif DisposeHandle((Handle)tempMemBlock); tempMemBlock = nextBlock; } @@ -132,16 +139,19 @@ void GC_MacFreeTemporaryMemory() # if !defined(SHARED_LIBRARY_BUILD) if (GC_print_stats) { fprintf(stdout, "[total memory used: %ld bytes.]\n", - totalMemoryUsed); - fprintf(stdout, "[total collections: %ld.]\n", GC_gc_no); + totalMemoryUsed); + fprintf(stdout, "[total collections: %lu]\n", + (unsigned long)GC_gc_no); } # endif } } +#endif /* USE_TEMPORARY_MEMORY */ + #if __option(far_data) - void* GC_MacGetDataEnd() + void* GC_MacGetDataEnd(void) { CodeZeroHandle code0 = (CodeZeroHandle)GetResource('CODE', 0); if (code0) { diff --git a/src/bdwgc/extra/Mac_files/MacOS_config.h b/src/bdwgc/extra/Mac_files/MacOS_config.h index ec8f82c3b..abbf9d8ef 100644 --- a/src/bdwgc/extra/Mac_files/MacOS_config.h +++ b/src/bdwgc/extra/Mac_files/MacOS_config.h @@ -12,17 +12,16 @@ /* Boehm, November 17, 1995 12:10 pm PST */ #ifdef __MWERKS__ - -// for CodeWarrior Pro with Metrowerks Standard Library (MSL). -// #define MSL_USE_PRECOMPILED_HEADERS 0 +/* for CodeWarrior Pro with Metrowerks Standard Library (MSL). */ +/* #define MSL_USE_PRECOMPILED_HEADERS 0 */ #include #endif /* __MWERKS__ */ -// these are defined again in gc_priv.h. +/* these are defined again in gc_priv.h. */ #undef TRUE #undef FALSE -#define ALL_INTERIOR_POINTERS // follows interior pointers. -//#define DONT_ADD_BYTE_AT_END // no padding. -//#define SMALL_CONFIG // whether to use a smaller heap. -#define USE_TEMPORARY_MEMORY // use Macintosh temporary memory. +#define ALL_INTERIOR_POINTERS /* follows interior pointers. */ +/* #define DONT_ADD_BYTE_AT_END */ /* no padding. */ +/* #define SMALL_CONFIG */ /* whether to use a smaller heap. */ +#define USE_TEMPORARY_MEMORY /* use Macintosh temporary memory. */ diff --git a/src/bdwgc/extra/gc.c b/src/bdwgc/extra/gc.c index a77fba65c..5a93f1003 100644 --- a/src/bdwgc/extra/gc.c +++ b/src/bdwgc/extra/gc.c @@ -4,6 +4,7 @@ * Copyright (c) 1998 by Fergus Henderson. All rights reserved. * Copyright (c) 2000-2009 by Hewlett-Packard Development Company. * All rights reserved. + * Copyright (c) 2009-2018 Ivan Maidanski * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. diff --git a/src/bdwgc/extra/msvc_dbg.c b/src/bdwgc/extra/msvc_dbg.c index ea7fc7b6c..8abe24738 100644 --- a/src/bdwgc/extra/msvc_dbg.c +++ b/src/bdwgc/extra/msvc_dbg.c @@ -47,7 +47,7 @@ typedef GC_word word; typedef ULONG ULONG_ADDR; #endif -static HANDLE GetSymHandle() +static HANDLE GetSymHandle(void) { static HANDLE symHandle = NULL; if (!symHandle) { @@ -158,8 +158,8 @@ size_t GetStackFramesFromContext(HANDLE hProcess, HANDLE hThread, #elif defined(_M_ALPHA64) machineType = IMAGE_FILE_MACHINE_ALPHA64; stackFrame.AddrPC.Offset = context->Fir; -#else -#error Unknown CPU +#elif !defined(CPPCHECK) +# error Unknown CPU #endif for (frameIndex = 0; frameIndex < maxFrames; ) { BOOL bRet = StackWalk(machineType, hProcess, hThread, &stackFrame, @@ -308,7 +308,6 @@ size_t GetDescriptionFromAddress(void* address, const char* format, char*const begin = buffer; char*const end = buffer + size; size_t line_number = 0; - char str[128]; if (size) { *buffer = 0; @@ -317,7 +316,9 @@ size_t GetDescriptionFromAddress(void* address, const char* format, size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer; if (line_number) { - wsprintf(str, "(%d) : ", line_number); + char str[128]; + + wsprintf(str, "(%d) : ", (int)line_number); if (size) { strncpy(buffer, str, size)[size - 1] = 0; } @@ -341,8 +342,6 @@ size_t GetDescriptionFromAddress(void* address, const char* format, size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer; buffer += GetModuleNameFromAddress(address, buffer, size); - size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer; - return buffer - begin; } @@ -354,12 +353,15 @@ size_t GetDescriptionFromStack(void* const frames[], size_t count, char*const end = begin + size; char* buffer = begin + (count + 1) * sizeof(char*); size_t i; + (void)format; for (i = 0; i < count; ++i) { - if (description) description[i] = buffer; + if (size) + description[i] = buffer; size = (GC_ULONG_PTR)end < (GC_ULONG_PTR)buffer ? 0 : end - buffer; buffer += 1 + GetDescriptionFromAddress(frames[i], NULL, buffer, size); } - if (description) description[count] = NULL; + if (size) + description[count] = NULL; return buffer - begin; } @@ -374,8 +376,14 @@ char** backtrace_symbols(void*const* addresses, int count) { size_t size = GetDescriptionFromStack(addresses, count, NULL, NULL, 0); char** symbols = (char**)malloc(size); - GetDescriptionFromStack(addresses, count, NULL, symbols, size); + if (symbols != NULL) + GetDescriptionFromStack(addresses, count, NULL, symbols, size); return symbols; } -#endif /* !_M_AMD64 */ +#else + + extern int GC_quiet; + /* ANSI C does not allow translation units to be empty. */ + +#endif /* _M_AMD64 */ diff --git a/src/bdwgc/extra/symbian.cpp b/src/bdwgc/extra/symbian.cpp index 94dd4de4f..8fdee6f34 100644 --- a/src/bdwgc/extra/symbian.cpp +++ b/src/bdwgc/extra/symbian.cpp @@ -45,7 +45,8 @@ char* GC_get_private_path_and_zero_file() size_t size = path8.Length() + 1; char* copyChar = (char*) malloc( size ); - memcpy( copyChar, path8.PtrZ(), size ); + if (copyChar) + memcpy( copyChar, path8.PtrZ(), size ); return copyChar; // ownership passed } diff --git a/src/bdwgc/finalize.c b/src/bdwgc/finalize.c index c2e8af026..95bbda7bf 100644 --- a/src/bdwgc/finalize.c +++ b/src/bdwgc/finalize.c @@ -26,7 +26,7 @@ typedef void (* finalization_mark_proc)(ptr_t /* finalizable_obj_ptr */); #define HASH3(addr,size,log_size) \ ((((word)(addr) >> 3) ^ ((word)(addr) >> (3 + (log_size)))) \ & ((size) - 1)) -#define HASH2(addr,log_size) HASH3(addr, 1 << (log_size), log_size) +#define HASH2(addr,log_size) HASH3(addr, (word)1 << (log_size), log_size) struct hash_chain_entry { word hidden_key; @@ -55,7 +55,7 @@ STATIC struct dl_hashtbl_s GC_dl_hashtbl = { STATIC struct dl_hashtbl_s GC_ll_hashtbl = { NULL, -1, 0 }; #endif -STATIC struct finalizable_object { +struct finalizable_object { struct hash_chain_entry prolog; # define fo_hidden_base prolog.hidden_key /* Pointer to object base. */ @@ -67,50 +67,68 @@ STATIC struct finalizable_object { ptr_t fo_client_data; word fo_object_size; /* In bytes. */ finalization_mark_proc fo_mark_proc; /* Mark-through procedure */ -} **GC_fo_head = 0; - -STATIC struct finalizable_object * GC_finalize_now = 0; - /* List of objects that should be finalized now. */ +}; static signed_word log_fo_table_size = -1; -GC_INNER void GC_push_finalizer_structures(void) +STATIC struct { + struct finalizable_object **fo_head; + /* List of objects that should be finalized now: */ + struct finalizable_object *finalize_now; +} GC_fnlz_roots = { NULL, NULL }; + +GC_API void GC_CALL GC_push_finalizer_structures(void) { - GC_ASSERT((word)&GC_dl_hashtbl.head % sizeof(word) == 0); - GC_ASSERT((word)&GC_fo_head % sizeof(word) == 0); - GC_ASSERT((word)&GC_finalize_now % sizeof(word) == 0); - + GC_ASSERT((word)(&GC_dl_hashtbl.head) % sizeof(word) == 0); + GC_ASSERT((word)(&GC_fnlz_roots) % sizeof(word) == 0); # ifndef GC_LONG_REFS_NOT_NEEDED - GC_ASSERT((word)&GC_ll_hashtbl.head % sizeof(word) == 0); - GC_push_all((ptr_t)(&GC_ll_hashtbl.head), - (ptr_t)(&GC_ll_hashtbl.head) + sizeof(word)); + GC_ASSERT((word)(&GC_ll_hashtbl.head) % sizeof(word) == 0); + GC_PUSH_ALL_SYM(GC_ll_hashtbl.head); # endif - - GC_push_all((ptr_t)(&GC_dl_hashtbl.head), - (ptr_t)(&GC_dl_hashtbl.head) + sizeof(word)); - GC_push_all((ptr_t)(&GC_fo_head), (ptr_t)(&GC_fo_head) + sizeof(word)); - GC_push_all((ptr_t)(&GC_finalize_now), - (ptr_t)(&GC_finalize_now) + sizeof(word)); + GC_PUSH_ALL_SYM(GC_dl_hashtbl.head); + GC_PUSH_ALL_SYM(GC_fnlz_roots); } -/* Double the size of a hash table. *size_ptr is the log of its current */ -/* size. May be a no-op. */ +/* Threshold of log_size to initiate full collection before growing */ +/* a hash table. */ +#ifndef GC_ON_GROW_LOG_SIZE_MIN +# define GC_ON_GROW_LOG_SIZE_MIN CPP_LOG_HBLKSIZE +#endif + +/* Double the size of a hash table. *log_size_ptr is the log of its */ +/* current size. May be a no-op. */ /* *table is a pointer to an array of hash headers. If we succeed, we */ /* update both *table and *log_size_ptr. Lock is held. */ STATIC void GC_grow_table(struct hash_chain_entry ***table, - signed_word *log_size_ptr) + signed_word *log_size_ptr, word *entries_ptr) { register word i; register struct hash_chain_entry *p; signed_word log_old_size = *log_size_ptr; signed_word log_new_size = log_old_size + 1; - word old_size = ((log_old_size == -1)? 0: (1 << log_old_size)); + word old_size = log_old_size == -1 ? 0 : (word)1 << log_old_size; word new_size = (word)1 << log_new_size; /* FIXME: Power of 2 size often gets rounded up to one more page. */ - struct hash_chain_entry **new_table = (struct hash_chain_entry **) - GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE( - (size_t)new_size * sizeof(struct hash_chain_entry *), NORMAL); + struct hash_chain_entry **new_table; + GC_ASSERT(I_HOLD_LOCK()); + /* Avoid growing the table in case of at least 25% of entries can */ + /* be deleted by enforcing a collection. Ignored for small tables. */ + if (log_old_size >= GC_ON_GROW_LOG_SIZE_MIN) { + IF_CANCEL(int cancel_state;) + + DISABLE_CANCEL(cancel_state); + (void)GC_try_to_collect_inner(GC_never_stop_func); + RESTORE_CANCEL(cancel_state); + /* GC_finalize might decrease entries value. */ + if (*entries_ptr < ((word)1 << log_old_size) - (*entries_ptr >> 2)) + return; + } + + new_table = (struct hash_chain_entry **) + GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE( + (size_t)new_size * sizeof(struct hash_chain_entry *), + NORMAL); if (new_table == 0) { if (*table == 0) { ABORT("Insufficient space for initial table allocation"); @@ -126,12 +144,14 @@ STATIC void GC_grow_table(struct hash_chain_entry ***table, size_t new_hash = HASH3(real_key, new_size, log_new_size); p -> next = new_table[new_hash]; + GC_dirty(p); new_table[new_hash] = p; p = next; } } *log_size_ptr = log_new_size; *table = new_table; + GC_dirty(new_table); /* entire object */ } GC_API int GC_CALL GC_register_disappearing_link(void * * link) @@ -146,20 +166,24 @@ GC_API int GC_CALL GC_register_disappearing_link(void * * link) STATIC int GC_register_disappearing_link_inner( struct dl_hashtbl_s *dl_hashtbl, void **link, - const void *obj) + const void *obj, const char *tbl_log_name) { struct disappearing_link *curr_dl; size_t index; struct disappearing_link * new_dl; DCL_LOCK_STATE; + if (EXPECT(GC_find_leak, FALSE)) return GC_UNIMPLEMENTED; LOCK(); GC_ASSERT(obj != NULL && GC_base_C(obj) == obj); if (dl_hashtbl -> log_size == -1 || dl_hashtbl -> entries > ((word)1 << dl_hashtbl -> log_size)) { GC_grow_table((struct hash_chain_entry ***)&dl_hashtbl -> head, - &dl_hashtbl -> log_size); - GC_COND_LOG_PRINTF("Grew dl table to %u entries\n", + &dl_hashtbl -> log_size, &dl_hashtbl -> entries); +# ifdef LINT2 + if (dl_hashtbl->log_size < 0) ABORT("log_size is negative"); +# endif + GC_COND_LOG_PRINTF("Grew %s table to %u entries\n", tbl_log_name, 1 << (unsigned)dl_hashtbl -> log_size); } index = HASH2(link, dl_hashtbl -> log_size); @@ -202,8 +226,10 @@ STATIC int GC_register_disappearing_link_inner( new_dl -> dl_hidden_obj = GC_HIDE_POINTER(obj); new_dl -> dl_hidden_link = GC_HIDE_POINTER(link); dl_set_next(new_dl, dl_hashtbl -> head[index]); + GC_dirty(new_dl); dl_hashtbl -> head[index] = new_dl; dl_hashtbl -> entries++; + GC_dirty(dl_hashtbl->head + index); UNLOCK(); return GC_SUCCESS; } @@ -211,9 +237,10 @@ STATIC int GC_register_disappearing_link_inner( GC_API int GC_CALL GC_general_register_disappearing_link(void * * link, const void * obj) { - if (((word)link & (ALIGNMENT-1)) != 0 || NULL == link) + if (((word)link & (ALIGNMENT-1)) != 0 || !NONNULL_ARG_NOT_NULL(link)) ABORT("Bad arg to GC_general_register_disappearing_link"); - return GC_register_disappearing_link_inner(&GC_dl_hashtbl, link, obj); + return GC_register_disappearing_link_inner(&GC_dl_hashtbl, link, obj, + "dl"); } #ifdef DBG_HDRS_ALL @@ -229,16 +256,22 @@ GC_INLINE struct disappearing_link *GC_unregister_disappearing_link_inner( { struct disappearing_link *curr_dl; struct disappearing_link *prev_dl = NULL; - size_t index = HASH2(link, dl_hashtbl->log_size); + size_t index; + if (dl_hashtbl->log_size == -1) + return NULL; /* prevent integer shift by a negative amount */ + + index = HASH2(link, dl_hashtbl->log_size); for (curr_dl = dl_hashtbl -> head[index]; curr_dl; curr_dl = dl_next(curr_dl)) { if (curr_dl -> dl_hidden_link == GC_HIDE_POINTER(link)) { /* Remove found entry from the table. */ if (NULL == prev_dl) { dl_hashtbl -> head[index] = dl_next(curr_dl); + GC_dirty(dl_hashtbl->head + index); } else { dl_set_next(prev_dl, dl_next(curr_dl)); + GC_dirty(prev_dl); } dl_hashtbl -> entries--; break; @@ -263,12 +296,213 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link) return 1; } +/* Toggle-ref support. */ +#ifndef GC_TOGGLE_REFS_NOT_NEEDED + typedef union { + /* Lowest bit is used to distinguish between choices. */ + void *strong_ref; + GC_hidden_pointer weak_ref; + } GCToggleRef; + + STATIC GC_toggleref_func GC_toggleref_callback = 0; + STATIC GCToggleRef *GC_toggleref_arr = NULL; + STATIC int GC_toggleref_array_size = 0; + STATIC int GC_toggleref_array_capacity = 0; + + GC_INNER void GC_process_togglerefs(void) + { + int i; + int new_size = 0; + GC_bool needs_barrier = FALSE; + + GC_ASSERT(I_HOLD_LOCK()); + for (i = 0; i < GC_toggleref_array_size; ++i) { + GCToggleRef r = GC_toggleref_arr[i]; + void *obj = r.strong_ref; + + if (((word)obj & 1) != 0) { + obj = GC_REVEAL_POINTER(r.weak_ref); + } + if (NULL == obj) { + continue; + } + switch (GC_toggleref_callback(obj)) { + case GC_TOGGLE_REF_DROP: + break; + case GC_TOGGLE_REF_STRONG: + GC_toggleref_arr[new_size++].strong_ref = obj; + needs_barrier = TRUE; + break; + case GC_TOGGLE_REF_WEAK: + GC_toggleref_arr[new_size++].weak_ref = GC_HIDE_POINTER(obj); + break; + default: + ABORT("Bad toggle-ref status returned by callback"); + } + } + + if (new_size < GC_toggleref_array_size) { + BZERO(&GC_toggleref_arr[new_size], + (GC_toggleref_array_size - new_size) * sizeof(GCToggleRef)); + GC_toggleref_array_size = new_size; + } + if (needs_barrier) + GC_dirty(GC_toggleref_arr); /* entire object */ + } + + STATIC void GC_normal_finalize_mark_proc(ptr_t); + + static void push_and_mark_object(void *p) + { + GC_normal_finalize_mark_proc(p); + while (!GC_mark_stack_empty()) { + MARK_FROM_MARK_STACK(); + } + GC_set_mark_bit(p); + if (GC_mark_state != MS_NONE) { + while (!GC_mark_some(0)) { + /* Empty. */ + } + } + } + + STATIC void GC_mark_togglerefs(void) + { + int i; + if (NULL == GC_toggleref_arr) + return; + + /* TODO: Hide GC_toggleref_arr to avoid its marking from roots. */ + GC_set_mark_bit(GC_toggleref_arr); + for (i = 0; i < GC_toggleref_array_size; ++i) { + void *obj = GC_toggleref_arr[i].strong_ref; + if (obj != NULL && ((word)obj & 1) == 0) { + push_and_mark_object(obj); + } + } + } + + STATIC void GC_clear_togglerefs(void) + { + int i; + for (i = 0; i < GC_toggleref_array_size; ++i) { + if ((GC_toggleref_arr[i].weak_ref & 1) != 0) { + if (!GC_is_marked(GC_REVEAL_POINTER(GC_toggleref_arr[i].weak_ref))) { + GC_toggleref_arr[i].weak_ref = 0; + } else { + /* No need to copy, BDWGC is a non-moving collector. */ + } + } + } + } + + GC_API void GC_CALL GC_set_toggleref_func(GC_toggleref_func fn) + { + DCL_LOCK_STATE; + + LOCK(); + GC_toggleref_callback = fn; + UNLOCK(); + } + + GC_API GC_toggleref_func GC_CALL GC_get_toggleref_func(void) + { + GC_toggleref_func fn; + DCL_LOCK_STATE; + + LOCK(); + fn = GC_toggleref_callback; + UNLOCK(); + return fn; + } + + static GC_bool ensure_toggleref_capacity(int capacity_inc) + { + GC_ASSERT(capacity_inc >= 0); + if (NULL == GC_toggleref_arr) { + GC_toggleref_array_capacity = 32; /* initial capacity */ + GC_toggleref_arr = GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE( + GC_toggleref_array_capacity * sizeof(GCToggleRef), + NORMAL); + if (NULL == GC_toggleref_arr) + return FALSE; + } + if ((unsigned)GC_toggleref_array_size + (unsigned)capacity_inc + >= (unsigned)GC_toggleref_array_capacity) { + GCToggleRef *new_array; + while ((unsigned)GC_toggleref_array_capacity + < (unsigned)GC_toggleref_array_size + (unsigned)capacity_inc) { + GC_toggleref_array_capacity *= 2; + if (GC_toggleref_array_capacity < 0) /* overflow */ + return FALSE; + } + + new_array = GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE( + GC_toggleref_array_capacity * sizeof(GCToggleRef), + NORMAL); + if (NULL == new_array) + return FALSE; + BCOPY(GC_toggleref_arr, new_array, + GC_toggleref_array_size * sizeof(GCToggleRef)); + GC_INTERNAL_FREE(GC_toggleref_arr); + GC_toggleref_arr = new_array; + } + return TRUE; + } + + GC_API int GC_CALL GC_toggleref_add(void *obj, int is_strong_ref) + { + int res = GC_SUCCESS; + DCL_LOCK_STATE; + + GC_ASSERT(NONNULL_ARG_NOT_NULL(obj)); + LOCK(); + if (GC_toggleref_callback != 0) { + if (!ensure_toggleref_capacity(1)) { + res = GC_NO_MEMORY; + } else { + GC_toggleref_arr[GC_toggleref_array_size].strong_ref = + is_strong_ref ? obj : (void *)GC_HIDE_POINTER(obj); + if (is_strong_ref) + GC_dirty(GC_toggleref_arr + GC_toggleref_array_size); + GC_toggleref_array_size++; + } + } + UNLOCK(); + return res; + } +#endif /* !GC_TOGGLE_REFS_NOT_NEEDED */ + +/* Finalizer callback support. */ +STATIC GC_await_finalize_proc GC_object_finalized_proc = 0; + +GC_API void GC_CALL GC_set_await_finalize_proc(GC_await_finalize_proc fn) +{ + DCL_LOCK_STATE; + + LOCK(); + GC_object_finalized_proc = fn; + UNLOCK(); +} + +GC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void) +{ + GC_await_finalize_proc fn; + DCL_LOCK_STATE; + + LOCK(); + fn = GC_object_finalized_proc; + UNLOCK(); + return fn; +} + #ifndef GC_LONG_REFS_NOT_NEEDED GC_API int GC_CALL GC_register_long_link(void * * link, const void * obj) { - if (((word)link & (ALIGNMENT-1)) != 0 || NULL == link) + if (((word)link & (ALIGNMENT-1)) != 0 || !NONNULL_ARG_NOT_NULL(link)) ABORT("Bad arg to GC_register_long_link"); - return GC_register_disappearing_link_inner(&GC_ll_hashtbl, link, obj); + return GC_register_disappearing_link_inner(&GC_ll_hashtbl, link, obj, + "long dl"); } GC_API int GC_CALL GC_unregister_long_link(void * * link) @@ -298,6 +532,9 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link) word curr_hidden_link; word new_hidden_link; + if (dl_hashtbl->log_size == -1) + return GC_NOT_FOUND; /* prevent integer shift by a negative amount */ + /* Find current link. */ curr_index = HASH2(link, dl_hashtbl -> log_size); curr_hidden_link = GC_HIDE_POINTER(link); @@ -333,10 +570,13 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link) dl_hashtbl -> head[curr_index] = dl_next(curr_dl); } else { dl_set_next(prev_dl, dl_next(curr_dl)); + GC_dirty(prev_dl); } curr_dl -> dl_hidden_link = new_hidden_link; dl_set_next(curr_dl, dl_hashtbl -> head[new_index]); dl_hashtbl -> head[new_index] = curr_dl; + GC_dirty(curr_dl); + GC_dirty(dl_hashtbl->head); /* entire object */ return GC_SUCCESS; } @@ -345,7 +585,8 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link) int result; DCL_LOCK_STATE; - if (((word)new_link & (ALIGNMENT-1)) != 0 || new_link == NULL) + if (((word)new_link & (ALIGNMENT-1)) != 0 + || !NONNULL_ARG_NOT_NULL(new_link)) ABORT("Bad new_link arg to GC_move_disappearing_link"); if (((word)link & (ALIGNMENT-1)) != 0) return GC_NOT_FOUND; /* Nothing to do. */ @@ -362,8 +603,9 @@ GC_API int GC_CALL GC_unregister_disappearing_link(void * * link) int result; DCL_LOCK_STATE; - if (((word)new_link & (ALIGNMENT-1)) != 0 || new_link == NULL) - ABORT("Bad new_link arg to GC_move_disappearing_link"); + if (((word)new_link & (ALIGNMENT-1)) != 0 + || !NONNULL_ARG_NOT_NULL(new_link)) + ABORT("Bad new_link arg to GC_move_long_link"); if (((word)link & (ALIGNMENT-1)) != 0) return GC_NOT_FOUND; /* Nothing to do. */ @@ -393,7 +635,6 @@ STATIC void GC_ignore_self_finalize_mark_proc(ptr_t p) hdr * hhdr = HDR(p); word descr = hhdr -> hb_descr; ptr_t q; - word r; ptr_t scan_limit; ptr_t target_limit = p + hhdr -> hb_sz - 1; @@ -403,7 +644,8 @@ STATIC void GC_ignore_self_finalize_mark_proc(ptr_t p) scan_limit = target_limit + 1 - sizeof(word); } for (q = p; (word)q <= (word)scan_limit; q += ALIGNMENT) { - r = *(word *)q; + word r = *(word *)q; + if (r < (word)p || r > (word)target_limit) { GC_PUSH_ONE_HEAP(r, q, GC_mark_stack_top); } @@ -435,41 +677,45 @@ STATIC void GC_register_finalizer_inner(void * obj, GC_finalization_proc *ofn, void **ocd, finalization_mark_proc mp) { - ptr_t base; - struct finalizable_object * curr_fo, * prev_fo; + struct finalizable_object * curr_fo; size_t index; struct finalizable_object *new_fo = 0; hdr *hhdr = NULL; /* initialized to prevent warning. */ - GC_oom_func oom_fn; DCL_LOCK_STATE; + if (EXPECT(GC_find_leak, FALSE)) return; LOCK(); if (log_fo_table_size == -1 || GC_fo_entries > ((word)1 << log_fo_table_size)) { - GC_grow_table((struct hash_chain_entry ***)&GC_fo_head, - &log_fo_table_size); + GC_grow_table((struct hash_chain_entry ***)&GC_fnlz_roots.fo_head, + &log_fo_table_size, &GC_fo_entries); +# ifdef LINT2 + if (log_fo_table_size < 0) ABORT("log_size is negative"); +# endif GC_COND_LOG_PRINTF("Grew fo table to %u entries\n", 1 << (unsigned)log_fo_table_size); } /* in the THREADS case we hold allocation lock. */ - base = (ptr_t)obj; for (;;) { - index = HASH2(base, log_fo_table_size); - prev_fo = 0; - curr_fo = GC_fo_head[index]; + struct finalizable_object *prev_fo = NULL; + GC_oom_func oom_fn; + + index = HASH2(obj, log_fo_table_size); + curr_fo = GC_fnlz_roots.fo_head[index]; while (curr_fo != 0) { GC_ASSERT(GC_size(curr_fo) >= sizeof(struct finalizable_object)); - if (curr_fo -> fo_hidden_base == GC_HIDE_POINTER(base)) { + if (curr_fo -> fo_hidden_base == GC_HIDE_POINTER(obj)) { /* Interruption by a signal in the middle of this */ /* should be safe. The client may see only *ocd */ /* updated, but we'll declare that to be his problem. */ if (ocd) *ocd = (void *) (curr_fo -> fo_client_data); if (ofn) *ofn = curr_fo -> fo_fn; - /* Delete the structure for base. */ + /* Delete the structure for obj. */ if (prev_fo == 0) { - GC_fo_head[index] = fo_next(curr_fo); + GC_fnlz_roots.fo_head[index] = fo_next(curr_fo); } else { fo_set_next(prev_fo, fo_next(curr_fo)); + GC_dirty(prev_fo); } if (fn == 0) { GC_fo_entries--; @@ -483,14 +729,18 @@ STATIC void GC_register_finalizer_inner(void * obj, curr_fo -> fo_fn = fn; curr_fo -> fo_client_data = (ptr_t)cd; curr_fo -> fo_mark_proc = mp; + GC_dirty(curr_fo); /* Reinsert it. We deleted it first to maintain */ /* consistency in the event of a signal. */ if (prev_fo == 0) { - GC_fo_head[index] = curr_fo; + GC_fnlz_roots.fo_head[index] = curr_fo; } else { fo_set_next(prev_fo, curr_fo); + GC_dirty(prev_fo); } } + if (NULL == prev_fo) + GC_dirty(GC_fnlz_roots.fo_head + index); UNLOCK(); # ifndef DBG_HDRS_ALL if (EXPECT(new_fo != 0, FALSE)) { @@ -504,7 +754,11 @@ STATIC void GC_register_finalizer_inner(void * obj, curr_fo = fo_next(curr_fo); } if (EXPECT(new_fo != 0, FALSE)) { - /* new_fo is returned by GC_oom_fn(), so fn != 0 and hhdr != 0. */ + /* new_fo is returned by GC_oom_fn(). */ + GC_ASSERT(fn != 0); +# ifdef LINT2 + if (NULL == hhdr) ABORT("Bad hhdr in GC_register_finalizer_inner"); +# endif break; } if (fn == 0) { @@ -513,7 +767,7 @@ STATIC void GC_register_finalizer_inner(void * obj, UNLOCK(); return; } - GET_HDR(base, hhdr); + GET_HDR(obj, hhdr); if (EXPECT(0 == hhdr, FALSE)) { /* We won't collect it, hence finalizer wouldn't be run. */ if (ocd) *ocd = 0; @@ -541,14 +795,16 @@ STATIC void GC_register_finalizer_inner(void * obj, GC_ASSERT(GC_size(new_fo) >= sizeof(struct finalizable_object)); if (ocd) *ocd = 0; if (ofn) *ofn = 0; - new_fo -> fo_hidden_base = GC_HIDE_POINTER(base); + new_fo -> fo_hidden_base = GC_HIDE_POINTER(obj); new_fo -> fo_fn = fn; new_fo -> fo_client_data = (ptr_t)cd; new_fo -> fo_object_size = hhdr -> hb_sz; new_fo -> fo_mark_proc = mp; - fo_set_next(new_fo, GC_fo_head[index]); + fo_set_next(new_fo, GC_fnlz_roots.fo_head[index]); + GC_dirty(new_fo); GC_fo_entries++; - GC_fo_head[index] = new_fo; + GC_fnlz_roots.fo_head[index] = new_fo; + GC_dirty(GC_fnlz_roots.fo_head + index); UNLOCK(); } @@ -593,27 +849,29 @@ GC_API void GC_CALL GC_register_finalizer_unreachable(void * obj, STATIC void GC_dump_finalization_links( const struct dl_hashtbl_s *dl_hashtbl) { - struct disappearing_link *curr_dl; - ptr_t real_ptr, real_link; size_t dl_size = dl_hashtbl->log_size == -1 ? 0 : - 1 << dl_hashtbl->log_size; + (size_t)1 << dl_hashtbl->log_size; size_t i; for (i = 0; i < dl_size; i++) { + struct disappearing_link *curr_dl; + for (curr_dl = dl_hashtbl -> head[i]; curr_dl != 0; curr_dl = dl_next(curr_dl)) { - real_ptr = GC_REVEAL_POINTER(curr_dl -> dl_hidden_obj); - real_link = GC_REVEAL_POINTER(curr_dl -> dl_hidden_link); - GC_printf("Object: %p, link: %p\n", real_ptr, real_link); + ptr_t real_ptr = GC_REVEAL_POINTER(curr_dl -> dl_hidden_obj); + ptr_t real_link = GC_REVEAL_POINTER(curr_dl -> dl_hidden_link); + + GC_printf("Object: %p, link: %p\n", + (void *)real_ptr, (void *)real_link); } } } - void GC_dump_finalization(void) + GC_API void GC_CALL GC_dump_finalization(void) { struct finalizable_object * curr_fo; - size_t fo_size = log_fo_table_size == -1 ? 0 : 1 << log_fo_table_size; - ptr_t real_ptr; + size_t fo_size = log_fo_table_size == -1 ? 0 : + (size_t)1 << log_fo_table_size; size_t i; GC_printf("Disappearing (short) links:\n"); @@ -624,10 +882,11 @@ GC_API void GC_CALL GC_register_finalizer_unreachable(void * obj, # endif GC_printf("Finalizers:\n"); for (i = 0; i < fo_size; i++) { - for (curr_fo = GC_fo_head[i]; curr_fo != 0; - curr_fo = fo_next(curr_fo)) { - real_ptr = GC_REVEAL_POINTER(curr_fo -> fo_hidden_base); - GC_printf("Finalizable object: %p\n", real_ptr); + for (curr_fo = GC_fnlz_roots.fo_head[i]; + curr_fo != NULL; curr_fo = fo_next(curr_fo)) { + ptr_t real_ptr = GC_REVEAL_POINTER(curr_fo -> fo_hidden_base); + + GC_printf("Finalizable object: %p\n", (void *)real_ptr); } } } @@ -672,10 +931,11 @@ GC_API void GC_CALL GC_register_finalizer_unreachable(void * obj, { \ size_t i; \ size_t dl_size = dl_hashtbl->log_size == -1 ? 0 : \ - 1 << dl_hashtbl->log_size; \ + (size_t)1 << dl_hashtbl->log_size; \ + GC_bool needs_barrier = FALSE; \ for (i = 0; i < dl_size; i++) { \ + struct disappearing_link *prev_dl = NULL; \ curr_dl = dl_hashtbl -> head[i]; \ - prev_dl = NULL; \ while (curr_dl) { #define ITERATE_DL_HASHTBL_END(curr_dl, prev_dl) \ @@ -683,6 +943,8 @@ GC_API void GC_CALL GC_register_finalizer_unreachable(void * obj, curr_dl = dl_next(curr_dl); \ } \ } \ + if (needs_barrier) \ + GC_dirty(dl_hashtbl -> head); /* entire object */ \ } #define DELETE_DL_HASHTBL_ENTRY(dl_hashtbl, curr_dl, prev_dl, next_dl) \ @@ -690,8 +952,10 @@ GC_API void GC_CALL GC_register_finalizer_unreachable(void * obj, next_dl = dl_next(curr_dl); \ if (NULL == prev_dl) { \ dl_hashtbl -> head[i] = next_dl; \ + needs_barrier = TRUE; \ } else { \ dl_set_next(prev_dl, next_dl); \ + GC_dirty(prev_dl); \ } \ GC_clear_mark_bit(curr_dl); \ dl_hashtbl -> entries--; \ @@ -702,15 +966,14 @@ GC_API void GC_CALL GC_register_finalizer_unreachable(void * obj, GC_INLINE void GC_make_disappearing_links_disappear( struct dl_hashtbl_s* dl_hashtbl) { - struct disappearing_link *curr, *prev, *next; - ptr_t real_ptr, real_link; + struct disappearing_link *curr, *next; ITERATE_DL_HASHTBL_BEGIN(dl_hashtbl, curr, prev) - real_ptr = GC_REVEAL_POINTER(curr -> dl_hidden_obj); - real_link = GC_REVEAL_POINTER(curr -> dl_hidden_link); + ptr_t real_ptr = GC_REVEAL_POINTER(curr -> dl_hidden_obj); + ptr_t real_link = GC_REVEAL_POINTER(curr -> dl_hidden_link); + if (!GC_is_marked(real_ptr)) { *(word *)real_link = 0; - GC_clear_mark_bit(curr); DELETE_DL_HASHTBL_ENTRY(dl_hashtbl, curr, prev, next); } ITERATE_DL_HASHTBL_END(curr, prev) @@ -719,13 +982,12 @@ GC_INLINE void GC_make_disappearing_links_disappear( GC_INLINE void GC_remove_dangling_disappearing_links( struct dl_hashtbl_s* dl_hashtbl) { - struct disappearing_link *curr, *prev, *next; - ptr_t real_link; + struct disappearing_link *curr, *next; ITERATE_DL_HASHTBL_BEGIN(dl_hashtbl, curr, prev) - real_link = GC_base(GC_REVEAL_POINTER(curr -> dl_hidden_link)); + ptr_t real_link = GC_base(GC_REVEAL_POINTER(curr -> dl_hidden_link)); + if (NULL != real_link && !GC_is_marked(real_link)) { - GC_clear_mark_bit(curr); DELETE_DL_HASHTBL_ENTRY(dl_hashtbl, curr, prev, next); } ITERATE_DL_HASHTBL_END(curr, prev) @@ -739,7 +1001,9 @@ GC_INNER void GC_finalize(void) struct finalizable_object * curr_fo, * prev_fo, * next_fo; ptr_t real_ptr; size_t i; - size_t fo_size = log_fo_table_size == -1 ? 0 : 1 << log_fo_table_size; + size_t fo_size = log_fo_table_size == -1 ? 0 : + (size_t)1 << log_fo_table_size; + GC_bool needs_barrier = FALSE; # ifndef SMALL_CONFIG /* Save current GC_[dl/ll]_entries value for stats printing */ @@ -749,14 +1013,17 @@ GC_INNER void GC_finalize(void) # endif # endif +# ifndef GC_TOGGLE_REFS_NOT_NEEDED + GC_mark_togglerefs(); +# endif GC_make_disappearing_links_disappear(&GC_dl_hashtbl); /* Mark all objects reachable via chains of 1 or more pointers */ /* from finalizable objects. */ GC_ASSERT(GC_mark_state == MS_NONE); for (i = 0; i < fo_size; i++) { - for (curr_fo = GC_fo_head[i]; curr_fo != 0; - curr_fo = fo_next(curr_fo)) { + for (curr_fo = GC_fnlz_roots.fo_head[i]; + curr_fo != NULL; curr_fo = fo_next(curr_fo)) { GC_ASSERT(GC_size(curr_fo) >= sizeof(struct finalizable_object)); real_ptr = GC_REVEAL_POINTER(curr_fo -> fo_hidden_base); if (!GC_is_marked(real_ptr)) { @@ -772,7 +1039,7 @@ GC_INNER void GC_finalize(void) /* unreachable. */ GC_bytes_finalized = 0; for (i = 0; i < fo_size; i++) { - curr_fo = GC_fo_head[i]; + curr_fo = GC_fnlz_roots.fo_head[i]; prev_fo = 0; while (curr_fo != 0) { real_ptr = GC_REVEAL_POINTER(curr_fo -> fo_hidden_base); @@ -782,15 +1049,25 @@ GC_INNER void GC_finalize(void) } /* Delete from hash table */ next_fo = fo_next(curr_fo); - if (prev_fo == 0) { - GC_fo_head[i] = next_fo; + if (NULL == prev_fo) { + GC_fnlz_roots.fo_head[i] = next_fo; + if (GC_object_finalized_proc) { + GC_dirty(GC_fnlz_roots.fo_head + i); + } else { + needs_barrier = TRUE; + } } else { fo_set_next(prev_fo, next_fo); + GC_dirty(prev_fo); } GC_fo_entries--; + if (GC_object_finalized_proc) + GC_object_finalized_proc(real_ptr); + /* Add to list of objects awaiting finalization. */ - fo_set_next(curr_fo, GC_finalize_now); - GC_finalize_now = curr_fo; + fo_set_next(curr_fo, GC_fnlz_roots.finalize_now); + GC_dirty(curr_fo); + GC_fnlz_roots.finalize_now = curr_fo; /* unhide object pointer so any future collections will */ /* see it. */ curr_fo -> fo_hidden_base = @@ -810,8 +1087,8 @@ GC_INNER void GC_finalize(void) if (GC_java_finalization) { /* make sure we mark everything reachable from objects finalized using the no_order mark_proc */ - for (curr_fo = GC_finalize_now; - curr_fo != NULL; curr_fo = fo_next(curr_fo)) { + for (curr_fo = GC_fnlz_roots.finalize_now; + curr_fo != NULL; curr_fo = fo_next(curr_fo)) { real_ptr = (ptr_t)curr_fo -> fo_hidden_base; if (!GC_is_marked(real_ptr)) { if (curr_fo -> fo_mark_proc == GC_null_finalize_mark_proc) { @@ -826,30 +1103,37 @@ GC_INNER void GC_finalize(void) /* now revive finalize-when-unreachable objects reachable from other finalizable objects */ if (need_unreachable_finalization) { - curr_fo = GC_finalize_now; - prev_fo = 0; - while (curr_fo != 0) { + curr_fo = GC_fnlz_roots.finalize_now; +# if defined(GC_ASSERTIONS) || defined(LINT2) + if (curr_fo != NULL && log_fo_table_size < 0) + ABORT("log_size is negative"); +# endif + prev_fo = NULL; + while (curr_fo != NULL) { next_fo = fo_next(curr_fo); if (curr_fo -> fo_mark_proc == GC_unreachable_finalize_mark_proc) { real_ptr = (ptr_t)curr_fo -> fo_hidden_base; if (!GC_is_marked(real_ptr)) { GC_set_mark_bit(real_ptr); } else { - if (prev_fo == 0) - GC_finalize_now = next_fo; - else + if (NULL == prev_fo) { + GC_fnlz_roots.finalize_now = next_fo; + } else { fo_set_next(prev_fo, next_fo); - + GC_dirty(prev_fo); + } curr_fo -> fo_hidden_base = GC_HIDE_POINTER(curr_fo -> fo_hidden_base); GC_bytes_finalized -= curr_fo->fo_object_size + sizeof(struct finalizable_object); i = HASH2(real_ptr, log_fo_table_size); - fo_set_next (curr_fo, GC_fo_head[i]); + fo_set_next(curr_fo, GC_fnlz_roots.fo_head[i]); + GC_dirty(curr_fo); GC_fo_entries++; - GC_fo_head[i] = curr_fo; + GC_fnlz_roots.fo_head[i] = curr_fo; curr_fo = prev_fo; + needs_barrier = TRUE; } } prev_fo = curr_fo; @@ -857,8 +1141,13 @@ GC_INNER void GC_finalize(void) } } } + if (needs_barrier) + GC_dirty(GC_fnlz_roots.fo_head); /* entire object */ GC_remove_dangling_disappearing_links(&GC_dl_hashtbl); +# ifndef GC_TOGGLE_REFS_NOT_NEEDED + GC_clear_togglerefs(); +# endif # ifndef GC_LONG_REFS_NOT_NEEDED GC_make_disappearing_links_disappear(&GC_ll_hashtbl); GC_remove_dangling_disappearing_links(&GC_ll_hashtbl); @@ -880,33 +1169,28 @@ GC_INNER void GC_finalize(void) /* Enqueue all remaining finalizers to be run - Assumes lock is held. */ STATIC void GC_enqueue_all_finalizers(void) { - struct finalizable_object * curr_fo, * prev_fo, * next_fo; - ptr_t real_ptr; - register int i; + struct finalizable_object * next_fo; + int i; int fo_size; fo_size = log_fo_table_size == -1 ? 0 : 1 << log_fo_table_size; GC_bytes_finalized = 0; for (i = 0; i < fo_size; i++) { - curr_fo = GC_fo_head[i]; - prev_fo = 0; - while (curr_fo != 0) { - real_ptr = GC_REVEAL_POINTER(curr_fo -> fo_hidden_base); + struct finalizable_object * curr_fo = GC_fnlz_roots.fo_head[i]; + + GC_fnlz_roots.fo_head[i] = NULL; + while (curr_fo != NULL) { + ptr_t real_ptr = (ptr_t)GC_REVEAL_POINTER(curr_fo->fo_hidden_base); + GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc); GC_set_mark_bit(real_ptr); - /* Delete from hash table */ next_fo = fo_next(curr_fo); - if (prev_fo == 0) { - GC_fo_head[i] = next_fo; - } else { - fo_set_next(prev_fo, next_fo); - } - GC_fo_entries--; /* Add to list of objects awaiting finalization. */ - fo_set_next(curr_fo, GC_finalize_now); - GC_finalize_now = curr_fo; + fo_set_next(curr_fo, GC_fnlz_roots.finalize_now); + GC_dirty(curr_fo); + GC_fnlz_roots.finalize_now = curr_fo; /* unhide object pointer so any future collections will */ /* see it. */ @@ -917,6 +1201,7 @@ GC_INNER void GC_finalize(void) curr_fo = next_fo; } } + GC_fo_entries = 0; /* all entries deleted from the hash table */ } /* Invoke all remaining finalizers that haven't yet been run. @@ -958,19 +1243,20 @@ GC_INNER void GC_finalize(void) /* getting into that safe state is expensive.) */ GC_API int GC_CALL GC_should_invoke_finalizers(void) { - return GC_finalize_now != 0; + return GC_fnlz_roots.finalize_now != NULL; } /* Invoke finalizers for all objects that are ready to be finalized. */ /* Should be called without allocation lock. */ GC_API int GC_CALL GC_invoke_finalizers(void) { - struct finalizable_object * curr_fo; int count = 0; word bytes_freed_before = 0; /* initialized to prevent warning. */ DCL_LOCK_STATE; - while (GC_finalize_now != 0) { + while (GC_fnlz_roots.finalize_now != NULL) { + struct finalizable_object * curr_fo; + # ifdef THREADS LOCK(); # endif @@ -978,25 +1264,22 @@ GC_API int GC_CALL GC_invoke_finalizers(void) bytes_freed_before = GC_bytes_freed; /* Don't do this outside, since we need the lock. */ } - curr_fo = GC_finalize_now; + curr_fo = GC_fnlz_roots.finalize_now; # ifdef THREADS - if (curr_fo != 0) GC_finalize_now = fo_next(curr_fo); + if (curr_fo != 0) GC_fnlz_roots.finalize_now = fo_next(curr_fo); UNLOCK(); if (curr_fo == 0) break; # else - GC_finalize_now = fo_next(curr_fo); + GC_fnlz_roots.finalize_now = fo_next(curr_fo); # endif fo_set_next(curr_fo, 0); (*(curr_fo -> fo_fn))((ptr_t)(curr_fo -> fo_hidden_base), curr_fo -> fo_client_data); curr_fo -> fo_client_data = 0; ++count; -# ifdef UNDEFINED - /* This is probably a bad idea. It throws off accounting if */ - /* nearly all objects are finalizable. O.w. it shouldn't */ - /* matter. */ - GC_free((void *)curr_fo); -# endif + /* Explicit freeing of curr_fo is probably a bad idea. */ + /* It throws off accounting if nearly all objects are */ + /* finalizable. Otherwise it should not matter. */ } /* bytes_freed_before is initialized whenever count != 0 */ if (count != 0 && bytes_freed_before != GC_bytes_freed) { @@ -1007,7 +1290,7 @@ GC_API int GC_CALL GC_invoke_finalizers(void) return count; } -static GC_word last_finalizer_notification = 0; +static word last_finalizer_notification = 0; GC_INNER void GC_notify_or_invoke_finalizers(void) { @@ -1020,7 +1303,7 @@ GC_INNER void GC_notify_or_invoke_finalizers(void) # if defined(THREADS) && !defined(KEEP_BACK_PTRS) \ && !defined(MAKE_BACK_GRAPH) /* Quick check (while unlocked) for an empty finalization queue. */ - if (GC_finalize_now == 0) return; + if (NULL == GC_fnlz_roots.finalize_now) return; # endif LOCK(); @@ -1045,14 +1328,12 @@ GC_INNER void GC_notify_or_invoke_finalizers(void) # endif # ifdef MAKE_BACK_GRAPH if (GC_print_back_height) { - UNLOCK(); GC_print_back_graph_stats(); - LOCK(); } # endif } # endif - if (GC_finalize_now == 0) { + if (NULL == GC_fnlz_roots.finalize_now) { UNLOCK(); return; } @@ -1065,7 +1346,7 @@ GC_INNER void GC_notify_or_invoke_finalizers(void) (void) GC_invoke_finalizers(); *pnested = 0; /* Reset since no more finalizers. */ # ifndef THREADS - GC_ASSERT(GC_finalize_now == 0); + GC_ASSERT(NULL == GC_fnlz_roots.finalize_now); # endif /* Otherwise GC can run concurrently and add more */ } return; @@ -1100,7 +1381,7 @@ GC_INNER void GC_notify_or_invoke_finalizers(void) (unsigned long)IF_LONG_REFS_PRESENT_ELSE( GC_ll_hashtbl.entries, 0)); - for (fo = GC_finalize_now; 0 != fo; fo = fo_next(fo)) + for (fo = GC_fnlz_roots.finalize_now; fo != NULL; fo = fo_next(fo)) ++ready; GC_log_printf("%lu finalization-ready objects;" " %ld/%ld short/long links cleared\n", diff --git a/src/bdwgc/fnlz_mlc.c b/src/bdwgc/fnlz_mlc.c index 4648ca967..ff7b28464 100644 --- a/src/bdwgc/fnlz_mlc.c +++ b/src/bdwgc/fnlz_mlc.c @@ -17,29 +17,32 @@ #ifdef ENABLE_DISCLAIM #include "gc_disclaim.h" - -#ifdef THREAD_LOCAL_ALLOC -# include "private/thread_local_alloc.h" -#else - STATIC ptr_t * GC_finalized_objfreelist = NULL; -#endif /* !THREAD_LOCAL_ALLOC */ +#include "gc_inline.h" /* for GC_malloc_kind */ STATIC int GC_finalized_kind = 0; +#if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) + /* The first bit is already used for a debug purpose. */ +# define FINALIZER_CLOSURE_FLAG 0x2 +#else +# define FINALIZER_CLOSURE_FLAG 0x1 +#endif + STATIC int GC_CALLBACK GC_finalized_disclaim(void *obj) { word fc_word = *(word *)obj; - if ((fc_word & 1) != 0) { + if ((fc_word & FINALIZER_CLOSURE_FLAG) != 0) { /* The disclaim function may be passed fragments from the */ /* free-list, on which it should not run finalization. */ /* To recognize this case, we use the fact that the first word */ - /* on such fragments are always even (a link to the next */ + /* on such fragments is always multiple of 4 (a link to the next */ /* fragment, or NULL). If it is desirable to have a finalizer */ /* which does not use the first word for storing finalization */ /* info, GC_reclaim_with_finalization must be extended to clear */ /* fragments so that the assumption holds for the selected word. */ - const struct GC_finalizer_closure *fc = (void *)(fc_word & ~(word)1); + const struct GC_finalizer_closure *fc + = (void *)(fc_word & ~(word)FINALIZER_CLOSURE_FLAG); (*fc->proc)((word *)obj + 1, fc->cd); } return 0; @@ -66,8 +69,7 @@ GC_API void GC_CALL GC_init_finalized_malloc(void) /* start of the user region. */ GC_register_displacement_inner(sizeof(word)); - GC_finalized_objfreelist = (ptr_t *)GC_new_free_list_inner(); - GC_finalized_kind = GC_new_kind_inner((void **)GC_finalized_objfreelist, + GC_finalized_kind = GC_new_kind_inner(GC_new_free_list_inner(), GC_DS_LENGTH, TRUE, TRUE); GC_register_disclaim_proc(GC_finalized_kind, GC_finalized_disclaim, TRUE); UNLOCK(); @@ -81,90 +83,17 @@ GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc, GC_obj_kinds[kind].ok_mark_unconditionally = (GC_bool)mark_unconditionally; } -#ifdef THREAD_LOCAL_ALLOC - STATIC void * GC_core_finalized_malloc(size_t lb, +GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t lb, const struct GC_finalizer_closure *fclos) -#else - GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t lb, - const struct GC_finalizer_closure *fclos) -#endif { - ptr_t op; - word lg; - DCL_LOCK_STATE; + word *op; - lb += sizeof(word); GC_ASSERT(done_init); - if (SMALL_OBJ(lb)) { - GC_DBG_COLLECT_AT_MALLOC(lb); - lg = GC_size_map[lb]; - LOCK(); - op = GC_finalized_objfreelist[lg]; - if (EXPECT(0 == op, FALSE)) { - UNLOCK(); - op = GC_generic_malloc(lb, GC_finalized_kind); - if (NULL == op) - return NULL; - /* GC_generic_malloc has extended the size map for us. */ - lg = GC_size_map[lb]; - } else { - GC_finalized_objfreelist[lg] = obj_link(op); - obj_link(op) = 0; - GC_bytes_allocd += GRANULES_TO_BYTES(lg); - UNLOCK(); - } - GC_ASSERT(lg > 0); - } else { - op = GC_generic_malloc(lb, GC_finalized_kind); - if (NULL == op) - return NULL; - GC_ASSERT(GC_size(op) >= lb); - } - *(word *)op = (word)fclos | 1; - return GC_clear_stack((word *)op + 1); + op = GC_malloc_kind(SIZET_SAT_ADD(lb, sizeof(word)), GC_finalized_kind); + if (EXPECT(NULL == op, FALSE)) + return NULL; + *op = (word)fclos | FINALIZER_CLOSURE_FLAG; + return op + 1; } -#ifdef THREAD_LOCAL_ALLOC - GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t client_lb, - const struct GC_finalizer_closure *fclos) - { - size_t lb = client_lb + sizeof(word); - size_t lg = ROUNDED_UP_GRANULES(lb); - GC_tlfs tsd; - void *result; - void **tiny_fl, **my_fl, *my_entry; - void *next; - - if (EXPECT(lg >= GC_TINY_FREELISTS, FALSE)) - return GC_core_finalized_malloc(client_lb, fclos); - - tsd = GC_getspecific(GC_thread_key); - tiny_fl = tsd->finalized_freelists; - my_fl = tiny_fl + lg; - my_entry = *my_fl; - while (EXPECT((word)my_entry - <= DIRECT_GRANULES + GC_TINY_FREELISTS + 1, FALSE)) { - if ((word)my_entry - 1 < DIRECT_GRANULES) { - *my_fl = (ptr_t)my_entry + lg + 1; - return GC_core_finalized_malloc(client_lb, fclos); - } else { - GC_generic_malloc_many(GC_RAW_BYTES_FROM_INDEX(lg), - GC_finalized_kind, my_fl); - my_entry = *my_fl; - if (my_entry == 0) { - return (*GC_get_oom_fn())(lb); - } - } - } - - next = obj_link(my_entry); - result = (void *)my_entry; - *my_fl = next; - obj_link(result) = 0; - *(word *)result = (word)fclos | 1; - PREFETCH_FOR_WRITE(next); - return (word *)result + 1; - } -#endif /* THREAD_LOCAL_ALLOC */ - #endif /* ENABLE_DISCLAIM */ diff --git a/src/bdwgc/gc.mak b/src/bdwgc/gc.mak index 9f92d381d..c0d142a8d 100644 --- a/src/bdwgc/gc.mak +++ b/src/bdwgc/gc.mak @@ -7,7 +7,7 @@ !IF "$(CFG)" == "" CFG=gctest - Win32 Release -!MESSAGE No configuration specified. Defaulting to cord - Win32 Debug. +!MESSAGE No configuration specified. Defaulting to gctest - Win32 Release. !ENDIF !IF "$(CFG)" != "gc - Win32 Release" && "$(CFG)" != "gc - Win32 Debug" &&\ @@ -110,8 +110,9 @@ CLEAN : -@erase ".\Release\typd_mlc.sbr" -@erase ".\Release\win32_threads.obj" -@erase ".\Release\win32_threads.sbr" - -@erase ".\Release\msvc_dbg.obj" - -@erase ".\Release\msvc_dbg.sbr" + -@erase ".\Release\msvc_dbg.copied.obj" + -@erase ".\Release\msvc_dbg.copied.sbr" + -@erase ".\msvc_dbg.copied.c" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" @@ -119,10 +120,10 @@ CLEAN : CPP=cl.exe # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c # ADD CPP /nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "GC_THREADS" /FR /YX /c -CPP_PROJ=/nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D\ - "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "GC_THREADS" \ - /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" \ - /I./libatomic_ops/src /YX /Fo"$(INTDIR)/" /c +CPP_PROJ=/nologo /MD /W3 /EHsc /O2 /I include /D "NDEBUG" /D "WIN32"\ + /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "GC_THREADS" /D "_CRT_SECURE_NO_DEPRECATE"\ + /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch"\ + /I./libatomic_ops/src /Fo"$(INTDIR)/" /c CPP_OBJS=.\Release/ CPP_SBRS=.\Release/ @@ -155,31 +156,31 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo BSC32_FLAGS=/nologo /o"$(OUTDIR)/gc.bsc" -BSC32_SBRS= \ - ".\Release\allchblk.sbr" \ - ".\Release\alloc.sbr" \ - ".\Release\blacklst.sbr" \ - ".\Release\checksums.sbr" \ - ".\Release\dbg_mlc.sbr" \ - ".\Release\dyn_load.sbr" \ - ".\Release\finalize.sbr" \ - ".\Release\fnlz_mlc.sbr" \ - ".\Release\gc_cpp.sbr" \ - ".\Release\headers.sbr" \ - ".\Release\mach_dep.sbr" \ - ".\Release\malloc.sbr" \ - ".\Release\mallocx.sbr" \ - ".\Release\mark.sbr" \ - ".\Release\mark_rts.sbr" \ - ".\Release\misc.sbr" \ - ".\Release\new_hblk.sbr" \ - ".\Release\obj_map.sbr" \ - ".\Release\os_dep.sbr" \ - ".\Release\ptr_chck.sbr" \ - ".\Release\reclaim.sbr" \ - ".\Release\stubborn.sbr" \ - ".\Release\typd_mlc.sbr" \ - ".\Release\msvc_dbg.sbr" \ +BSC32_SBRS=\ + ".\Release\allchblk.sbr"\ + ".\Release\alloc.sbr"\ + ".\Release\blacklst.sbr"\ + ".\Release\checksums.sbr"\ + ".\Release\dbg_mlc.sbr"\ + ".\Release\dyn_load.sbr"\ + ".\Release\finalize.sbr"\ + ".\Release\fnlz_mlc.sbr"\ + ".\Release\gc_cpp.sbr"\ + ".\Release\headers.sbr"\ + ".\Release\mach_dep.sbr"\ + ".\Release\malloc.sbr"\ + ".\Release\mallocx.sbr"\ + ".\Release\mark.sbr"\ + ".\Release\mark_rts.sbr"\ + ".\Release\misc.sbr"\ + ".\Release\new_hblk.sbr"\ + ".\Release\obj_map.sbr"\ + ".\Release\os_dep.sbr"\ + ".\Release\ptr_chck.sbr"\ + ".\Release\reclaim.sbr"\ + ".\Release\stubborn.sbr"\ + ".\Release\typd_mlc.sbr"\ + ".\Release\msvc_dbg.copied.sbr"\ ".\Release\win32_threads.sbr" ".\Release\gc.bsc" : "$(OUTDIR)" $(BSC32_SBRS) @@ -195,31 +196,31 @@ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\ /pdb:"$(OUTDIR)/gc.pdb" /machine:I386 /out:"$(OUTDIR)/gc.dll"\ /implib:"$(OUTDIR)/gc.lib" -LINK32_OBJS= \ - ".\Release\allchblk.obj" \ - ".\Release\alloc.obj" \ - ".\Release\blacklst.obj" \ - ".\Release\checksums.obj" \ - ".\Release\dbg_mlc.obj" \ - ".\Release\dyn_load.obj" \ - ".\Release\finalize.obj" \ - ".\Release\fnlz_mlc.obj" \ - ".\Release\gc_cpp.obj" \ - ".\Release\headers.obj" \ - ".\Release\mach_dep.obj" \ - ".\Release\malloc.obj" \ - ".\Release\mallocx.obj" \ - ".\Release\mark.obj" \ - ".\Release\mark_rts.obj" \ - ".\Release\misc.obj" \ - ".\Release\new_hblk.obj" \ - ".\Release\obj_map.obj" \ - ".\Release\os_dep.obj" \ - ".\Release\ptr_chck.obj" \ - ".\Release\reclaim.obj" \ - ".\Release\stubborn.obj" \ - ".\Release\typd_mlc.obj" \ - ".\Release\msvc_dbg.obj" \ +LINK32_OBJS=\ + ".\Release\allchblk.obj"\ + ".\Release\alloc.obj"\ + ".\Release\blacklst.obj"\ + ".\Release\checksums.obj"\ + ".\Release\dbg_mlc.obj"\ + ".\Release\dyn_load.obj"\ + ".\Release\finalize.obj"\ + ".\Release\fnlz_mlc.obj"\ + ".\Release\gc_cpp.obj"\ + ".\Release\headers.obj"\ + ".\Release\mach_dep.obj"\ + ".\Release\malloc.obj"\ + ".\Release\mallocx.obj"\ + ".\Release\mark.obj"\ + ".\Release\mark_rts.obj"\ + ".\Release\misc.obj"\ + ".\Release\new_hblk.obj"\ + ".\Release\obj_map.obj"\ + ".\Release\os_dep.obj"\ + ".\Release\ptr_chck.obj"\ + ".\Release\reclaim.obj"\ + ".\Release\stubborn.obj"\ + ".\Release\typd_mlc.obj"\ + ".\Release\msvc_dbg.copied.obj"\ ".\Release\win32_threads.obj" ".\Release\gc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) @@ -301,8 +302,9 @@ CLEAN : -@erase ".\Debug\vc40.pdb" -@erase ".\Debug\win32_threads.obj" -@erase ".\Debug\win32_threads.sbr" - -@erase ".\Debug\msvc_dbg.obj" - -@erase ".\Debug\msvc_dbg.sbr" + -@erase ".\Debug\msvc_dbg.copied.obj" + -@erase ".\Debug\msvc_dbg.copied.sbr" + -@erase ".\msvc_dbg.copied.c" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" @@ -310,10 +312,10 @@ CLEAN : CPP=cl.exe # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c # ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "GC_THREADS" /FR /YX /c -CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG"\ - /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" \ - /D "GC_ASSERTIONS" /D "GC_THREADS" \ - /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" /YX /Fo"$(INTDIR)/"\ +CPP_PROJ=/nologo /MDd /W3 /Gm /EHsc /Zi /Od /I include /D "_DEBUG"\ + /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS"\ + /D "GC_ASSERTIONS" /D "GC_THREADS" /D "_CRT_SECURE_NO_DEPRECATE"\ + /FR"$(INTDIR)/" /Fp"$(INTDIR)/gc.pch" /Fo"$(INTDIR)/"\ /I./libatomic_ops/src /Fd"$(INTDIR)/" /c CPP_OBJS=.\Debug/ CPP_SBRS=.\Debug/ @@ -347,31 +349,31 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo BSC32_FLAGS=/nologo /o"$(OUTDIR)/gc.bsc" -BSC32_SBRS= \ - ".\Debug\allchblk.sbr" \ - ".\Debug\alloc.sbr" \ - ".\Debug\blacklst.sbr" \ - ".\Debug\checksums.sbr" \ - ".\Debug\dbg_mlc.sbr" \ - ".\Debug\dyn_load.sbr" \ - ".\Debug\finalize.sbr" \ - ".\Debug\fnlz_mlc.sbr" \ - ".\Debug\gc_cpp.sbr" \ - ".\Debug\headers.sbr" \ - ".\Debug\mach_dep.sbr" \ - ".\Debug\malloc.sbr" \ - ".\Debug\mallocx.sbr" \ - ".\Debug\mark.sbr" \ - ".\Debug\mark_rts.sbr" \ - ".\Debug\misc.sbr" \ - ".\Debug\new_hblk.sbr" \ - ".\Debug\obj_map.sbr" \ - ".\Debug\os_dep.sbr" \ - ".\Debug\ptr_chck.sbr" \ - ".\Debug\reclaim.sbr" \ - ".\Debug\stubborn.sbr" \ - ".\Debug\typd_mlc.sbr" \ - ".\Debug\msvc_dbg.sbr" \ +BSC32_SBRS=\ + ".\Debug\allchblk.sbr"\ + ".\Debug\alloc.sbr"\ + ".\Debug\blacklst.sbr"\ + ".\Debug\checksums.sbr"\ + ".\Debug\dbg_mlc.sbr"\ + ".\Debug\dyn_load.sbr"\ + ".\Debug\finalize.sbr"\ + ".\Debug\fnlz_mlc.sbr"\ + ".\Debug\gc_cpp.sbr"\ + ".\Debug\headers.sbr"\ + ".\Debug\mach_dep.sbr"\ + ".\Debug\malloc.sbr"\ + ".\Debug\mallocx.sbr"\ + ".\Debug\mark.sbr"\ + ".\Debug\mark_rts.sbr"\ + ".\Debug\misc.sbr"\ + ".\Debug\new_hblk.sbr"\ + ".\Debug\obj_map.sbr"\ + ".\Debug\os_dep.sbr"\ + ".\Debug\ptr_chck.sbr"\ + ".\Debug\reclaim.sbr"\ + ".\Debug\stubborn.sbr"\ + ".\Debug\typd_mlc.sbr"\ + ".\Debug\msvc_dbg.copied.sbr"\ ".\Debug\win32_threads.sbr" ".\Debug\gc.bsc" : "$(OUTDIR)" $(BSC32_SBRS) @@ -387,31 +389,31 @@ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ odbccp32.lib /nologo /subsystem:windows /dll /incremental:no\ /pdb:"$(OUTDIR)/gc.pdb" /map:"$(INTDIR)/gc.map" /debug /machine:I386\ /out:"$(OUTDIR)/gc.dll" /implib:"$(OUTDIR)/gc.lib" -LINK32_OBJS= \ - ".\Debug\allchblk.obj" \ - ".\Debug\alloc.obj" \ - ".\Debug\blacklst.obj" \ - ".\Debug\checksums.obj" \ - ".\Debug\dbg_mlc.obj" \ - ".\Debug\dyn_load.obj" \ - ".\Debug\finalize.obj" \ - ".\Debug\fnlz_mlc.obj" \ - ".\Debug\gc_cpp.obj" \ - ".\Debug\headers.obj" \ - ".\Debug\mach_dep.obj" \ - ".\Debug\malloc.obj" \ - ".\Debug\mallocx.obj" \ - ".\Debug\mark.obj" \ - ".\Debug\mark_rts.obj" \ - ".\Debug\misc.obj" \ - ".\Debug\new_hblk.obj" \ - ".\Debug\obj_map.obj" \ - ".\Debug\os_dep.obj" \ - ".\Debug\ptr_chck.obj" \ - ".\Debug\reclaim.obj" \ - ".\Debug\stubborn.obj" \ - ".\Debug\typd_mlc.obj" \ - ".\Debug\msvc_dbg.obj" \ +LINK32_OBJS=\ + ".\Debug\allchblk.obj"\ + ".\Debug\alloc.obj"\ + ".\Debug\blacklst.obj"\ + ".\Debug\checksums.obj"\ + ".\Debug\dbg_mlc.obj"\ + ".\Debug\dyn_load.obj"\ + ".\Debug\finalize.obj"\ + ".\Debug\fnlz_mlc.obj"\ + ".\Debug\gc_cpp.obj"\ + ".\Debug\headers.obj"\ + ".\Debug\mach_dep.obj"\ + ".\Debug\malloc.obj"\ + ".\Debug\mallocx.obj"\ + ".\Debug\mark.obj"\ + ".\Debug\mark_rts.obj"\ + ".\Debug\misc.obj"\ + ".\Debug\new_hblk.obj"\ + ".\Debug\obj_map.obj"\ + ".\Debug\os_dep.obj"\ + ".\Debug\ptr_chck.obj"\ + ".\Debug\reclaim.obj"\ + ".\Debug\stubborn.obj"\ + ".\Debug\typd_mlc.obj"\ + ".\Debug\msvc_dbg.copied.obj"\ ".\Debug\win32_threads.obj" ".\Debug\gc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) @@ -437,22 +439,23 @@ INTDIR=.\gctest\Release ALL : "gc - Win32 Release" ".\Release\gctest.exe" CLEAN : - -@erase ".\gctest\Release\test.obj" + -@erase ".\gctest\Release\test.copied.obj" + -@erase ".\test.copied.c" -@erase ".\Release\gctest.exe" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" -test.c : tests\test.c - copy tests\test.c test.c +test.copied.c : tests\test.c + copy tests\test.c test.copied.c CPP=cl.exe # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c # ADD CPP /nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "GC_THREADS" /YX /c -CPP_PROJ=/nologo /MD /W3 /GX /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\ - "ALL_INTERIOR_POINTERS" /D "GC_THREADS" \ - /I./libatomic_ops/src /Fp"$(INTDIR)/gctest.pch" \ - /YX /Fo"$(INTDIR)/" /c +CPP_PROJ=/nologo /MD /W3 /EHsc /O2 /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS"\ + /D "ALL_INTERIOR_POINTERS" /D "GC_THREADS" /D "_CRT_SECURE_NO_DEPRECATE"\ + /I./libatomic_ops/src /Fp"$(INTDIR)/gctest.pch"\ + /Fo"$(INTDIR)/" /c CPP_OBJS=.\gctest\Release/ CPP_SBRS=.\. @@ -485,7 +488,7 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo BSC32_FLAGS=/nologo /o"$(OUTDIR)/gctest.bsc" -BSC32_SBRS= \ +BSC32_SBRS=\ LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 @@ -494,8 +497,8 @@ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ odbccp32.lib /nologo /subsystem:windows /incremental:no\ /pdb:"$(OUTDIR)/gctest.pdb" /machine:I386 /out:"Release/gctest.exe" -LINK32_OBJS= \ - ".\gctest\Release\test.obj" \ +LINK32_OBJS=\ + ".\gctest\Release\test.copied.obj"\ ".\Release\gc.lib" ".\Release\gctest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) @@ -525,8 +528,9 @@ CLEAN : -@erase ".\gctest\Debug\gctest.bsc" -@erase ".\gctest\Debug\gctest.map" -@erase ".\gctest\Debug\gctest.pdb" - -@erase ".\gctest\Debug\test.obj" - -@erase ".\gctest\Debug\test.sbr" + -@erase ".\gctest\Debug\test.copied.obj" + -@erase ".\gctest\Debug\test.copied.sbr" + -@erase ".\test.copied.c" -@erase ".\gctest\Debug\vc40.idb" -@erase ".\gctest\Debug\vc40.pdb" @@ -536,9 +540,9 @@ CLEAN : CPP=cl.exe # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c # ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /D "GC_THREADS" /FR /YX /c -CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I include /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\ - /D "ALL_INTERIOR_POINTERS" /D "GC_THREADS" /FR"$(INTDIR)/"\ - /I./libatomic_ops/src /Fp"$(INTDIR)/gctest.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_PROJ=/nologo /MDd /W3 /Gm /EHsc /Zi /Od /I include /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\ + /D "ALL_INTERIOR_POINTERS" /D "GC_THREADS" /D "_CRT_SECURE_NO_DEPRECATE" /FR"$(INTDIR)/"\ + /I./libatomic_ops/src /Fp"$(INTDIR)/gctest.pch" /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c CPP_OBJS=.\gctest\Debug/ CPP_SBRS=.\gctest\Debug/ @@ -571,8 +575,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo BSC32_FLAGS=/nologo /o"$(OUTDIR)/gctest.bsc" -BSC32_SBRS= \ - ".\gctest\Debug\test.sbr" +BSC32_SBRS=\ + ".\gctest\Debug\test.copied.sbr" ".\gctest\Debug\gctest.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< @@ -587,9 +591,9 @@ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ odbccp32.lib /nologo /subsystem:windows /incremental:no\ /pdb:"$(OUTDIR)/gctest.pdb" /map:"$(INTDIR)/gctest.map" /debug /machine:I386\ /out:"Debug/gctest.exe" -LINK32_OBJS= \ - ".\Debug\gc.lib" \ - ".\gctest\Debug\test.obj" +LINK32_OBJS=\ + ".\Debug\gc.lib"\ + ".\gctest\Debug\test.copied.obj" ".\Debug\gctest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< @@ -627,8 +631,8 @@ CLEAN : CPP=cl.exe # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /YX /c -CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "." /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\ - /I./libatomic_ops/src "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX /Fo"$(INTDIR)/" /c +CPP_PROJ=/nologo /MD /W3 /EHsc /O2 /I "." /I include /D "NDEBUG" /D "WIN32" /D "_WINDOWS"\ + /D "ALL_INTERIOR_POINTERS" /I./libatomic_ops/src /Fp"$(INTDIR)/cord.pch" /Fo"$(INTDIR)/" /c CPP_OBJS=.\cord\Release/ CPP_SBRS=.\. @@ -662,7 +666,7 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo BSC32_FLAGS=/nologo /o"$(OUTDIR)/cord.bsc" -BSC32_SBRS= \ +BSC32_SBRS=\ LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 @@ -671,12 +675,12 @@ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ odbccp32.lib /nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)/de.pdb"\ /machine:I386 /out:"Release/de.exe" -LINK32_OBJS= \ - ".\cord\Release\cordbscs.obj" \ - ".\cord\Release\cordxtra.obj" \ - ".\cord\Release\de.obj" \ - ".\cord\Release\de_win.obj" \ - ".\cord\Release\de_win.res" \ +LINK32_OBJS=\ + ".\cord\Release\cordbscs.obj"\ + ".\cord\Release\cordxtra.obj"\ + ".\cord\Release\de.obj"\ + ".\cord\Release\de_win.obj"\ + ".\cord\Release\de_win.res"\ ".\Release\gc.lib" ".\Release\de.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) @@ -719,8 +723,8 @@ CLEAN : CPP=cl.exe # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c # ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /YX /c -CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "." /I include /D "_DEBUG" /D "WIN32" /D\ - "_WINDOWS" /D "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch" /YX\ +CPP_PROJ=/nologo /MDd /W3 /Gm /EHsc /Zi /Od /I "." /I include /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\ + /D "ALL_INTERIOR_POINTERS" /Fp"$(INTDIR)/cord.pch"\ /I./libatomic_ops/src /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c CPP_OBJS=.\cord\Debug/ CPP_SBRS=.\. @@ -755,7 +759,7 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo BSC32_FLAGS=/nologo /o"$(OUTDIR)/cord.bsc" -BSC32_SBRS= \ +BSC32_SBRS=\ LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 @@ -764,12 +768,12 @@ LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ odbccp32.lib /nologo /subsystem:windows /incremental:yes\ /pdb:"$(OUTDIR)/de.pdb" /debug /machine:I386 /out:"Debug/de.exe" -LINK32_OBJS= \ - ".\cord\Debug\cordbscs.obj" \ - ".\cord\Debug\cordxtra.obj" \ - ".\cord\Debug\de.obj" \ - ".\cord\Debug\de_win.obj" \ - ".\cord\Debug\de_win.res" \ +LINK32_OBJS=\ + ".\cord\Debug\cordbscs.obj"\ + ".\cord\Debug\cordxtra.obj"\ + ".\cord\Debug\de.obj"\ + ".\cord\Debug\de_win.obj"\ + ".\cord\Debug\de_win.res"\ ".\Debug\gc.lib" ".\Debug\de.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) @@ -1945,6 +1949,9 @@ NODEP_CPP_WIN32=\ SOURCE=.\extra\msvc_dbg.c +msvc_dbg.copied.c : extra\msvc_dbg.c + copy extra\msvc_dbg.c msvc_dbg.copied.c + !IF "$(CFG)" == "gc - Win32 Release" DEP_CPP_WIN32=\ @@ -1961,9 +1968,9 @@ NODEP_CPP_WIN32=\ ".\th\PCR_ThCtl.h"\ -".\Release\msvc_dbg.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)" +".\Release\msvc_dbg.copied.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)" -".\Release\msvc_dbg.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)" +".\Release\msvc_dbg.copied.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)" !ELSEIF "$(CFG)" == "gc - Win32 Debug" @@ -1982,9 +1989,9 @@ NODEP_CPP_WIN32=\ ".\th\PCR_ThCtl.h"\ -".\Debug\msvc_dbg.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)" +".\Debug\msvc_dbg.copied.obj" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)" -".\Debug\msvc_dbg.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)" +".\Debug\msvc_dbg.copied.sbr" : $(SOURCE) $(DEP_CPP_WIN32) "$(INTDIR)" !ENDIF @@ -2090,15 +2097,15 @@ NODEP_CPP_TEST_=\ !IF "$(CFG)" == "gctest - Win32 Release" -".\gctest\Release\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)" +".\gctest\Release\test.copied.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)" !ELSEIF "$(CFG)" == "gctest - Win32 Debug" -".\gctest\Debug\test.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)" +".\gctest\Debug\test.copied.obj" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)" -".\gctest\Debug\test.sbr" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)" +".\gctest\Debug\test.copied.sbr" : $(SOURCE) $(DEP_CPP_TEST_) "$(INTDIR)" !ENDIF diff --git a/src/bdwgc/gc_cpp.cc b/src/bdwgc/gc_cpp.cc index 0f6c9d2b1..1dc11a47a 100644 --- a/src/bdwgc/gc_cpp.cc +++ b/src/bdwgc/gc_cpp.cc @@ -27,62 +27,73 @@ built-in "new" and "delete". # define GC_BUILD #endif -#include "gc_cpp.h" +#include "gc.h" -#if !defined(GC_NEW_DELETE_NEED_THROW) && defined(__GNUC__) \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) -# define GC_NEW_DELETE_NEED_THROW +#include // for bad_alloc, precedes include of gc_cpp.h + +#include "gc_cpp.h" // for GC_OPERATOR_NEW_ARRAY, GC_DECL_DELETE_THROW + +#if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS) +# define GC_ALLOCATOR_THROW_OR_ABORT() GC_abort_on_oom() +#else +# define GC_ALLOCATOR_THROW_OR_ABORT() throw std::bad_alloc() #endif -#ifdef GC_NEW_DELETE_NEED_THROW -# include /* for std::bad_alloc */ -# define GC_DECL_NEW_THROW throw(std::bad_alloc) -# define GC_DECL_DELETE_THROW throw() -#else -# define GC_DECL_NEW_THROW /* empty */ -# define GC_DECL_DELETE_THROW /* empty */ -#endif /* !GC_NEW_DELETE_NEED_THROW */ - -void* operator new( size_t size ) GC_DECL_NEW_THROW { - return GC_MALLOC_UNCOLLECTABLE(size); +GC_API void GC_CALL GC_throw_bad_alloc() { + GC_ALLOCATOR_THROW_OR_ABORT(); } -#if !defined(__CYGWIN__) - void operator delete( void* obj ) GC_DECL_DELETE_THROW { - GC_FREE(obj); - } -#endif /* !__CYGWIN__ */ +#if !defined(_MSC_VER) && !defined(__DMC__) -#ifdef GC_OPERATOR_NEW_ARRAY - void* operator new[]( size_t size ) GC_DECL_NEW_THROW { - return GC_MALLOC_UNCOLLECTABLE(size); - } - - void operator delete[]( void* obj ) GC_DECL_DELETE_THROW { - GC_FREE(obj); - } -#endif /* GC_OPERATOR_NEW_ARRAY */ - -#ifdef _MSC_VER - - // This new operator is used by VC++ in case of Debug builds! - void* operator new( size_t size, int /* nBlockUse */, - const char * szFileName, int nLine ) GC_DECL_NEW_THROW - { -# ifndef GC_DEBUG - return GC_malloc_uncollectable(size); -# else - return GC_debug_malloc_uncollectable(size, szFileName, nLine); -# endif - } - -# if _MSC_VER > 1020 - // This new operator is used by VC++ 7.0 and later in Debug builds. - void* operator new[]( size_t size, int nBlockUse, - const char* szFileName, int nLine ) GC_DECL_NEW_THROW - { - return operator new(size, nBlockUse, szFileName, nLine); - } +# if !defined(GC_NEW_DELETE_THROW_NOT_NEEDED) \ + && !defined(GC_NEW_DELETE_NEED_THROW) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) \ + && (__cplusplus < 201103L || defined(__clang__)) +# define GC_NEW_DELETE_NEED_THROW # endif -#endif /* _MSC_VER */ +# ifdef GC_NEW_DELETE_NEED_THROW +# define GC_DECL_NEW_THROW throw(std::bad_alloc) +# else +# define GC_DECL_NEW_THROW /* empty */ +# endif + + void* operator new(size_t size) GC_DECL_NEW_THROW { + void* obj = GC_MALLOC_UNCOLLECTABLE(size); + if (0 == obj) + GC_ALLOCATOR_THROW_OR_ABORT(); + return obj; + } + + void operator delete(void* obj) GC_DECL_DELETE_THROW { + GC_FREE(obj); + } + +# if defined(GC_OPERATOR_NEW_ARRAY) && !defined(CPPCHECK) + void* operator new[](size_t size) GC_DECL_NEW_THROW { + void* obj = GC_MALLOC_UNCOLLECTABLE(size); + if (0 == obj) + GC_ALLOCATOR_THROW_OR_ABORT(); + return obj; + } + + void operator delete[](void* obj) GC_DECL_DELETE_THROW { + GC_FREE(obj); + } +# endif // GC_OPERATOR_NEW_ARRAY + +# if __cplusplus > 201103L // C++14 + void operator delete(void* obj, size_t size) GC_DECL_DELETE_THROW { + (void)size; // size is ignored + GC_FREE(obj); + } + +# if defined(GC_OPERATOR_NEW_ARRAY) && !defined(CPPCHECK) + void operator delete[](void* obj, size_t size) GC_DECL_DELETE_THROW { + (void)size; + GC_FREE(obj); + } +# endif +# endif // C++14 + +#endif // !_MSC_VER diff --git a/src/bdwgc/gcj_mlc.c b/src/bdwgc/gcj_mlc.c index 195a215ae..b37d0b354 100644 --- a/src/bdwgc/gcj_mlc.c +++ b/src/bdwgc/gcj_mlc.c @@ -54,8 +54,6 @@ int GC_gcj_debug_kind = 0; GC_INNER ptr_t * GC_gcjobjfreelist = NULL; -STATIC ptr_t * GC_gcjdebugobjfreelist = NULL; - STATIC struct GC_ms_entry * GC_gcj_fake_mark_proc(word * addr GC_ATTR_UNUSED, struct GC_ms_entry *mark_stack_ptr, struct GC_ms_entry * mark_stack_limit GC_ATTR_UNUSED, @@ -69,7 +67,9 @@ STATIC struct GC_ms_entry * GC_gcj_fake_mark_proc(word * addr GC_ATTR_UNUSED, GC_API void GC_CALL GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp) { - GC_bool ignore_gcj_info; +# ifndef GC_IGNORE_GCJ_INFO + GC_bool ignore_gcj_info; +# endif DCL_LOCK_STATE; if (mp == 0) /* In case GC_DS_PROC is unused. */ @@ -84,7 +84,7 @@ GC_API void GC_CALL GC_init_gcj_malloc(int mp_index, GC_gcj_malloc_initialized = TRUE; # ifdef GC_IGNORE_GCJ_INFO /* This is useful for debugging on platforms with missing getenv(). */ - ignore_gcj_info = 1; +# define ignore_gcj_info TRUE # else ignore_gcj_info = (0 != GETENV("GC_IGNORE_GCJ_INFO")); # endif @@ -101,7 +101,7 @@ GC_API void GC_CALL GC_init_gcj_malloc(int mp_index, /* Use a simple length-based descriptor, thus forcing a fully */ /* conservative scan. */ GC_gcj_kind = GC_new_kind_inner((void **)GC_gcjobjfreelist, - (0 | GC_DS_LENGTH), + /* 0 | */ GC_DS_LENGTH, TRUE, TRUE); } else { GC_gcj_kind = GC_new_kind_inner( @@ -114,16 +114,14 @@ GC_API void GC_CALL GC_init_gcj_malloc(int mp_index, /* Set up object kind for objects that require mark proc call. */ if (ignore_gcj_info) { GC_gcj_debug_kind = GC_gcj_kind; - GC_gcjdebugobjfreelist = GC_gcjobjfreelist; } else { - GC_gcjdebugobjfreelist = (ptr_t *)GC_new_free_list_inner(); - GC_gcj_debug_kind = GC_new_kind_inner( - (void **)GC_gcjdebugobjfreelist, + GC_gcj_debug_kind = GC_new_kind_inner(GC_new_free_list_inner(), GC_MAKE_PROC(mp_index, 1 /* allocated with debug info */), FALSE, TRUE); } UNLOCK(); +# undef ignore_gcj_info } #define GENERAL_MALLOC_INNER(lb,k) \ @@ -164,12 +162,12 @@ static void maybe_finalize(void) #endif { ptr_t op; - word lg; DCL_LOCK_STATE; GC_DBG_COLLECT_AT_MALLOC(lb); if(SMALL_OBJ(lb)) { - lg = GC_size_map[lb]; + word lg = GC_size_map[lb]; + LOCK(); op = GC_gcjobjfreelist[lg]; if(EXPECT(0 == op, FALSE)) { @@ -182,11 +180,9 @@ static void maybe_finalize(void) } } else { GC_gcjobjfreelist[lg] = obj_link(op); - GC_bytes_allocd += GRANULES_TO_BYTES(lg); + GC_bytes_allocd += GRANULES_TO_BYTES((word)lg); } - *(void **)op = ptr_to_struct_containing_descr; GC_ASSERT(((void **)op)[1] == 0); - UNLOCK(); } else { LOCK(); maybe_finalize(); @@ -196,10 +192,12 @@ static void maybe_finalize(void) UNLOCK(); return((*oom_fn)(lb)); } - *(void **)op = ptr_to_struct_containing_descr; - UNLOCK(); } - return((void *) op); + *(void **)op = ptr_to_struct_containing_descr; + UNLOCK(); + GC_dirty(op); + REACHABLE_AFTER_DIRTY(ptr_to_struct_containing_descr); + return (void *)op; } /* Similar to GC_gcj_malloc, but add debug info. This is allocated */ @@ -214,7 +212,8 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_gcj_malloc(size_t lb, /* confuse the backtrace. */ LOCK(); maybe_finalize(); - result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind); + result = GC_generic_malloc_inner(SIZET_SAT_ADD(lb, DEBUG_BYTES), + GC_gcj_debug_kind); if (result == 0) { GC_oom_func oom_fn = GC_oom_fn; UNLOCK(); @@ -223,12 +222,15 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_gcj_malloc(size_t lb, return((*oom_fn)(lb)); } *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr; - UNLOCK(); if (!GC_debugging_started) { - GC_start_debugging(); + GC_start_debugging_inner(); } ADD_CALL_CHAIN(result, ra); - return (GC_store_debug_info(result, (word)lb, s, i)); + result = GC_store_debug_info_inner(result, (word)lb, s, i); + UNLOCK(); + GC_dirty(result); + REACHABLE_AFTER_DIRTY(ptr_to_struct_containing_descr); + return result; } /* There is no THREAD_LOCAL_ALLOC for GC_gcj_malloc_ignore_off_page(). */ @@ -236,12 +238,12 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_gcj_malloc_ignore_off_page(size_t lb, void * ptr_to_struct_containing_descr) { ptr_t op; - word lg; DCL_LOCK_STATE; GC_DBG_COLLECT_AT_MALLOC(lb); if(SMALL_OBJ(lb)) { - lg = GC_size_map[lb]; + word lg = GC_size_map[lb]; + LOCK(); op = GC_gcjobjfreelist[lg]; if (EXPECT(0 == op, FALSE)) { @@ -254,7 +256,7 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_gcj_malloc_ignore_off_page(size_t lb, } } else { GC_gcjobjfreelist[lg] = obj_link(op); - GC_bytes_allocd += GRANULES_TO_BYTES(lg); + GC_bytes_allocd += GRANULES_TO_BYTES((word)lg); } } else { LOCK(); @@ -268,7 +270,9 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_gcj_malloc_ignore_off_page(size_t lb, } *(void **)op = ptr_to_struct_containing_descr; UNLOCK(); - return((void *) op); + GC_dirty(op); + REACHABLE_AFTER_DIRTY(ptr_to_struct_containing_descr); + return (void *)op; } #endif /* GC_GCJ_SUPPORT */ diff --git a/src/bdwgc/headers.c b/src/bdwgc/headers.c index 057d989fd..0c258de79 100644 --- a/src/bdwgc/headers.c +++ b/src/bdwgc/headers.c @@ -118,7 +118,7 @@ static ptr_t scratch_free_ptr = 0; GC_INNER ptr_t GC_scratch_alloc(size_t bytes) { ptr_t result = scratch_free_ptr; - word bytes_to_get; + size_t bytes_to_get; bytes = ROUNDUP_GRANULE_SIZE(bytes); for (;;) { @@ -170,7 +170,7 @@ static hdr * alloc_hdr(void) register hdr * result; if (hdr_free_list == 0) { - result = (hdr *) GC_scratch_alloc((word)(sizeof(hdr))); + result = (hdr *)GC_scratch_alloc(sizeof(hdr)); } else { result = hdr_free_list; hdr_free_list = (hdr *) (result -> hb_next); @@ -194,7 +194,7 @@ GC_INNER void GC_init_headers(void) { register unsigned i; - GC_all_nils = (bottom_index *)GC_scratch_alloc((word)sizeof(bottom_index)); + GC_all_nils = (bottom_index *)GC_scratch_alloc(sizeof(bottom_index)); if (GC_all_nils == NULL) { GC_err_printf("Insufficient memory for GC_all_nils\n"); EXIT(); @@ -224,14 +224,14 @@ static GC_bool get_index(word addr) if (p -> key == hi) return(TRUE); p = p -> hash_link; } - r = (bottom_index*)GC_scratch_alloc((word)(sizeof (bottom_index))); + r = (bottom_index *)GC_scratch_alloc(sizeof(bottom_index)); if (r == 0) return(FALSE); BZERO(r, sizeof (bottom_index)); r -> hash_link = old; GC_top_index[i] = r; # else if (GC_top_index[hi] != GC_all_nils) return(TRUE); - r = (bottom_index*)GC_scratch_alloc((word)(sizeof (bottom_index))); + r = (bottom_index *)GC_scratch_alloc(sizeof(bottom_index)); if (r == 0) return(FALSE); GC_top_index[hi] = r; BZERO(r, sizeof (bottom_index)); @@ -277,14 +277,14 @@ GC_INNER struct hblkhdr * GC_install_header(struct hblk *h) GC_INNER GC_bool GC_install_counts(struct hblk *h, size_t sz/* bytes */) { struct hblk * hbp; - word i; for (hbp = h; (word)hbp < (word)h + sz; hbp += BOTTOM_SZ) { if (!get_index((word) hbp)) return(FALSE); } if (!get_index((word)h + sz - 1)) return(FALSE); for (hbp = h + 1; (word)hbp < (word)h + sz; hbp += 1) { - i = HBLK_PTR_DIFF(hbp, h); + word i = HBLK_PTR_DIFF(hbp, h); + SET_HDR(hbp, (hdr *)(i > MAX_JUMP? MAX_JUMP : i)); } return(TRUE); diff --git a/src/bdwgc/include/config.h.in b/src/bdwgc/include/config.h.in index 0b6d3c837..305bb1496 100644 --- a/src/bdwgc/include/config.h.in +++ b/src/bdwgc/include/config.h.in @@ -3,9 +3,6 @@ /* Define to recognise all pointers to the interior of objects. */ #undef ALL_INTERIOR_POINTERS -/* Define to enable atomic uncollectible allocation. */ -#undef ATOMIC_UNCOLLECTABLE - /* See doc/README.macros. */ #undef DARWIN_DONT_PARSE_STACK @@ -30,6 +27,9 @@ /* Define to enable internal debug assertions. */ #undef GC_ASSERTIONS +/* Define to enable atomic uncollectible allocation. */ +#undef GC_ATOMIC_UNCOLLECTABLE + /* Define to support Darwin pthreads. */ #undef GC_DARWIN_THREADS @@ -39,6 +39,9 @@ /* Define to build dynamic libraries with only API symbols exposed. */ #undef GC_DLL +/* Define to turn on GC_suspend_thread support. */ +#undef GC_ENABLE_SUSPEND_THREAD + /* Define to support FreeBSD pthreads. */ #undef GC_FREEBSD_THREADS @@ -48,6 +51,9 @@ /* Define to support GNU pthreads. */ #undef GC_GNU_THREADS +/* Define to support Haiku pthreads. */ +#undef GC_HAIKU_THREADS + /* Define if backtrace information is supported. */ #undef GC_HAVE_BUILTIN_BACKTRACE @@ -63,6 +69,9 @@ /* Define to support pthreads on Linux. */ #undef GC_LINUX_THREADS +/* Missing execinfo.h header. */ +#undef GC_MISSING_EXECINFO_H + /* Define to support NetBSD pthreads. */ #undef GC_NETBSD_THREADS @@ -93,6 +102,15 @@ /* See doc/README.macros. */ #undef GC_USE_DLOPEN_WRAP +/* The major version number of this GC release. */ +#undef GC_VERSION_MAJOR + +/* The micro version number of this GC release. */ +#undef GC_VERSION_MICRO + +/* The minor version number of this GC release. */ +#undef GC_VERSION_MINOR + /* Define to support pthreads-win32 or winpthreads. */ #undef GC_WIN32_PTHREADS @@ -108,6 +126,15 @@ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H +/* Define if 'dl_iterate_phdr' function is available. */ +#undef HAVE_DL_ITERATE_PHDR + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if you have the `getcontext' function. */ +#undef HAVE_GETCONTEXT + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H @@ -162,6 +189,9 @@ /* Define to make the collector not allocate executable memory by default. */ #undef NO_EXECUTE_PERMISSION +/* Missing getcontext function. */ +#undef NO_GETCONTEXT + /* Prohibit installation of pthread_atfork() handlers. */ #undef NO_HANDLE_FORK diff --git a/src/bdwgc/include/cord.h b/src/bdwgc/include/cord.h index d3d555b6b..adac772b9 100644 --- a/src/bdwgc/include/cord.h +++ b/src/bdwgc/include/cord.h @@ -58,7 +58,7 @@ #include #include -#ifdef GC_DLL +#if defined(GC_DLL) && !defined(CORD_NOT_DLL) /* Same as for GC_API in gc_config_macros.h. */ # ifdef CORD_BUILD # if defined(__MINGW32__) || defined(__CEGCC__) @@ -66,8 +66,8 @@ # elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \ || defined(__CYGWIN__) || defined(__WATCOMC__) # define CORD_API extern __declspec(dllexport) -# elif defined(__GNUC__) && (__GNUC__ >= 4 \ - || defined(GC_VISIBILITY_HIDDEN_SET)) +# elif defined(__GNUC__) && !defined(GC_NO_VISIBILITY) \ + && (__GNUC__ >= 4 || defined(GC_VISIBILITY_HIDDEN_SET)) /* Only matters if used in conjunction with -fvisibility=hidden option. */ # define CORD_API extern __attribute__((__visibility__("default"))) # endif diff --git a/src/bdwgc/include/ec.h b/src/bdwgc/include/ec.h index 30806ed2f..160fc81a9 100644 --- a/src/bdwgc/include/ec.h +++ b/src/bdwgc/include/ec.h @@ -43,7 +43,7 @@ typedef struct CORD_ec_struct { /* This structure represents the concatenation of ec_cord with */ /* ec_buf[0 ... (ec_bufptr-ec_buf-1)] */ -/* Flush the buffer part of the extended chord into ec_cord. */ +/* Flush the buffer part of the extended cord into ec_cord. */ /* Note that this is almost the only real function, and it is */ /* implemented in 6 lines in cordxtra.c */ void CORD_ec_flush_buf(CORD_ec x); diff --git a/src/bdwgc/include/gc.h b/src/bdwgc/include/gc.h index f1051c974..690b4a08c 100644 --- a/src/bdwgc/include/gc.h +++ b/src/bdwgc/include/gc.h @@ -5,6 +5,7 @@ * Copyright 1999 by Hewlett-Packard Company. All rights reserved. * Copyright (C) 2007 Free Software Foundation, Inc * Copyright (c) 2000-2011 by Hewlett-Packard Development Company. + * Copyright (c) 2009-2018 Ivan Maidanski * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -31,6 +32,11 @@ #ifndef GC_H #define GC_H +/* Help debug mixed up preprocessor symbols. */ +#if (defined(WIN64) && !defined(_WIN64)) && defined(_MSC_VER) +#pragma message("Warning: Expecting _WIN64 for x64 targets! Notice the leading underscore!") +#endif + #include "gc_version.h" /* Define version numbers here to allow test on build machine */ /* for cross-builds. Note that this defines the header */ @@ -54,7 +60,7 @@ typedef void * GC_PTR; /* preserved only for backward compatibility */ /* better choices. But those had incorrect definitions on some older */ /* systems. Notably "typedef int size_t" is WRONG. */ #ifdef _WIN64 -# ifdef __int64 +# if defined(__int64) && !defined(CPPCHECK) typedef unsigned __int64 GC_word; typedef __int64 GC_signed_word; # else @@ -129,10 +135,50 @@ GC_API GC_on_heap_resize_proc GC_CALL GC_get_on_heap_resize(void); /* Both the supplied setter and the getter */ /* acquire the GC lock (to avoid data races). */ +typedef enum { + GC_EVENT_START /* COLLECTION */, + GC_EVENT_MARK_START, + GC_EVENT_MARK_END, + GC_EVENT_RECLAIM_START, + GC_EVENT_RECLAIM_END, + GC_EVENT_END /* COLLECTION */, + GC_EVENT_PRE_STOP_WORLD /* STOPWORLD_BEGIN */, + GC_EVENT_POST_STOP_WORLD /* STOPWORLD_END */, + GC_EVENT_PRE_START_WORLD /* STARTWORLD_BEGIN */, + GC_EVENT_POST_START_WORLD /* STARTWORLD_END */, + GC_EVENT_THREAD_SUSPENDED, + GC_EVENT_THREAD_UNSUSPENDED +} GC_EventType; + +typedef void (GC_CALLBACK * GC_on_collection_event_proc)(GC_EventType); + /* Invoked to indicate progress through the */ + /* collection process. Not used for thread */ + /* suspend/resume notifications. Called with */ + /* the GC lock held (or, even, the world */ + /* stopped). May be 0 (means no notifier). */ +GC_API void GC_CALL GC_set_on_collection_event(GC_on_collection_event_proc); +GC_API GC_on_collection_event_proc GC_CALL GC_get_on_collection_event(void); + /* Both the supplied setter and the getter */ + /* acquire the GC lock (to avoid data races). */ + +#ifdef GC_THREADS + typedef void (GC_CALLBACK * GC_on_thread_event_proc)(GC_EventType, + void * /* thread_id */); + /* Invoked when a thread is suspended or */ + /* resumed during collection. Called with the */ + /* GC lock held (and the world stopped */ + /* partially). May be 0 (means no notifier). */ + GC_API void GC_CALL GC_set_on_thread_event(GC_on_thread_event_proc); + GC_API GC_on_thread_event_proc GC_CALL GC_get_on_thread_event(void); + /* Both the supplied setter and the getter */ + /* acquire the GC lock (to avoid data races). */ +#endif + GC_API GC_ATTR_DEPRECATED int GC_find_leak; - /* Do not actually garbage collect, but simply */ + /* Set to true to turn on the leak-finding mode */ + /* (do not actually garbage collect, but simply */ /* report inaccessible memory that was not */ - /* deallocated with GC_free. Initial value */ + /* deallocated with GC_FREE). Initial value */ /* is determined by FIND_LEAK macro. */ /* The value should not typically be modified */ /* after GC initialization (and, thus, it does */ @@ -274,7 +320,7 @@ GC_API GC_ATTR_DEPRECATED GC_word GC_free_space_divisor; /* bytes (bytes in "atomic" objects), plus */ /* a rough estimate of the root set size. */ /* N approximates GC tracing work per GC. */ - /* Initially, GC_free_space_divisor = 3. */ + /* The initial value is GC_FREE_SPACE_DIVISOR. */ /* Increasing its value will use less space */ /* but more collection time. Decreasing it */ /* will appreciably decrease collection time */ @@ -283,6 +329,8 @@ GC_API GC_ATTR_DEPRECATED GC_word GC_free_space_divisor; /* GC_call_with_alloc_lock() is required to */ /* avoid data races (if the value is modified */ /* after the GC is put to multi-threaded mode). */ + /* In version 7.1 (and before), the setter */ + /* returned the old value. */ GC_API void GC_CALL GC_set_free_space_divisor(GC_word); GC_API GC_word GC_CALL GC_get_free_space_divisor(void); @@ -395,6 +443,10 @@ GC_API void GC_CALL GC_atfork_child(void); /* from the main program instead. */ GC_API void GC_CALL GC_init(void); +/* Returns non-zero (TRUE) if and only if the collector is initialized */ +/* (or, at least, the initialization is in progress). */ +GC_API int GC_CALL GC_is_init_called(void); + /* General purpose allocation routines, with roughly malloc calling */ /* conv. The atomic versions promise that no relevant pointers are */ /* contained in the object. The non-atomic versions guarantee that the */ @@ -482,7 +534,20 @@ GC_API size_t GC_CALL GC_size(const void * /* obj_addr */) GC_ATTR_NONNULL(1); /* The resulting object has the same kind as the original. */ /* If the argument is stubborn, the result will have changes enabled. */ /* It is an error to have changes enabled for the original object. */ -/* Follows ANSI conventions for NULL old_object. */ +/* It does not change the content of the object from its beginning to */ +/* the minimum of old size and new_size_in_bytes; the content above in */ +/* case of object size growth is initialized to zero (not guaranteed */ +/* for atomic object type). The function follows ANSI conventions for */ +/* NULL old_object (i.e., equivalent to GC_malloc regardless of new */ +/* size). If new size is zero (and old_object is non-NULL) then the */ +/* call is equivalent to GC_free (and NULL is returned). If old_object */ +/* is non-NULL, it must have been returned by an earlier call to */ +/* GC_malloc* or GC_realloc. In case of the allocation failure, the */ +/* memory pointed by old_object is untouched (and not freed). */ +/* If the returned pointer is not the same as old_object and both of */ +/* them are non-NULL then old_object is freed. Returns either NULL (in */ +/* case of the allocation failure or zero new size) or pointer to the */ +/* allocated memory. */ GC_API void * GC_CALL GC_realloc(void * /* old_object */, size_t /* new_size_in_bytes */) /* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2); @@ -585,7 +650,7 @@ GC_API GC_stop_func GC_CALL GC_get_stop_func(void); /* This getter remains lock-free (unsynchronized) for compatibility */ /* reason since some existing clients call it from a GC callback */ /* holding the allocator lock. (This API function and the following */ -/* four ones bellow were made thread-safe in GC v7.2alpha1 and */ +/* four ones below were made thread-safe in GC v7.2alpha1 and */ /* reverted back in v7.2alpha7 for the reason described.) */ GC_API size_t GC_CALL GC_get_heap_size(void); @@ -680,6 +745,10 @@ GC_API size_t GC_CALL GC_get_prof_stats(struct GC_prof_stats_s *, size_t /* stats_sz */); #endif +/* Count total memory use in bytes by all allocated blocks. Acquires */ +/* the lock. */ +GC_API size_t GC_CALL GC_get_memory_use(void); + /* Disable garbage collection. Even GC_gcollect calls will be */ /* ineffective. */ GC_API void GC_CALL GC_disable(void); @@ -708,7 +777,7 @@ GC_API void GC_CALL GC_enable_incremental(void); /* Does incremental mode write-protect pages? Returns zero or */ /* more of the following, or'ed together: */ -#define GC_PROTECTS_POINTER_HEAP 1 /* May protect non-atomic objs. */ +#define GC_PROTECTS_POINTER_HEAP 1 /* May protect non-atomic objects. */ #define GC_PROTECTS_PTRFREE_HEAP 2 #define GC_PROTECTS_STATIC_DATA 4 /* Currently never. */ #define GC_PROTECTS_STACK 8 /* Probably impractical. */ @@ -718,7 +787,8 @@ GC_API void GC_CALL GC_enable_incremental(void); GC_API int GC_CALL GC_incremental_protection_needs(void); /* Perform some garbage collection work, if appropriate. */ -/* Return 0 if there is no more work to be done. */ +/* Return 0 if there is no more work to be done (including the */ +/* case when garbage collection is not appropriate). */ /* Typically performs an amount of work corresponding roughly */ /* to marking from one page. May do more work if further */ /* progress requires it, e.g. if incremental collection is */ @@ -933,6 +1003,7 @@ GC_API void GC_CALL GC_debug_register_finalizer(void * /* obj */, /* be avoided, or broken by disappearing links. */ /* All but the last finalizer registered for an object */ /* is ignored. */ + /* No-op in the leak-finding mode. */ /* Finalization may be removed by passing 0 as fn. */ /* Finalizers are implicitly unregistered when they are */ /* enqueued for finalization (i.e. become ready to be */ @@ -1070,6 +1141,7 @@ GC_API int GC_CALL GC_general_register_disappearing_link(void ** /* link */, /* explicitly deallocate the object containing link. */ /* Explicit deallocation of obj may or may not cause */ /* link to eventually be cleared. */ + /* No-op in the leak-finding mode. */ /* This function can be used to implement certain types */ /* of weak pointers. Note, however, this generally */ /* requires that the allocation lock is held (see */ @@ -1081,7 +1153,8 @@ GC_API int GC_CALL GC_general_register_disappearing_link(void ** /* link */, /* succeeded (a new link is registered), GC_DUPLICATE */ /* if link was already registered (with some object), */ /* GC_NO_MEMORY if registration failed for lack of */ - /* memory (and GC_oom_fn did not handle the problem). */ + /* memory (and GC_oom_fn did not handle the problem), */ + /* GC_UNIMPLEMENTED if GC_find_leak is true. */ GC_API int GC_CALL GC_move_disappearing_link(void ** /* link */, void ** /* new_link */) @@ -1124,7 +1197,54 @@ GC_API int GC_CALL GC_unregister_long_link(void ** /* link */); /* Similar to GC_unregister_disappearing_link but for a */ /* registration by either of the above two routines. */ +/* Support of toggle-ref style of external memory management */ +/* without hooking up to the host retain/release machinery. */ +/* The idea of toggle-ref is that an external reference to */ +/* an object is kept and it can be either a strong or weak */ +/* reference; a weak reference is used when the external peer */ +/* has no interest in the object, and a strong otherwise. */ +typedef enum { + GC_TOGGLE_REF_DROP, + GC_TOGGLE_REF_STRONG, + GC_TOGGLE_REF_WEAK +} GC_ToggleRefStatus; + +/* The callback is to decide (return) the new state of a given */ +/* object. Invoked by the collector for all objects registered */ +/* for toggle-ref processing. Invoked with the allocation lock */ +/* held (but the "world" is running). */ +typedef GC_ToggleRefStatus (GC_CALLBACK *GC_toggleref_func)(void * /* obj */); + +/* Set (register) a callback that decides the state of a given */ +/* object (by, probably, inspecting its native state). */ +/* The argument may be 0 (means no callback). Both the setter */ +/* and the getter acquire the allocation lock (to avoid data */ +/* races). */ +GC_API void GC_CALL GC_set_toggleref_func(GC_toggleref_func); +GC_API GC_toggleref_func GC_CALL GC_get_toggleref_func(void); + +/* Register a given object for toggle-ref processing. It will */ +/* be stored internally and the toggle-ref callback will be */ +/* invoked on the object until the callback returns */ +/* GC_TOGGLE_REF_DROP or the object is collected. If is_strong */ +/* is true then the object is registered with a strong ref, */ +/* a weak one otherwise. Returns GC_SUCCESS if registration */ +/* succeeded (or no callback registered yet), GC_NO_MEMORY if */ +/* it failed for lack of memory. */ +GC_API int GC_CALL GC_toggleref_add(void * /* obj */, int /* is_strong */) + GC_ATTR_NONNULL(1); + +/* Finalizer callback support. Invoked by the collector (with */ +/* the allocation lock held) for each unreachable object */ +/* enqueued for finalization. */ +typedef void (GC_CALLBACK * GC_await_finalize_proc)(void * /* obj */); +GC_API void GC_CALL GC_set_await_finalize_proc(GC_await_finalize_proc); +GC_API GC_await_finalize_proc GC_CALL GC_get_await_finalize_proc(void); + /* Zero means no callback. The setter */ + /* and getter acquire the lock too. */ + /* Returns !=0 if GC_invoke_finalizers has something to do. */ +/* Does not use any synchronization. */ GC_API int GC_CALL GC_should_invoke_finalizers(void); GC_API int GC_CALL GC_invoke_finalizers(void); @@ -1155,7 +1275,8 @@ GC_API int GC_CALL GC_invoke_finalizers(void); /* GC_set_warn_proc can be used to redirect or filter warning messages. */ /* p may not be a NULL pointer. msg is printf format string (arg must */ /* match the format). Both the setter and the getter acquire the GC */ -/* lock (to avoid data races). */ +/* lock (to avoid data races). In version 7.1 (and before), the setter */ +/* returned the old warn_proc value. */ typedef void (GC_CALLBACK * GC_warn_proc)(char * /* msg */, GC_word /* arg */); GC_API void GC_CALL GC_set_warn_proc(GC_warn_proc /* p */) GC_ATTR_NONNULL(1); @@ -1180,6 +1301,9 @@ typedef void (GC_CALLBACK * GC_abort_func)(const char * /* msg */); GC_API void GC_CALL GC_set_abort_func(GC_abort_func) GC_ATTR_NONNULL(1); GC_API GC_abort_func GC_CALL GC_get_abort_func(void); +/* A portable way to abort the application because of not enough memory.*/ +GC_API void GC_CALL GC_abort_on_oom(void); + /* The following is intended to be used by a higher level */ /* (e.g. Java-like) finalization facility. It is expected */ /* that finalization code will arrange for hidden pointers to */ @@ -1303,6 +1427,7 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */, /* latter case, the explicit call is normally required for threads */ /* created by third-party libraries. */ /* A manually registered thread requires manual unregistering. */ + /* Returns GC_SUCCESS on success, GC_DUPLICATE if already registered. */ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *) GC_ATTR_NONNULL(1); @@ -1310,6 +1435,14 @@ GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func /* fn */, /* registered with the garbage collector. */ GC_API int GC_CALL GC_thread_is_registered(void); + /* Notify the collector about the stack and the alt-stack of the */ + /* current thread. stack_start/size is used to determine the stack */ + /* boundaries when a thread is suspended while it is on an alt-stack. */ + GC_API void GC_CALL GC_register_altstack(void * /* stack_start */, + GC_word /* stack_size */, + void * /* altstack_base */, + GC_word /* altstack_size */); + /* Unregister the current thread. Only an explicitly registered */ /* thread (i.e. for which GC_register_my_thread() returns GC_SUCCESS) */ /* is allowed (and required) to call this function. (As a special */ @@ -1402,6 +1535,15 @@ GC_API void * GC_CALL GC_is_valid_displacement(void * /* p */); /* Defined only if the library has been compiled without NO_DEBUGGING. */ GC_API void GC_CALL GC_dump(void); +/* Dump information about each block of every GC memory section. */ +/* Defined only if the library has been compiled without NO_DEBUGGING. */ +GC_API void GC_CALL GC_dump_regions(void); + +/* Dump information about every registered disappearing link and */ +/* finalizable object. */ +/* Defined only if the library has been compiled without NO_DEBUGGING. */ +GC_API void GC_CALL GC_dump_finalization(void); + /* Safer, but slow, pointer addition. Probably useful mainly with */ /* a preprocessor. Useful only for heap pointers. */ /* Only the macros without trailing digits are meant to be used */ @@ -1417,10 +1559,10 @@ GC_API void GC_CALL GC_dump(void); ((type_of_result)GC_pre_incr((void **)(&(x)), (n)*sizeof(*x))) # define GC_POST_INCR3(x, n, type_of_result) \ ((type_of_result)GC_post_incr((void **)(&(x)), (n)*sizeof(*x))) -# define GC_PTR_ADD(x, n) GC_PTR_ADD3(x, n, typeof(x)) -# define GC_PRE_INCR(x, n) GC_PRE_INCR3(x, n, typeof(x)) -# define GC_POST_INCR(x) GC_POST_INCR3(x, 1, typeof(x)) -# define GC_POST_DECR(x) GC_POST_INCR3(x, -1, typeof(x)) +# define GC_PTR_ADD(x, n) GC_PTR_ADD3(x, n, __typeof__(x)) +# define GC_PRE_INCR(x, n) GC_PRE_INCR3(x, n, __typeof__(x)) +# define GC_POST_INCR(x) GC_POST_INCR3(x, 1, __typeof__(x)) +# define GC_POST_DECR(x) GC_POST_INCR3(x, -1, __typeof__(x)) #else /* !GC_DEBUG || !__GNUC__ */ /* We can't do this right without typeof, which ANSI decided was not */ /* sufficiently useful. Without it we resort to the non-debug version. */ @@ -1478,8 +1620,14 @@ typedef int (GC_CALLBACK * GC_has_static_roots_func)( GC_API void GC_CALL GC_register_has_static_roots_callback( GC_has_static_roots_func); +#if !defined(CPPCHECK) && !defined(GC_WINDOWS_H_INCLUDED) && defined(WINAPI) + /* windows.h is included before gc.h */ +# define GC_WINDOWS_H_INCLUDED +#endif + #if defined(GC_WIN32_THREADS) \ - && (!defined(GC_PTHREADS) || defined(GC_BUILD) || defined(WINAPI)) + && (!defined(GC_PTHREADS) || defined(GC_BUILD) \ + || defined(GC_WINDOWS_H_INCLUDED)) /* Note: for Cygwin and pthreads-win32, this is skipped */ /* unless windows.h is included before gc.h. */ @@ -1493,7 +1641,10 @@ GC_API void GC_CALL GC_register_has_static_roots_callback( # include /* For _beginthreadex, _endthreadex */ # endif -# include +# if defined(GC_BUILD) || !defined(GC_DONT_INCLUDE_WINDOWS_H) +# include +# define GC_WINDOWS_H_INCLUDED +# endif # ifdef __cplusplus extern "C" { @@ -1506,14 +1657,14 @@ GC_API void GC_CALL GC_register_has_static_roots_callback( # define GC_ExitThread _GC_ExitThread # endif -# ifdef GC_INSIDE_DLL - /* Export GC DllMain to be invoked from client DllMain. */ -# ifdef GC_UNDERSCORE_STDCALL -# define GC_DllMain _GC_DllMain +# ifndef DECLSPEC_NORETURN + /* Typically defined in winnt.h. */ +# ifdef GC_WINDOWS_H_INCLUDED +# define DECLSPEC_NORETURN /* empty */ +# else +# define DECLSPEC_NORETURN __declspec(noreturn) # endif - GC_API BOOL WINAPI GC_DllMain(HINSTANCE /* inst */, ULONG /* reason */, - LPVOID /* reserved */); -# endif /* GC_INSIDE_DLL */ +# endif # if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED) \ && !defined(UINTPTR_MAX) @@ -1521,7 +1672,28 @@ GC_API void GC_CALL GC_register_has_static_roots_callback( # else typedef uintptr_t GC_uintptr_t; # endif -# define GC_WIN32_SIZE_T GC_uintptr_t + +# ifdef _WIN64 +# define GC_WIN32_SIZE_T GC_uintptr_t +# elif defined(GC_WINDOWS_H_INCLUDED) +# define GC_WIN32_SIZE_T DWORD +# else +# define GC_WIN32_SIZE_T unsigned long +# endif + +# ifdef GC_INSIDE_DLL + /* Export GC DllMain to be invoked from client DllMain. */ +# ifdef GC_UNDERSCORE_STDCALL +# define GC_DllMain _GC_DllMain +# endif +# ifdef GC_WINDOWS_H_INCLUDED + GC_API BOOL WINAPI GC_DllMain(HINSTANCE /* inst */, + ULONG /* reason */, + LPVOID /* reserved */); +# else + GC_API int __stdcall GC_DllMain(void *, unsigned long, void *); +# endif +# endif /* GC_INSIDE_DLL */ /* All threads must be created using GC_CreateThread or */ /* GC_beginthreadex, or must explicitly call GC_register_my_thread */ @@ -1533,20 +1705,24 @@ GC_API void GC_CALL GC_register_has_static_roots_callback( /* Currently the collector expects all threads to fall through and */ /* terminate normally, or call GC_endthreadex() or GC_ExitThread, */ /* so that the thread is properly unregistered. */ - GC_API HANDLE WINAPI GC_CreateThread( +# ifdef GC_WINDOWS_H_INCLUDED + GC_API HANDLE WINAPI GC_CreateThread( LPSECURITY_ATTRIBUTES /* lpThreadAttributes */, GC_WIN32_SIZE_T /* dwStackSize */, LPTHREAD_START_ROUTINE /* lpStartAddress */, LPVOID /* lpParameter */, DWORD /* dwCreationFlags */, LPDWORD /* lpThreadId */); -# ifndef DECLSPEC_NORETURN - /* Typically defined in winnt.h. */ -# define DECLSPEC_NORETURN /* empty */ -# endif - - GC_API DECLSPEC_NORETURN void WINAPI GC_ExitThread( + GC_API DECLSPEC_NORETURN void WINAPI GC_ExitThread( DWORD /* dwExitCode */); +# else + struct _SECURITY_ATTRIBUTES; + GC_API void *__stdcall GC_CreateThread(struct _SECURITY_ATTRIBUTES *, + GC_WIN32_SIZE_T, + unsigned long (__stdcall *)(void *), + void *, unsigned long, unsigned long *); + GC_API DECLSPEC_NORETURN void __stdcall GC_ExitThread(unsigned long); +# endif # if !defined(_WIN32_WCE) && !defined(__CEGCC__) GC_API GC_uintptr_t GC_CALL GC_beginthreadex( @@ -1603,11 +1779,21 @@ GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void); #if defined(__CYGWIN32__) || defined(__CYGWIN__) /* Similarly gnu-win32 DLLs need explicit initialization from the */ /* main program, as does AIX. */ - extern int _data_start__[], _data_end__[], _bss_start__[], _bss_end__[]; -# define GC_DATASTART ((GC_word)_data_start__ < (GC_word)_bss_start__ ? \ - (void *)_data_start__ : (void *)_bss_start__) -# define GC_DATAEND ((GC_word)_data_end__ > (GC_word)_bss_end__ ? \ - (void *)_data_end__ : (void *)_bss_end__) +# ifdef __x86_64__ + /* Cygwin/x64 does not add leading underscore to symbols anymore. */ + extern int __data_start__[], __data_end__[]; + extern int __bss_start__[], __bss_end__[]; +# define GC_DATASTART ((GC_word)__data_start__ < (GC_word)__bss_start__ \ + ? (void *)__data_start__ : (void *)__bss_start__) +# define GC_DATAEND ((GC_word)__data_end__ > (GC_word)__bss_end__ \ + ? (void *)__data_end__ : (void *)__bss_end__) +# else + extern int _data_start__[], _data_end__[], _bss_start__[], _bss_end__[]; +# define GC_DATASTART ((GC_word)_data_start__ < (GC_word)_bss_start__ \ + ? (void *)_data_start__ : (void *)_bss_start__) +# define GC_DATAEND ((GC_word)_data_end__ > (GC_word)_bss_end__ \ + ? (void *)_data_end__ : (void *)_bss_end__) +# endif /* !__x86_64__ */ # define GC_INIT_CONF_ROOTS GC_add_roots(GC_DATASTART, GC_DATAEND); \ GC_gcollect() /* For blacklisting. */ /* Required at least if GC is in a DLL. And doesn't hurt. */ @@ -1618,23 +1804,29 @@ GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void); # define GC_INIT_CONF_ROOTS GC_add_roots(GC_DATASTART, GC_DATAEND) #elif (defined(PLATFORM_ANDROID) || defined(__ANDROID__)) \ && !defined(GC_NOT_DLL) -# pragma weak __data_start - extern int __data_start[], _end[]; # pragma weak _etext +# pragma weak __data_start # pragma weak __dso_handle - extern int _etext[], __dso_handle[]; - /* Explicitly register caller static data roots (__data_start points */ - /* to the beginning typically but NDK "gold" linker could provide it */ - /* incorrectly, so the workaround is to check the value and use */ - /* __dso_handle as an alternative data start reference if provided). */ - /* It also works for Android/x86 target where __data_start is not */ - /* defined currently (regardless of linker used). */ + extern int _etext[], __data_start[], __dso_handle[]; +# pragma weak __end__ + extern int __end__[], _end[]; + /* Explicitly register caller static data roots. Workaround for */ + /* __data_start: NDK "gold" linker might miss it or place it */ + /* incorrectly, __dso_handle is an alternative data start reference. */ + /* Workaround for _end: NDK Clang 3.5+ does not place it at correct */ + /* offset (as of NDK r10e) but "bfd" linker provides __end__ symbol */ + /* that could be used instead. */ # define GC_INIT_CONF_ROOTS \ (void)((GC_word)__data_start < (GC_word)_etext \ - && (GC_word)_etext < (GC_word)__dso_handle ? \ - (GC_add_roots(__dso_handle, _end), 0) : \ - (GC_word)__data_start != 0 ? \ - (GC_add_roots(__data_start, _end), 0) : 0) + && (GC_word)_etext < (GC_word)__dso_handle \ + ? (__end__ != 0 \ + ? (GC_add_roots(__dso_handle, __end__), 0) \ + : (GC_word)__dso_handle < (GC_word)_end \ + ? (GC_add_roots(__dso_handle, _end), 0) : 0) \ + : __data_start != 0 ? (__end__ != 0 \ + ? (GC_add_roots(__data_start, __end__), 0) \ + : (GC_word)__data_start < (GC_word)_end \ + ? (GC_add_roots(__data_start, _end), 0) : 0) : 0) #else # define GC_INIT_CONF_ROOTS /* empty */ #endif @@ -1658,14 +1850,14 @@ GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void); /* This is for debugging only (useful if environment variables are */ /* unsupported); cannot call GC_disable as goes before GC_init. */ # define GC_INIT_CONF_MAX_RETRIES (void)(GC_dont_gc = 1) -#elif defined(GC_MAX_RETRIES) +#elif defined(GC_MAX_RETRIES) && !defined(CPPCHECK) /* Set GC_max_retries to the desired value at start-up */ # define GC_INIT_CONF_MAX_RETRIES GC_set_max_retries(GC_MAX_RETRIES) #else # define GC_INIT_CONF_MAX_RETRIES /* empty */ #endif -#ifdef GC_FREE_SPACE_DIVISOR +#if defined(GC_FREE_SPACE_DIVISOR) && !defined(CPPCHECK) /* Set GC_free_space_divisor to the desired value at start-up */ # define GC_INIT_CONF_FREE_SPACE_DIVISOR \ GC_set_free_space_divisor(GC_FREE_SPACE_DIVISOR) @@ -1673,34 +1865,34 @@ GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void); # define GC_INIT_CONF_FREE_SPACE_DIVISOR /* empty */ #endif -#ifdef GC_FULL_FREQ +#if defined(GC_FULL_FREQ) && !defined(CPPCHECK) /* Set GC_full_freq to the desired value at start-up */ # define GC_INIT_CONF_FULL_FREQ GC_set_full_freq(GC_FULL_FREQ) #else # define GC_INIT_CONF_FULL_FREQ /* empty */ #endif -#ifdef GC_TIME_LIMIT +#if defined(GC_TIME_LIMIT) && !defined(CPPCHECK) /* Set GC_time_limit to the desired value at start-up */ # define GC_INIT_CONF_TIME_LIMIT GC_set_time_limit(GC_TIME_LIMIT) #else # define GC_INIT_CONF_TIME_LIMIT /* empty */ #endif -#if defined(GC_SIG_SUSPEND) && defined(GC_THREADS) +#if defined(GC_SIG_SUSPEND) && defined(GC_THREADS) && !defined(CPPCHECK) # define GC_INIT_CONF_SUSPEND_SIGNAL GC_set_suspend_signal(GC_SIG_SUSPEND) #else # define GC_INIT_CONF_SUSPEND_SIGNAL /* empty */ #endif -#if defined(GC_SIG_THR_RESTART) && defined(GC_THREADS) +#if defined(GC_SIG_THR_RESTART) && defined(GC_THREADS) && !defined(CPPCHECK) # define GC_INIT_CONF_THR_RESTART_SIGNAL \ GC_set_thr_restart_signal(GC_SIG_THR_RESTART) #else # define GC_INIT_CONF_THR_RESTART_SIGNAL /* empty */ #endif -#ifdef GC_MAXIMUM_HEAP_SIZE +#if defined(GC_MAXIMUM_HEAP_SIZE) && !defined(CPPCHECK) /* Limit the heap size to the desired value (useful for debugging). */ /* The limit could be overridden either at the program start-up by */ /* the similar environment variable or anytime later by the */ @@ -1718,7 +1910,7 @@ GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void); # define GC_INIT_CONF_IGNORE_WARN /* empty */ #endif -#ifdef GC_INITIAL_HEAP_SIZE +#if defined(GC_INITIAL_HEAP_SIZE) && !defined(CPPCHECK) /* Set heap size to the desired value at start-up */ # define GC_INIT_CONF_INITIAL_HEAP_SIZE \ { size_t heap_size = GC_get_heap_size(); \ diff --git a/src/bdwgc/include/gc_allocator.h b/src/bdwgc/include/gc_allocator.h index 367cfe24f..6aa866443 100644 --- a/src/bdwgc/include/gc_allocator.h +++ b/src/bdwgc/include/gc_allocator.h @@ -38,16 +38,23 @@ */ #ifndef GC_ALLOCATOR_H - #define GC_ALLOCATOR_H #include "gc.h" -#include // for placement new +#include // for placement new and bad_alloc -#if defined(__GNUC__) -# define GC_ATTR_UNUSED __attribute__((__unused__)) +#ifndef GC_ATTR_EXPLICIT +# if (__cplusplus >= 201103L) || defined(CPPCHECK) +# define GC_ATTR_EXPLICIT explicit +# else +# define GC_ATTR_EXPLICIT /* empty */ +# endif +#endif + +#if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS) +# define GC_ALLOCATOR_THROW_OR_ABORT() GC_abort_on_oom() #else -# define GC_ATTR_UNUSED +# define GC_ALLOCATOR_THROW_OR_ABORT() throw std::bad_alloc() #endif /* First some helpers to allow us to dispatch on whether or not a type @@ -85,15 +92,24 @@ GC_DECLARE_PTRFREE(long double); // pointer-free object. template inline void * GC_selective_alloc(size_t n, GC_Tp, bool ignore_off_page) { - return ignore_off_page?GC_MALLOC_IGNORE_OFF_PAGE(n):GC_MALLOC(n); + void *obj = ignore_off_page ? GC_MALLOC_IGNORE_OFF_PAGE(n) : GC_MALLOC(n); + if (0 == obj) + GC_ALLOCATOR_THROW_OR_ABORT(); + return obj; } -template <> -inline void * GC_selective_alloc(size_t n, GC_true_type, - bool ignore_off_page) { - return ignore_off_page? GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(n) - : GC_MALLOC_ATOMIC(n); -} +#if !defined(__WATCOMC__) + /* Note: template-id not supported in this context by Watcom compiler. */ + template <> + inline void * GC_selective_alloc(size_t n, GC_true_type, + bool ignore_off_page) { + void * obj = ignore_off_page ? GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(n) + : GC_MALLOC_ATOMIC(n); + if (0 == obj) + GC_ALLOCATOR_THROW_OR_ABORT(); + return obj; + } +#endif /* Now the public gc_allocator class: */ @@ -116,7 +132,8 @@ public: gc_allocator(const gc_allocator&) throw() {} # if !(GC_NO_MEMBER_TEMPLATES || 0 < _MSC_VER && _MSC_VER <= 1200) // MSVC++ 6.0 do not support member templates - template gc_allocator(const gc_allocator&) throw() {} + template GC_ATTR_EXPLICIT + gc_allocator(const gc_allocator&) throw() {} # endif ~gc_allocator() throw() {} @@ -133,7 +150,7 @@ public: } // __p is not permitted to be a null pointer. - void deallocate(pointer __p, size_type GC_ATTR_UNUSED GC_n) + void deallocate(pointer __p, size_type /* GC_n */) { GC_FREE(__p); } size_type max_size() const throw() @@ -191,7 +208,7 @@ public: gc_allocator_ignore_off_page(const gc_allocator_ignore_off_page&) throw() {} # if !(GC_NO_MEMBER_TEMPLATES || 0 < _MSC_VER && _MSC_VER <= 1200) // MSVC++ 6.0 do not support member templates - template + template GC_ATTR_EXPLICIT gc_allocator_ignore_off_page(const gc_allocator_ignore_off_page&) throw() {} # endif @@ -210,7 +227,7 @@ public: } // __p is not permitted to be a null pointer. - void deallocate(pointer __p, size_type GC_ATTR_UNUSED GC_n) + void deallocate(pointer __p, size_type /* GC_n */) { GC_FREE(__p); } size_type max_size() const throw() @@ -271,8 +288,8 @@ public: traceable_allocator(const traceable_allocator&) throw() {} # if !(GC_NO_MEMBER_TEMPLATES || 0 < _MSC_VER && _MSC_VER <= 1200) // MSVC++ 6.0 do not support member templates - template traceable_allocator - (const traceable_allocator&) throw() {} + template GC_ATTR_EXPLICIT + traceable_allocator(const traceable_allocator&) throw() {} # endif ~traceable_allocator() throw() {} @@ -282,11 +299,14 @@ public: // GC_n is permitted to be 0. The C++ standard says nothing about what // the return value is when GC_n == 0. GC_Tp* allocate(size_type GC_n, const void* = 0) { - return static_cast(GC_MALLOC_UNCOLLECTABLE(GC_n * sizeof(GC_Tp))); + void * obj = GC_MALLOC_UNCOLLECTABLE(GC_n * sizeof(GC_Tp)); + if (0 == obj) + GC_ALLOCATOR_THROW_OR_ABORT(); + return static_cast(obj); } // __p is not permitted to be a null pointer. - void deallocate(pointer __p, size_type GC_ATTR_UNUSED GC_n) + void deallocate(pointer __p, size_type /* GC_n */) { GC_FREE(__p); } size_type max_size() const throw() diff --git a/src/bdwgc/include/gc_config_macros.h b/src/bdwgc/include/gc_config_macros.h index d6da7ca2a..d9885bb7c 100644 --- a/src/bdwgc/include/gc_config_macros.h +++ b/src/bdwgc/include/gc_config_macros.h @@ -64,7 +64,8 @@ #if defined(GC_AIX_THREADS) || defined(GC_DARWIN_THREADS) \ || defined(GC_DGUX386_THREADS) || defined(GC_FREEBSD_THREADS) \ - || defined(GC_GNU_THREADS) || defined(GC_HPUX_THREADS) \ + || defined(GC_GNU_THREADS) \ + || defined(GC_HAIKU_THREADS) || defined(GC_HPUX_THREADS) \ || defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) \ || defined(GC_NETBSD_THREADS) || defined(GC_OPENBSD_THREADS) \ || defined(GC_OSF1_THREADS) || defined(GC_SOLARIS_THREADS) \ @@ -88,18 +89,22 @@ # define GC_IRIX_THREADS # endif # if defined(__sparc) && !defined(__linux__) \ - || defined(sun) && (defined(i386) || defined(__i386__) \ - || defined(__amd64__)) + || ((defined(sun) || defined(__sun)) \ + && (defined(i386) || defined(__i386__) \ + || defined(__amd64) || defined(__amd64__))) # define GC_SOLARIS_THREADS # elif defined(__APPLE__) && defined(__MACH__) # define GC_DARWIN_THREADS +# elif defined(__HAIKU__) +# define GC_HAIKU_THREADS # elif defined(__OpenBSD__) # define GC_OPENBSD_THREADS # elif !defined(GC_LINUX_THREADS) && !defined(GC_HPUX_THREADS) \ && !defined(GC_OSF1_THREADS) && !defined(GC_IRIX_THREADS) /* FIXME: Should we really need for FreeBSD and NetBSD to check */ /* that no other GC_xxx_THREADS macro is set? */ -# if defined(__FreeBSD__) || defined(__DragonFly__) +# if defined(__FreeBSD__) || defined(__DragonFly__) \ + || defined(__FreeBSD_kernel__) # define GC_FREEBSD_THREADS # elif defined(__NetBSD__) # define GC_NETBSD_THREADS @@ -172,7 +177,7 @@ #if defined(GC_DLL) && !defined(GC_API) # if defined(__MINGW32__) || defined(__CEGCC__) -# ifdef GC_BUILD +# if defined(GC_BUILD) || defined(__MINGW32_DELAY_LOAD__) # define GC_API __declspec(dllexport) # else # define GC_API __declspec(dllimport) @@ -202,8 +207,8 @@ # elif defined(__GNUC__) /* Only matters if used in conjunction with -fvisibility=hidden option. */ -# if defined(GC_BUILD) && (__GNUC__ >= 4 \ - || defined(GC_VISIBILITY_HIDDEN_SET)) +# if defined(GC_BUILD) && !defined(GC_NO_VISIBILITY) \ + && (__GNUC__ >= 4 || defined(GC_VISIBILITY_HIDDEN_SET)) # define GC_API extern __attribute__((__visibility__("default"))) # endif # endif @@ -232,7 +237,7 @@ # elif defined(__GNUC__) && (__GNUC__ > 3 \ || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) # define GC_ATTR_MALLOC __attribute__((__malloc__)) -# elif defined(_MSC_VER) && _MSC_VER >= 14 +# elif defined(_MSC_VER) && _MSC_VER >= 1400 # define GC_ATTR_MALLOC __declspec(noalias) __declspec(restrict) # else # define GC_ATTR_MALLOC @@ -270,7 +275,7 @@ # define GC_ATTR_DEPRECATED /* empty */ # elif defined(__GNUC__) && __GNUC__ >= 4 # define GC_ATTR_DEPRECATED __attribute__((__deprecated__)) -# elif defined(_MSC_VER) && _MSC_VER >= 12 +# elif defined(_MSC_VER) && _MSC_VER >= 1200 # define GC_ATTR_DEPRECATED __declspec(deprecated) # else # define GC_ATTR_DEPRECATED /* empty */ @@ -287,7 +292,8 @@ # include # endif # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \ - && !defined(__ia64__) && !defined(__UCLIBC__) \ + && !defined(__ia64__) \ + && !defined(GC_MISSING_EXECINFO_H) \ && !defined(GC_HAVE_BUILTIN_BACKTRACE) # define GC_HAVE_BUILTIN_BACKTRACE # endif @@ -319,7 +325,8 @@ /* This may also be desirable if it is possible but expensive to */ /* retrieve the call chain. */ #if (defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) \ - || defined(__FreeBSD__) || defined(__DragonFly__) \ + || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__HAIKU__) \ + || defined(__FreeBSD_kernel__) \ || defined(PLATFORM_ANDROID) || defined(__ANDROID__)) \ && !defined(GC_CAN_SAVE_CALL_STACKS) # define GC_ADD_CALLER @@ -329,6 +336,7 @@ # define GC_RETURN_ADDR (GC_word)__builtin_return_address(0) # if (__GNUC__ >= 4) && (defined(__i386__) || defined(__amd64__) \ || defined(__x86_64__) /* and probably others... */) +# define GC_HAVE_RETURN_ADDR_PARENT # define GC_RETURN_ADDR_PARENT \ (GC_word)__builtin_extract_return_addr(__builtin_return_address(1)) # endif @@ -361,14 +369,16 @@ # ifndef GC_PTHREAD_CREATE_CONST # define GC_PTHREAD_CREATE_CONST /* empty */ # endif -# ifndef GC_PTHREAD_EXIT_ATTRIBUTE +# ifndef GC_HAVE_PTHREAD_EXIT +# define GC_HAVE_PTHREAD_EXIT # define GC_PTHREAD_EXIT_ATTRIBUTE /* empty */ # endif # endif -# if !defined(GC_PTHREAD_EXIT_ATTRIBUTE) \ +# if !defined(GC_HAVE_PTHREAD_EXIT) \ && !defined(PLATFORM_ANDROID) && !defined(__ANDROID__) \ && (defined(GC_LINUX_THREADS) || defined(GC_SOLARIS_THREADS)) +# define GC_HAVE_PTHREAD_EXIT /* Intercept pthread_exit on Linux and Solaris. */ # if defined(__GNUC__) /* since GCC v2.7 */ # define GC_PTHREAD_EXIT_ATTRIBUTE __attribute__((__noreturn__)) @@ -379,7 +389,7 @@ # endif # endif -# if (!defined(GC_PTHREAD_EXIT_ATTRIBUTE) || defined(__native_client__)) \ +# if (!defined(GC_HAVE_PTHREAD_EXIT) || defined(__native_client__)) \ && !defined(GC_NO_PTHREAD_CANCEL) /* Either there is no pthread_cancel() or no need to intercept it. */ # define GC_NO_PTHREAD_CANCEL diff --git a/src/bdwgc/include/gc_cpp.h b/src/bdwgc/include/gc_cpp.h index 0302439df..92ec2317f 100644 --- a/src/bdwgc/include/gc_cpp.h +++ b/src/bdwgc/include/gc_cpp.h @@ -149,91 +149,125 @@ by UseGC. GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined. #endif #ifndef THINK_CPLUS -# define GC_cdecl GC_CALLBACK +# define GC_cdecl GC_CALLBACK #else -# define GC_cdecl _cdecl +# define GC_cdecl _cdecl #endif -#if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \ +#if !defined(GC_NO_OPERATOR_NEW_ARRAY) \ && !defined(_ENABLE_ARRAYNEW) /* Digimars */ \ && (defined(__BORLANDC__) && (__BORLANDC__ < 0x450) \ || (defined(__GNUC__) && \ (__GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 6)) \ || (defined(_MSC_VER) && _MSC_VER <= 1020) \ || (defined(__WATCOMC__) && __WATCOMC__ < 1050)) -# define GC_NO_OPERATOR_NEW_ARRAY +# define GC_NO_OPERATOR_NEW_ARRAY #endif #if !defined(GC_NO_OPERATOR_NEW_ARRAY) && !defined(GC_OPERATOR_NEW_ARRAY) -# define GC_OPERATOR_NEW_ARRAY +# define GC_OPERATOR_NEW_ARRAY #endif #if (!defined(__BORLANDC__) || __BORLANDC__ > 0x0620) \ - && ! defined ( __sgi ) && ! defined( __WATCOMC__ ) \ + && ! defined (__sgi) && ! defined(__WATCOMC__) \ && (!defined(_MSC_VER) || _MSC_VER > 1020) -# define GC_PLACEMENT_DELETE +# define GC_PLACEMENT_DELETE #endif +#ifndef GC_DECL_DELETE_THROW +# if defined(__DMC__) || (defined(__BORLANDC__) \ + && (defined(_RWSTD_NO_EXCEPTIONS) || defined(_RWSTD_NO_EX_SPEC))) \ + || (defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) \ + || (defined(__WATCOMC__) && !defined(_CPPUNWIND)) +# define GC_DECL_DELETE_THROW /* empty */ +# ifndef GC_NEW_ABORTS_ON_OOM +# define GC_NEW_ABORTS_ON_OOM +# endif +# else +# define GC_DECL_DELETE_THROW throw() +# endif +#endif // !GC_DECL_DELETE_THROW + +#if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS) +# define GC_OP_NEW_OOM_CHECK(obj) \ + do { if (!(obj)) GC_abort_on_oom(); } while (0) +#elif defined(GC_INCLUDE_NEW) +# include // for bad_alloc +# define GC_OP_NEW_OOM_CHECK(obj) if (obj) {} else throw std::bad_alloc() +#else + // "new" header is not included, so bad_alloc cannot be thrown directly. + GC_API void GC_CALL GC_throw_bad_alloc(); +# define GC_OP_NEW_OOM_CHECK(obj) if (obj) {} else GC_throw_bad_alloc() +#endif // !GC_NEW_ABORTS_ON_OOM && !GC_INCLUDE_NEW + #ifdef GC_NAMESPACE namespace boehmgc { #endif -enum GCPlacement { +enum GCPlacement +{ UseGC, # ifndef GC_NAME_CONFLICT - GC=UseGC, + GC = UseGC, # endif NoGC, PointerFreeGC +# ifdef GC_ATOMIC_UNCOLLECTABLE + , PointerFreeNoGC +# endif }; -class gc { - public: - inline void* operator new( size_t size ); - inline void* operator new( size_t size, GCPlacement gcp ); - inline void* operator new( size_t size, void *p ); - /* Must be redefined here, since the other overloadings */ - /* hide the global definition. */ - inline void operator delete( void* obj ); -# ifdef GC_PLACEMENT_DELETE - inline void operator delete( void*, GCPlacement ); - /* called if construction fails. */ - inline void operator delete( void*, void* ); -# endif +/** + * Instances of classes derived from "gc" will be allocated in the collected + * heap by default, unless an explicit NoGC placement is specified. + */ +class gc +{ +public: + inline void* operator new(size_t size); + inline void* operator new(size_t size, GCPlacement gcp); + inline void* operator new(size_t size, void* p); + // Must be redefined here, since the other overloadings hide + // the global definition. + inline void operator delete(void* obj); -#ifdef GC_OPERATOR_NEW_ARRAY - inline void* operator new[]( size_t size ); - inline void* operator new[]( size_t size, GCPlacement gcp ); - inline void* operator new[]( size_t size, void *p ); - inline void operator delete[]( void* obj ); +# ifdef GC_PLACEMENT_DELETE + inline void operator delete(void*, GCPlacement); + // Called if construction fails. + inline void operator delete(void*, void*); +# endif // GC_PLACEMENT_DELETE + +# ifdef GC_OPERATOR_NEW_ARRAY + inline void* operator new[](size_t size); + inline void* operator new[](size_t size, GCPlacement gcp); + inline void* operator new[](size_t size, void* p); + inline void operator delete[](void* obj); # ifdef GC_PLACEMENT_DELETE - inline void operator delete[]( void*, GCPlacement ); - inline void operator delete[]( void*, void* ); + inline void operator delete[](void*, GCPlacement); + inline void operator delete[](void*, void*); # endif -#endif /* GC_OPERATOR_NEW_ARRAY */ +# endif // GC_OPERATOR_NEW_ARRAY }; - /* - Instances of classes derived from "gc" will be allocated in the - collected heap by default, unless an explicit NoGC placement is - specified. */ -class gc_cleanup: virtual public gc { - public: - inline gc_cleanup(); - inline virtual ~gc_cleanup(); +/** + * Instances of classes derived from "gc_cleanup" will be allocated + * in the collected heap by default. When the collector discovers + * an inaccessible object derived from "gc_cleanup" or containing + * a member derived from "gc_cleanup", its destructors will be invoked. + */ +class gc_cleanup: virtual public gc +{ +public: + inline gc_cleanup(); + inline virtual ~gc_cleanup(); + private: - inline static void GC_cdecl cleanup( void* obj, void* clientData ); + inline static void GC_cdecl cleanup(void* obj, void* clientData); }; - /* - Instances of classes derived from "gc_cleanup" will be allocated - in the collected heap by default. When the collector discovers an - inaccessible object derived from "gc_cleanup" or containing a - member derived from "gc_cleanup", its destructors will be - invoked. */ extern "C" { - typedef void (GC_CALLBACK * GCCleanUpFunc)( void* obj, void* clientData ); + typedef void (GC_CALLBACK * GCCleanUpFunc)(void* obj, void* clientData); } #ifdef GC_NAMESPACE @@ -244,193 +278,268 @@ extern "C" { // Disable warning that "no matching operator delete found; memory will // not be freed if initialization throws an exception" # pragma warning(disable:4291) + // TODO: "non-member operator new or delete may not be declared inline" + // warning is disabled for now. +# pragma warning(disable:4595) #endif -inline void* operator new( size_t size, GC_NS_QUALIFY(GCPlacement) gcp, +inline void* operator new(size_t size, GC_NS_QUALIFY(GCPlacement) gcp, GC_NS_QUALIFY(GCCleanUpFunc) cleanup = 0, - void* clientData = 0 ); - /* - Allocates a collectible or uncollectible object, according to the - value of "gcp". - - For collectible objects, if "cleanup" is non-null, then when the - allocated object "obj" becomes inaccessible, the collector will - invoke the function "cleanup( obj, clientData )" but will not - invoke the object's destructors. It is an error to explicitly - delete an object allocated with a non-null "cleanup". - - It is an error to specify a non-null "cleanup" with NoGC or for - classes derived from "gc_cleanup" or containing members derived - from "gc_cleanup". */ + void* clientData = 0); + // Allocates a collectible or uncollectible object, according to the + // value of "gcp". + // + // For collectible objects, if "cleanup" is non-null, then when the + // allocated object "obj" becomes inaccessible, the collector will + // invoke the function "cleanup(obj, clientData)" but will not + // invoke the object's destructors. It is an error to explicitly + // delete an object allocated with a non-null "cleanup". + // + // It is an error to specify a non-null "cleanup" with NoGC or for + // classes derived from "gc_cleanup" or containing members derived + // from "gc_cleanup". #ifdef GC_PLACEMENT_DELETE - inline void operator delete( void*, GC_NS_QUALIFY(GCPlacement), - GC_NS_QUALIFY(GCCleanUpFunc), void * ); + inline void operator delete(void*, GC_NS_QUALIFY(GCPlacement), + GC_NS_QUALIFY(GCCleanUpFunc), void*); #endif -#ifdef _MSC_VER - /** This ensures that the system default operator new[] doesn't get - * undefined, which is what seems to happen on VC++ 6 for some reason - * if we define a multi-argument operator new[]. - * There seems to be no way to redirect new in this environment without - * including this everywhere. - */ -# if _MSC_VER > 1020 - void *operator new[]( size_t size ); - void operator delete[]( void* obj ); +#if defined(_MSC_VER) || defined(__DMC__) + // The following ensures that the system default operator new[] does not + // get undefined, which is what seems to happen on VC++ 6 for some reason + // if we define a multi-argument operator new[]. + // There seems to be no way to redirect new in this environment without + // including this everywhere. + // Inlining done to avoid mix up of new and delete operators by VC++ 9 (due + // to arbitrary ordering during linking). + +# ifdef GC_OPERATOR_NEW_ARRAY + inline void* operator new[](size_t size) + { + void* obj = GC_MALLOC_UNCOLLECTABLE(size); + GC_OP_NEW_OOM_CHECK(obj); + return obj; + } + + inline void operator delete[](void* obj) + { + GC_FREE(obj); + } # endif - void* operator new( size_t size ); - void operator delete( void* obj ); + inline void* operator new(size_t size) + { + void* obj = GC_MALLOC_UNCOLLECTABLE(size); + GC_OP_NEW_OOM_CHECK(obj); + return obj; + } - // This new operator is used by VC++ in case of Debug builds ! - void* operator new( size_t size, int /* nBlockUse */, - const char * szFileName, int nLine ); -#endif /* _MSC_VER */ + inline void operator delete(void* obj) + { + GC_FREE(obj); + } + + // This new operator is used by VC++ in case of Debug builds: +# ifdef GC_DEBUG + inline void* operator new(size_t size, int /* nBlockUse */, + const char* szFileName, int nLine) + { + void* obj = GC_debug_malloc_uncollectable(size, szFileName, nLine); + GC_OP_NEW_OOM_CHECK(obj); + return obj; + } +# else + inline void* operator new(size_t size, int /* nBlockUse */, + const char* /* szFileName */, int /* nLine */) + { + void* obj = GC_malloc_uncollectable(size); + GC_OP_NEW_OOM_CHECK(obj); + return obj; + } +# endif /* !GC_DEBUG */ + +# ifdef GC_OPERATOR_NEW_ARRAY + // This new operator is used by VC++ 7+ in Debug builds: + inline void* operator new[](size_t size, int nBlockUse, + const char* szFileName, int nLine) + { + return operator new(size, nBlockUse, szFileName, nLine); + } +# endif + +#endif // _MSC_VER #ifdef GC_OPERATOR_NEW_ARRAY - inline void* operator new[]( size_t size, GC_NS_QUALIFY(GCPlacement) gcp, + // The operator new for arrays, identical to the above. + inline void* operator new[](size_t size, GC_NS_QUALIFY(GCPlacement) gcp, GC_NS_QUALIFY(GCCleanUpFunc) cleanup = 0, - void* clientData = 0 ); - /* The operator new for arrays, identical to the above. */ -#endif /* GC_OPERATOR_NEW_ARRAY */ + void* clientData = 0); +#endif // GC_OPERATOR_NEW_ARRAY -/**************************************************************************** - -Inline implementation - -****************************************************************************/ +/* Inline implementation */ #ifdef GC_NAMESPACE namespace boehmgc { #endif -inline void* gc::operator new( size_t size ) { - return GC_MALLOC( size ); +inline void* gc::operator new(size_t size) +{ + void* obj = GC_MALLOC(size); + GC_OP_NEW_OOM_CHECK(obj); + return obj; } -inline void* gc::operator new( size_t size, GCPlacement gcp ) { - if (gcp == UseGC) - return GC_MALLOC( size ); - else if (gcp == PointerFreeGC) - return GC_MALLOC_ATOMIC( size ); - else - return GC_MALLOC_UNCOLLECTABLE( size ); +inline void* gc::operator new(size_t size, GCPlacement gcp) +{ + void* obj; + switch (gcp) { + case UseGC: + obj = GC_MALLOC(size); + break; + case PointerFreeGC: + obj = GC_MALLOC_ATOMIC(size); + break; +# ifdef GC_ATOMIC_UNCOLLECTABLE + case PointerFreeNoGC: + obj = GC_MALLOC_ATOMIC_UNCOLLECTABLE(size); + break; +# endif + case NoGC: + default: + obj = GC_MALLOC_UNCOLLECTABLE(size); + } + GC_OP_NEW_OOM_CHECK(obj); + return obj; } -inline void* gc::operator new( size_t /* size */, void *p ) { - return p; +inline void* gc::operator new(size_t /* size */, void* p) +{ + return p; } -inline void gc::operator delete( void* obj ) { - GC_FREE( obj ); +inline void gc::operator delete(void* obj) +{ + GC_FREE(obj); } #ifdef GC_PLACEMENT_DELETE - inline void gc::operator delete( void*, void* ) {} + inline void gc::operator delete(void*, void*) {} - inline void gc::operator delete( void* p, GCPlacement /* gcp */ ) { + inline void gc::operator delete(void* p, GCPlacement /* gcp */) + { GC_FREE(p); } -#endif +#endif // GC_PLACEMENT_DELETE #ifdef GC_OPERATOR_NEW_ARRAY - inline void* gc::operator new[]( size_t size ) { - return gc::operator new( size ); + inline void* gc::operator new[](size_t size) + { + return gc::operator new(size); } - inline void* gc::operator new[]( size_t size, GCPlacement gcp ) { - return gc::operator new( size, gcp ); + inline void* gc::operator new[](size_t size, GCPlacement gcp) + { + return gc::operator new(size, gcp); } - inline void* gc::operator new[]( size_t /* size */, void *p ) { + inline void* gc::operator new[](size_t /* size */, void* p) + { return p; } - inline void gc::operator delete[]( void* obj ) { - gc::operator delete( obj ); + inline void gc::operator delete[](void* obj) + { + gc::operator delete(obj); } # ifdef GC_PLACEMENT_DELETE - inline void gc::operator delete[]( void*, void* ) {} + inline void gc::operator delete[](void*, void*) {} - inline void gc::operator delete[]( void* p, GCPlacement /* gcp */ ) { + inline void gc::operator delete[](void* p, GCPlacement /* gcp */) + { gc::operator delete(p); } # endif -#endif /* GC_OPERATOR_NEW_ARRAY */ +#endif // GC_OPERATOR_NEW_ARRAY -inline gc_cleanup::~gc_cleanup() { - GC_register_finalizer_ignore_self( GC_base(this), 0, 0, 0, 0 ); +inline gc_cleanup::~gc_cleanup() +{ + void* base = GC_base(this); + if (0 == base) return; // Non-heap object. + GC_register_finalizer_ignore_self(base, 0, 0, 0, 0); } -inline void GC_CALLBACK gc_cleanup::cleanup( void* obj, void* displ ) { - ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup(); +inline void GC_CALLBACK gc_cleanup::cleanup(void* obj, void* displ) +{ + ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup(); } -inline gc_cleanup::gc_cleanup() { - GC_finalization_proc oldProc; - void* oldData; - void* base = GC_base( (void *) this ); - if (0 != base) { - // Don't call the debug version, since this is a real base address. - GC_register_finalizer_ignore_self( base, (GC_finalization_proc)cleanup, - (void*)((char*)this - (char*)base), - &oldProc, &oldData ); - if (0 != oldProc) { - GC_register_finalizer_ignore_self( base, oldProc, oldData, 0, 0 ); - } +inline gc_cleanup::gc_cleanup() +{ + GC_finalization_proc oldProc; + void* oldData; + void* this_ptr = (void*)this; + void* base = GC_base(this_ptr); + if (base != 0) { + // Don't call the debug version, since this is a real base address. + GC_register_finalizer_ignore_self(base, (GC_finalization_proc) cleanup, + (void*)((char*)this_ptr - (char*)base), + &oldProc, &oldData); + if (oldProc != 0) { + GC_register_finalizer_ignore_self(base, oldProc, oldData, 0, 0); } + } } #ifdef GC_NAMESPACE } #endif -inline void* operator new( size_t size, GC_NS_QUALIFY(GCPlacement) gcp, +inline void* operator new(size_t size, GC_NS_QUALIFY(GCPlacement) gcp, GC_NS_QUALIFY(GCCleanUpFunc) cleanup, - void* clientData ) + void* clientData) { - void* obj; - - if (gcp == GC_NS_QUALIFY(UseGC)) { - obj = GC_MALLOC( size ); - if (cleanup != 0) - GC_REGISTER_FINALIZER_IGNORE_SELF( obj, cleanup, clientData, - 0, 0 ); - } else if (gcp == GC_NS_QUALIFY(PointerFreeGC)) { - obj = GC_MALLOC_ATOMIC( size ); - } else { - obj = GC_MALLOC_UNCOLLECTABLE( size ); - }; - return obj; + void* obj; + switch (gcp) { + case GC_NS_QUALIFY(UseGC): + obj = GC_MALLOC(size); + if (cleanup != 0 && obj != 0) { + GC_REGISTER_FINALIZER_IGNORE_SELF(obj, cleanup, clientData, 0, 0); + } + break; + case GC_NS_QUALIFY(PointerFreeGC): + obj = GC_MALLOC_ATOMIC(size); + break; +# ifdef GC_ATOMIC_UNCOLLECTABLE + case GC_NS_QUALIFY(PointerFreeNoGC): + obj = GC_MALLOC_ATOMIC_UNCOLLECTABLE(size); + break; +# endif + case GC_NS_QUALIFY(NoGC): + default: + obj = GC_MALLOC_UNCOLLECTABLE(size); + } + GC_OP_NEW_OOM_CHECK(obj); + return obj; } #ifdef GC_PLACEMENT_DELETE - inline void operator delete( void *p, GC_NS_QUALIFY(GCPlacement) /* gcp */, + inline void operator delete(void* p, GC_NS_QUALIFY(GCPlacement) /* gcp */, GC_NS_QUALIFY(GCCleanUpFunc) /* cleanup */, - void* /* clientData */ ) + void* /* clientData */) { GC_FREE(p); } -#endif /* GC_PLACEMENT_DELETE */ +#endif // GC_PLACEMENT_DELETE #ifdef GC_OPERATOR_NEW_ARRAY - inline void* operator new[]( size_t size, GC_NS_QUALIFY(GCPlacement) gcp, + inline void* operator new[](size_t size, GC_NS_QUALIFY(GCPlacement) gcp, GC_NS_QUALIFY(GCCleanUpFunc) cleanup, - void* clientData ) + void* clientData) { - return ::operator new( size, gcp, cleanup, clientData ); + return ::operator new(size, gcp, cleanup, clientData); } -#endif /* GC_OPERATOR_NEW_ARRAY */ - -#if defined(__CYGWIN__) -# include // for delete throw() - inline void operator delete(void *p) - { - GC_FREE(p); - } -#endif +#endif // GC_OPERATOR_NEW_ARRAY #endif /* GC_CPP_H */ diff --git a/src/bdwgc/include/gc_disclaim.h b/src/bdwgc/include/gc_disclaim.h index 3631e6e89..716b741f6 100644 --- a/src/bdwgc/include/gc_disclaim.h +++ b/src/bdwgc/include/gc_disclaim.h @@ -48,6 +48,9 @@ struct GC_finalizer_closure { /* dedicated object kind with a disclaim procedure, and is more */ /* efficient than GC_register_finalizer and friends. */ /* GC_init_finalized_malloc must be called before using this. */ +/* Note that GC_size (applied to such allocated object) returns a value */ +/* slightly bigger than the specified allocation size, and that GC_base */ +/* result points to a word prior to the start of the allocated object. */ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL GC_finalized_malloc(size_t /*size*/, const struct GC_finalizer_closure * /*fc*/); diff --git a/src/bdwgc/include/gc_inline.h b/src/bdwgc/include/gc_inline.h index 8d93f44ac..32c15c130 100644 --- a/src/bdwgc/include/gc_inline.h +++ b/src/bdwgc/include/gc_inline.h @@ -42,12 +42,34 @@ # define GC_ASSERT(expr) /* empty */ #endif +#ifndef GC_PREFETCH_FOR_WRITE +# define GC_PREFETCH_FOR_WRITE(x) (void)0 +#endif + +/* Object kinds; must match PTRFREE, NORMAL in gc_priv.h. */ +#define GC_I_PTRFREE 0 +#define GC_I_NORMAL 1 + /* Store a pointer to a list of newly allocated objects of kind k and */ /* size lb in *result. The caller must make sure that *result is */ /* traced even if objects are ptrfree. */ GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, void ** /* result */); +/* Generalized version of GC_malloc and GC_malloc_atomic. */ +/* Uses appropriately the thread-local (if available) or the global */ +/* free-list of the specified kind. */ +GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL + GC_malloc_kind(size_t /* lb */, int /* k */); + +#ifdef GC_THREADS + /* Same as above but uses only the global free-list. */ + GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL + GC_malloc_kind_global(size_t /* lb */, int /* k */); +#else +# define GC_malloc_kind_global GC_malloc_kind +#endif + /* The ultimately general inline allocation macro. Allocate an object */ /* of size granules, putting the resulting pointer in result. Tiny_fl */ /* is a "tiny" free list array, which will be used first, if the size */ @@ -56,17 +78,17 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, /* GC_generic_malloc_many with the indicated kind. */ /* Tiny_fl should be an array of GC_TINY_FREELISTS void * pointers. */ /* If num_direct is nonzero, and the individual free list pointers */ -/* are initialized to (void *)1, then we allocate numdirect granules */ -/* directly using gmalloc before putting multiple objects into the */ -/* tiny_fl entry. If num_direct is zero, then the free lists may also */ -/* be initialized to (void *)0. */ +/* are initialized to (void *)1, then we allocate num_direct granules */ +/* directly using generic_malloc before putting multiple objects into */ +/* the tiny_fl entry. If num_direct is zero, then the free lists may */ +/* also be initialized to (void *)0. */ /* Note that we use the zeroth free list to hold objects 1 granule in */ /* size that are used to satisfy size 0 allocation requests. */ /* We rely on much of this hopefully getting optimized away in the */ /* num_direct = 0 case. */ /* Particularly if granules is constant, this should generate a small */ /* amount of code. */ -# define GC_FAST_MALLOC_GRANS(result,granules,tiny_fl,num_direct,\ +# define GC_FAST_MALLOC_GRANS(result,granules,tiny_fl,num_direct, \ kind,default_expr,init) \ do { \ if (GC_EXPECT((granules) >= GC_TINY_FREELISTS,0)) { \ @@ -76,14 +98,31 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, void *my_entry=*my_fl; \ void *next; \ \ - while (GC_EXPECT((GC_word)my_entry \ - <= (num_direct) + GC_TINY_FREELISTS + 1, 0)) { \ + for (;;) { \ + if (GC_EXPECT((GC_word)my_entry \ + > (num_direct) + GC_TINY_FREELISTS + 1, 1)) { \ + next = *(void **)(my_entry); \ + result = (void *)my_entry; \ + *my_fl = next; \ + init; \ + GC_PREFETCH_FOR_WRITE(next); \ + if ((kind) != GC_I_PTRFREE) { \ + GC_end_stubborn_change(my_fl); \ + GC_reachable_here(next); \ + } \ + GC_ASSERT(GC_size(result) >= (granules)*GC_GRANULE_BYTES); \ + GC_ASSERT((kind) == GC_I_PTRFREE \ + || ((GC_word *)result)[1] == 0); \ + break; \ + } \ /* Entry contains counter or NULL */ \ - if ((GC_word)my_entry - 1 < (num_direct)) { \ + if ((GC_signed_word)my_entry - (GC_signed_word)(num_direct) <= 0 \ + /* (GC_word)my_entry <= (num_direct) */ \ + && my_entry != 0 /* NULL */) { \ /* Small counter value, not NULL */ \ *my_fl = (char *)my_entry + (granules) + 1; \ result = (default_expr); \ - goto out; \ + break; \ } else { \ /* Large counter or NULL */ \ GC_generic_malloc_many(((granules) == 0? GC_GRANULE_BYTES : \ @@ -92,18 +131,10 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, my_entry = *my_fl; \ if (my_entry == 0) { \ result = (*GC_get_oom_fn())((granules)*GC_GRANULE_BYTES); \ - goto out; \ + break; \ } \ } \ } \ - next = *(void **)(my_entry); \ - result = (void *)my_entry; \ - *my_fl = next; \ - init; \ - PREFETCH_FOR_WRITE(next); \ - GC_ASSERT(GC_size(result) >= (granules)*GC_GRANULE_BYTES); \ - GC_ASSERT((kind) == PTRFREE || ((GC_word *)result)[1] == 0); \ - out: ; \ } \ } while (0) @@ -117,30 +148,37 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, /* the caller is responsible for supplying a cleared tiny_fl */ /* free list array. For single-threaded applications, this may be */ /* a global array. */ +# define GC_MALLOC_WORDS_KIND(result,n,tiny_fl,k,init) \ + do { \ + size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \ + GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, k, \ + GC_malloc_kind(grans * GC_GRANULE_BYTES, k), \ + init); \ + } while (0) + # define GC_MALLOC_WORDS(result,n,tiny_fl) \ - do { \ - size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \ - GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ - NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \ - *(void **)(result) = 0); \ - } while (0) + GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_NORMAL, \ + *(void **)(result) = 0) # define GC_MALLOC_ATOMIC_WORDS(result,n,tiny_fl) \ - do { \ - size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \ - GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ - PTRFREE, GC_malloc_atomic(grans*GC_GRANULE_BYTES), \ - (void)0 /* no initialization */); \ - } while (0) + GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_PTRFREE, (void)0) /* And once more for two word initialized objects: */ # define GC_CONS(result, first, second, tiny_fl) \ - do { \ - size_t grans = GC_WORDS_TO_WHOLE_GRANULES(2); \ - GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ - NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \ - *(void **)(result) = (void *)(first)); \ - ((void **)(result))[1] = (void *)(second); \ - } while (0) + do { \ + void *l = (void *)(first); \ + void *r = (void *)(second); \ + GC_MALLOC_WORDS_KIND(result, 2, tiny_fl, GC_I_NORMAL, (void)0); \ + if ((result) != 0 /* NULL */) { \ + *(void **)(result) = l; \ + ((void **)(result))[1] = r; \ + GC_end_stubborn_change(result); \ + GC_reachable_here(l); \ + GC_reachable_here(r); \ + } \ + } while (0) + +GC_API void GC_CALL GC_print_free_list(int /* kind */, + size_t /* sz_in_granules */); #endif /* !GC_INLINE_H */ diff --git a/src/bdwgc/include/gc_mark.h b/src/bdwgc/include/gc_mark.h index dcadf42ef..ee0bb11c3 100644 --- a/src/bdwgc/include/gc_mark.h +++ b/src/bdwgc/include/gc_mark.h @@ -101,10 +101,10 @@ typedef struct GC_ms_entry * (*GC_mark_proc)(GC_word * /* addr */, | (proc_index)) << GC_DS_TAG_BITS) | GC_DS_PROC) #define GC_DS_PER_OBJECT 3 /* The real descriptor is at the */ /* byte displacement from the beginning of the */ - /* object given by descr & ~DS_TAGS */ + /* object given by descr & ~GC_DS_TAGS. */ /* If the descriptor is negative, the real */ /* descriptor is at (*) - */ - /* (descr & ~DS_TAGS) - GC_INDIR_PER_OBJ_BIAS */ + /* (descr&~GC_DS_TAGS) - GC_INDIR_PER_OBJ_BIAS */ /* The latter alternative can be used if each */ /* object contains a type descriptor in the */ /* first word. */ @@ -184,7 +184,7 @@ GC_API unsigned GC_CALL GC_new_proc(GC_mark_proc); GC_API unsigned GC_CALL GC_new_proc_inner(GC_mark_proc); /* Allocate an object of a given kind. By default, there are only */ -/* a few kinds: composite (pointer-free), atomic, uncollectible, etc. */ +/* a few kinds: composite (pointerful), atomic, uncollectible, etc. */ /* We claim it is possible for clever client code that understands the */ /* GC internals to add more, e.g. to communicate object layout */ /* information to the collector. Note that in the multi-threaded */ @@ -204,6 +204,11 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL /* first page of the resulting object */ /* are ignored. */ +/* Generalized version of GC_malloc_[atomic_]uncollectable. */ +GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL + GC_generic_malloc_uncollectable( + size_t /* lb */, int /* knd */); + /* Same as above but primary for allocating an object of the same kind */ /* as an existing one (kind obtained by GC_get_kind_and_size). */ /* Not suitable for GCJ and typed-malloc kinds. */ @@ -274,10 +279,13 @@ GC_API void GC_CALL GC_set_mark_bit(const void *) GC_ATTR_NONNULL(1); /* Push everything in the given range onto the mark stack. */ /* (GC_push_conditional pushes either all or only dirty pages depending */ -/* on the third argument.) */ +/* on the third argument.) GC_push_all_eager also ensures that stack */ +/* is scanned immediately, not just scheduled for scanning. */ GC_API void GC_CALL GC_push_all(char * /* bottom */, char * /* top */); +GC_API void GC_CALL GC_push_all_eager(char * /* bottom */, char * /* top */); GC_API void GC_CALL GC_push_conditional(char * /* bottom */, char * /* top */, int /* bool all */); +GC_API void GC_CALL GC_push_finalizer_structures(void); /* Set and get the client push-other-roots procedure. A client */ /* supplied procedure should also call the original procedure. */ @@ -287,6 +295,21 @@ typedef void (GC_CALLBACK * GC_push_other_roots_proc)(void); GC_API void GC_CALL GC_set_push_other_roots(GC_push_other_roots_proc); GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void); +/* Walk the GC heap visiting all reachable objects. Assume the caller */ +/* holds the allocation lock. Object base pointer, object size and */ +/* client custom data are passed to the callback (holding the lock). */ +typedef void (GC_CALLBACK *GC_reachable_object_proc)(void * /* obj */, + size_t /* bytes */, + void * /* client_data */); +GC_API void GC_CALL GC_enumerate_reachable_objects_inner( + GC_reachable_object_proc, + void * /* client_data */) GC_ATTR_NONNULL(1); + +GC_API int GC_CALL GC_is_tmp_root(void *); + +GC_API void GC_CALL GC_print_trace(GC_word /* gc_no */); +GC_API void GC_CALL GC_print_trace_inner(GC_word /* gc_no */); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/src/bdwgc/include/gc_pthread_redirects.h b/src/bdwgc/include/gc_pthread_redirects.h index 0d571e913..8dcf7ebf6 100644 --- a/src/bdwgc/include/gc_pthread_redirects.h +++ b/src/bdwgc/include/gc_pthread_redirects.h @@ -33,15 +33,23 @@ #ifndef GC_PTHREAD_REDIRECTS_ONLY # include +# ifndef GC_SUSPEND_THREAD_ID +# define GC_SUSPEND_THREAD_ID pthread_t +# endif + # ifndef GC_NO_DLOPEN # include GC_API void *GC_dlopen(const char * /* path */, int /* mode */); # endif /* !GC_NO_DLOPEN */ # ifndef GC_NO_PTHREAD_SIGMASK -# include - GC_API int GC_pthread_sigmask(int /* how */, const sigset_t *, - sigset_t * /* oset */); +# include /* needed anyway for proper redirection */ +# if defined(GC_PTHREAD_SIGMASK_NEEDED) \ + || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) \ + || (_POSIX_C_SOURCE >= 199506L) || (_XOPEN_SOURCE >= 500) + GC_API int GC_pthread_sigmask(int /* how */, const sigset_t *, + sigset_t * /* oset */); +# endif # endif /* !GC_NO_PTHREAD_SIGMASK */ # ifndef GC_PTHREAD_CREATE_CONST @@ -59,7 +67,7 @@ GC_API int GC_pthread_cancel(pthread_t); # endif -# if defined(GC_PTHREAD_EXIT_ATTRIBUTE) && !defined(GC_PTHREAD_EXIT_DECLARED) +# if defined(GC_HAVE_PTHREAD_EXIT) && !defined(GC_PTHREAD_EXIT_DECLARED) # define GC_PTHREAD_EXIT_DECLARED GC_API void GC_pthread_exit(void *) GC_PTHREAD_EXIT_ATTRIBUTE; # endif @@ -88,7 +96,7 @@ # undef pthread_cancel # define pthread_cancel GC_pthread_cancel # endif -# ifdef GC_PTHREAD_EXIT_ATTRIBUTE +# ifdef GC_HAVE_PTHREAD_EXIT # undef pthread_exit # define pthread_exit GC_pthread_exit # endif diff --git a/src/bdwgc/include/gc_typed.h b/src/bdwgc/include/gc_typed.h index 8261cd7b1..06e8261e8 100644 --- a/src/bdwgc/include/gc_typed.h +++ b/src/bdwgc/include/gc_typed.h @@ -50,7 +50,7 @@ typedef GC_word * GC_bitmap; typedef GC_word GC_descr; GC_API GC_descr GC_CALL GC_make_descriptor(const GC_word * /* GC_bitmap bm */, - size_t /* len */); + size_t /* len (number_of_bits_in_bitmap) */); /* Return a type descriptor for the object whose layout */ /* is described by the argument. */ /* The least significant bit of the first word is one */ @@ -81,8 +81,10 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL GC_malloc_explicitly_typed(size_t /* size_in_bytes */, GC_descr /* d */); /* Allocate an object whose layout is described by d. */ - /* The resulting object MAY NOT BE PASSED TO REALLOC. */ - /* The returned object is cleared. */ + /* The size may NOT be less than the number of */ + /* meaningful bits in the bitmap of d multiplied by */ + /* sizeof GC_word. The returned object is cleared. */ + /* The returned object may NOT be passed to GC_realloc. */ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL GC_malloc_explicitly_typed_ignore_off_page(size_t /* size_in_bytes */, @@ -97,7 +99,9 @@ GC_API GC_ATTR_MALLOC void * GC_CALL /* The element size must be a multiple of the byte */ /* alignment required for pointers. E.g. on a 32-bit */ /* machine with 16-bit aligned pointers, size_in_bytes */ - /* must be a multiple of 2. */ + /* must be a multiple of 2. The element size may NOT */ + /* be less than the number of meaningful bits in the */ + /* bitmap of d multiplied by sizeof GC_word. */ /* Returned object is cleared. */ #ifdef GC_DEBUG diff --git a/src/bdwgc/include/gc_version.h b/src/bdwgc/include/gc_version.h index 00cde55f8..e780ab546 100644 --- a/src/bdwgc/include/gc_version.h +++ b/src/bdwgc/include/gc_version.h @@ -29,8 +29,8 @@ /* Eventually this one may become unnecessary. For now we need */ /* it to keep the old-style build process working. */ #define GC_TMP_VERSION_MAJOR 7 -#define GC_TMP_VERSION_MINOR 5 -#define GC_TMP_VERSION_MICRO 0 /* 7.5.0 */ +#define GC_TMP_VERSION_MINOR 6 +#define GC_TMP_VERSION_MICRO 8 /* 7.6.8 */ #ifdef GC_VERSION_MAJOR # if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR \ diff --git a/src/bdwgc/include/javaxfc.h b/src/bdwgc/include/javaxfc.h index 99eaf9ad8..2a77ea6ce 100644 --- a/src/bdwgc/include/javaxfc.h +++ b/src/bdwgc/include/javaxfc.h @@ -33,13 +33,28 @@ * must be prepared to deal with objects that have been finalized in * spite of the fact that they are still referenced by statically * allocated pointer variables. - * 1) It may mean that we get stuck in an infinite loop running + * 2) It may mean that we get stuck in an infinite loop running * finalizers which create new finalizable objects, though that's * probably unlikely. * Thus this is not recommended for general use. */ GC_API void GC_CALL GC_finalize_all(void); +#ifdef GC_THREADS + /* External thread suspension support. No thread suspension count */ + /* (so a thread which has been suspended numerous times will be */ + /* resumed with the very first call to GC_resume_thread). */ + /* Acquire the allocation lock. Thread should be registered in GC */ + /* (otherwise no-op, GC_is_thread_suspended returns false). */ + /* Unimplemented on some platforms. Not recommended for general use. */ +# ifndef GC_SUSPEND_THREAD_ID +# define GC_SUSPEND_THREAD_ID void* +# endif + GC_API void GC_CALL GC_suspend_thread(GC_SUSPEND_THREAD_ID); + GC_API void GC_CALL GC_resume_thread(GC_SUSPEND_THREAD_ID); + GC_API int GC_CALL GC_is_thread_suspended(GC_SUSPEND_THREAD_ID); +#endif /* GC_THREADS */ + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/src/bdwgc/include/new_gc_alloc.h b/src/bdwgc/include/new_gc_alloc.h index 94020cdd6..eeb8ff0b7 100644 --- a/src/bdwgc/include/new_gc_alloc.h +++ b/src/bdwgc/include/new_gc_alloc.h @@ -12,15 +12,15 @@ */ // -// This is a revision of gc_alloc.h for SGI STL versions > 3.0 -// Unlike earlier versions, it supplements the standard "alloc.h" +// This is a revision of gc_allocator.h for SGI STL versions > 3.0. +// Unlike earlier versions, it supplements the standard (STL) alloc.h // instead of replacing it. // // This is sloppy about variable names used in header files. // It also doesn't yet understand the new header file names or // namespaces. // -// This assumes the collector has been compiled with -DATOMIC_UNCOLLECTABLE. +// This assumes the collector has been compiled with -DGC_ATOMIC_UNCOLLECTABLE. // The user should also consider -DREDIRECT_MALLOC=GC_uncollectable_malloc, // to ensure that object allocated through malloc are traced. // @@ -85,11 +85,13 @@ extern "C" { GC_API void GC_CALL GC_incr_bytes_allocd(size_t bytes); GC_API void GC_CALL GC_incr_bytes_freed(size_t bytes); - - GC_API char * GC_CALL GC_generic_malloc_words_small(size_t word, int kind); - /* FIXME: Doesn't exist anymore. */ } +#define GC_generic_malloc_words_small(lw, k) \ + GC_generic_malloc((lw) * sizeof(GC_word), k) + +#define GC_ALLOCATOR_THROW_OR_ABORT() GC_abort_on_oom() + // Object kinds; must match PTRFREE, NORMAL, UNCOLLECTABLE, and // AUNCOLLECTABLE in gc_priv.h. @@ -98,11 +100,15 @@ enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2, enum { GC_max_fast_bytes = 255 }; -enum { GC_bytes_per_word = sizeof(char *) }; - enum { GC_byte_alignment = 8 }; -enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word }; +#if defined(CPPCHECK) + const unsigned GC_bytes_per_word = sizeof(char *); + const unsigned GC_word_alignment = GC_byte_alignment/GC_bytes_per_word; +#else + enum { GC_bytes_per_word = sizeof(char *) }; + enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word }; +#endif inline void * &GC_obj_link(void * p) { return *reinterpret_cast(p); } @@ -156,6 +162,10 @@ size_t GC_aux_template::GC_uncollectable_bytes_recently_freed = 0; template void * GC_aux_template::GC_out_of_line_malloc(size_t nwords, int kind) { + void * op = GC_generic_malloc_words_small(nwords, kind); + if (0 == op) + GC_ALLOCATOR_THROW_OR_ABORT(); + GC_bytes_recently_allocd += GC_uncollectable_bytes_recently_allocd; GC_non_gc_bytes += GC_uncollectable_bytes_recently_allocd; @@ -170,8 +180,7 @@ void * GC_aux_template::GC_out_of_line_malloc(size_t nwords, int kind) GC_incr_bytes_freed(GC_bytes_recently_freed); GC_bytes_recently_freed = 0; - - return GC_generic_malloc_words_small(nwords, kind); + return op; } typedef GC_aux_template<0> GC_aux; @@ -189,9 +198,15 @@ class single_client_gc_alloc_template { void ** flh; void * op; - if (n > GC_max_fast_bytes) return GC_malloc(n); - flh = GC_objfreelist_ptr + nwords; - if (0 == (op = *flh)) { + if (n > GC_max_fast_bytes) { + op = GC_malloc(n); + if (0 == op) + GC_ALLOCATOR_THROW_OR_ABORT(); + return op; + } + flh = &GC_objfreelist_ptr[nwords]; + op = *flh; + if (0 == op) { return GC_aux::GC_out_of_line_malloc(nwords, GC_NORMAL); } *flh = GC_obj_link(op); @@ -204,9 +219,15 @@ class single_client_gc_alloc_template { void ** flh; void * op; - if (n > GC_max_fast_bytes) return GC_malloc_atomic(n); - flh = GC_aobjfreelist_ptr + nwords; - if (0 == (op = *flh)) { + if (n > GC_max_fast_bytes) { + op = GC_malloc_atomic(n); + if (0 == op) + GC_ALLOCATOR_THROW_OR_ABORT(); + return op; + } + flh = &GC_aobjfreelist_ptr[nwords]; + op = *flh; + if (0 == op) { return GC_aux::GC_out_of_line_malloc(nwords, GC_PTRFREE); } *flh = GC_obj_link(op); @@ -215,13 +236,12 @@ class single_client_gc_alloc_template { } static void deallocate(void *p, size_t n) { - size_t nwords = GC_round_up(n); - void ** flh; - if (n > GC_max_fast_bytes) { GC_free(p); } else { - flh = GC_objfreelist_ptr + nwords; + size_t nwords = GC_round_up(n); + void ** flh = &GC_objfreelist_ptr[nwords]; + GC_obj_link(p) = *flh; memset(reinterpret_cast(p) + GC_bytes_per_word, 0, GC_bytes_per_word * (nwords - 1)); @@ -231,13 +251,12 @@ class single_client_gc_alloc_template { } static void ptr_free_deallocate(void *p, size_t n) { - size_t nwords = GC_round_up(n); - void ** flh; - if (n > GC_max_fast_bytes) { GC_free(p); } else { - flh = GC_aobjfreelist_ptr + nwords; + size_t nwords = GC_round_up(n); + void ** flh = &GC_aobjfreelist_ptr[nwords]; + GC_obj_link(p) = *flh; *flh = p; GC_aux::GC_bytes_recently_freed += nwords * GC_bytes_per_word; @@ -257,9 +276,15 @@ class single_client_traceable_alloc_template { void ** flh; void * op; - if (n > GC_max_fast_bytes) return GC_malloc_uncollectable(n); - flh = GC_uobjfreelist_ptr + nwords; - if (0 == (op = *flh)) { + if (n > GC_max_fast_bytes) { + op = GC_malloc_uncollectable(n); + if (0 == op) + GC_ALLOCATOR_THROW_OR_ABORT(); + return op; + } + flh = &GC_uobjfreelist_ptr[nwords]; + op = *flh; + if (0 == op) { return GC_aux::GC_out_of_line_malloc(nwords, GC_UNCOLLECTABLE); } *flh = GC_obj_link(op); @@ -273,9 +298,15 @@ class single_client_traceable_alloc_template { void ** flh; void * op; - if (n > GC_max_fast_bytes) return GC_malloc_atomic_uncollectable(n); - flh = GC_auobjfreelist_ptr + nwords; - if (0 == (op = *flh)) { + if (n > GC_max_fast_bytes) { + op = GC_malloc_atomic_uncollectable(n); + if (0 == op) + GC_ALLOCATOR_THROW_OR_ABORT(); + return op; + } + flh = &GC_auobjfreelist_ptr[nwords]; + op = *flh; + if (0 == op) { return GC_aux::GC_out_of_line_malloc(nwords, GC_AUNCOLLECTABLE); } *flh = GC_obj_link(op); @@ -285,13 +316,12 @@ class single_client_traceable_alloc_template { } static void deallocate(void *p, size_t n) { - size_t nwords = GC_round_up_uncollectable(n); - void ** flh; - if (n > GC_max_fast_bytes) { GC_free(p); } else { - flh = GC_uobjfreelist_ptr + nwords; + size_t nwords = GC_round_up_uncollectable(n); + void ** flh = &GC_uobjfreelist_ptr[nwords]; + GC_obj_link(p) = *flh; *flh = p; GC_aux::GC_uncollectable_bytes_recently_freed += @@ -300,13 +330,12 @@ class single_client_traceable_alloc_template { } static void ptr_free_deallocate(void *p, size_t n) { - size_t nwords = GC_round_up_uncollectable(n); - void ** flh; - if (n > GC_max_fast_bytes) { GC_free(p); } else { - flh = GC_auobjfreelist_ptr + nwords; + size_t nwords = GC_round_up_uncollectable(n); + void ** flh = &GC_auobjfreelist_ptr[nwords]; + GC_obj_link(p) = *flh; *flh = p; GC_aux::GC_uncollectable_bytes_recently_freed += @@ -320,9 +349,18 @@ typedef single_client_traceable_alloc_template<0> single_client_traceable_alloc; template < int dummy > class gc_alloc_template { public: - static void * allocate(size_t n) { return GC_malloc(n); } - static void * ptr_free_allocate(size_t n) - { return GC_malloc_atomic(n); } + static void * allocate(size_t n) { + void * op = GC_malloc(n); + if (0 == op) + GC_ALLOCATOR_THROW_OR_ABORT(); + return op; + } + static void * ptr_free_allocate(size_t n) { + void * op = GC_malloc_atomic(n); + if (0 == op) + GC_ALLOCATOR_THROW_OR_ABORT(); + return op; + } static void deallocate(void *, size_t) { } static void ptr_free_deallocate(void *, size_t) { } }; @@ -332,9 +370,18 @@ typedef gc_alloc_template < 0 > gc_alloc; template < int dummy > class traceable_alloc_template { public: - static void * allocate(size_t n) { return GC_malloc_uncollectable(n); } - static void * ptr_free_allocate(size_t n) - { return GC_malloc_atomic_uncollectable(n); } + static void * allocate(size_t n) { + void * op = GC_malloc_uncollectable(n); + if (0 == op) + GC_ALLOCATOR_THROW_OR_ABORT(); + return op; + } + static void * ptr_free_allocate(size_t n) { + void * op = GC_malloc_atomic_uncollectable(n); + if (0 == op) + GC_ALLOCATOR_THROW_OR_ABORT(); + return op; + } static void deallocate(void *p, size_t) { GC_free(p); } static void ptr_free_deallocate(void *p, size_t) { GC_free(p); } }; @@ -351,12 +398,12 @@ typedef traceable_alloc_template < 0 > traceable_alloc; class simple_alloc { \ public: \ static T *allocate(size_t n) \ - { return 0 == n? 0 : \ - reinterpret_cast(alloc::ptr_free_allocate(n * sizeof(T))); } \ + { reinterpret_cast(alloc::ptr_free_allocate(0 == n ? 1 \ + : n * sizeof(T))); } \ static T *allocate(void) \ { return reinterpret_cast(alloc::ptr_free_allocate(sizeof(T))); } \ static void deallocate(T *p, size_t n) \ - { if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof(T)); } \ + { alloc::ptr_free_deallocate(p, 0 == n ? 1 : n * sizeof(T)); } \ static void deallocate(T *p) \ { alloc::ptr_free_deallocate(p, sizeof(T)); } \ }; diff --git a/src/bdwgc/include/private/dbg_mlc.h b/src/bdwgc/include/private/dbg_mlc.h index deda69c7c..1ec0e97ee 100644 --- a/src/bdwgc/include/private/dbg_mlc.h +++ b/src/bdwgc/include/private/dbg_mlc.h @@ -78,7 +78,7 @@ typedef struct { /* We're careful never to overwrite a value with lsb 0. */ # if ALIGNMENT == 1 /* Fudge back pointer to be even. */ -# define HIDE_BACK_PTR(p) GC_HIDE_POINTER(~1 & (GC_word)(p)) +# define HIDE_BACK_PTR(p) GC_HIDE_POINTER(~1 & (word)(p)) # else # define HIDE_BACK_PTR(p) GC_HIDE_POINTER(p) # endif @@ -121,8 +121,7 @@ typedef struct { #define SIMPLE_ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1) /* ADD_CALL_CHAIN stores a (partial) call chain into an object */ -/* header. It may be called with or without the allocation */ -/* lock. */ +/* header; it should be called with the allocation lock held. */ /* PRINT_CALL_CHAIN prints the call chain stored in an object */ /* to stderr. It requires that we do not hold the lock. */ #if defined(SAVE_CALL_CHAIN) @@ -157,6 +156,10 @@ typedef struct { #endif #if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) +# ifdef SHORT_DBG_HDRS +# error Non-ptr stored in object results in GC_HAS_DEBUG_INFO malfunction + /* We may mistakenly conclude that p has a debugging wrapper. */ +# endif # define GC_HAS_DEBUG_INFO(p) \ ((*((word *)p) & 1) && GC_has_other_debug_info(p) > 0) #else diff --git a/src/bdwgc/include/private/gc_hdrs.h b/src/bdwgc/include/private/gc_hdrs.h index 89914284b..a7892a31f 100644 --- a/src/bdwgc/include/private/gc_hdrs.h +++ b/src/bdwgc/include/private/gc_hdrs.h @@ -18,7 +18,7 @@ typedef struct hblkhdr hdr; #if CPP_WORDSZ != 32 && CPP_WORDSZ < 36 - --> Get a real machine. +# error Get a real machine #endif /* @@ -98,22 +98,21 @@ typedef struct hce { #endif /* Set hhdr to the header for p. Analogous to GET_HDR below, */ -/* except that in the case of large objects, it */ -/* gets the header for the object beginning, if GC_all_interior_ptrs */ -/* is set. */ +/* except that in the case of large objects, it gets the header for */ +/* the object beginning if GC_all_interior_pointers is set. */ /* Returns zero if p points to somewhere other than the first page */ /* of an object, and it is not a valid pointer to the object. */ -#define HC_GET_HDR(p, hhdr, source, exit_label) \ - do { \ +#define HC_GET_HDR(p, hhdr, source) \ + { /* cannot use do-while(0) here */ \ hdr_cache_entry * hce = HCE(p); \ if (EXPECT(HCE_VALID_FOR(hce, p), TRUE)) { \ HC_HIT(); \ hhdr = hce -> hce_hdr; \ } else { \ hhdr = HEADER_CACHE_MISS(p, hce, source); \ - if (0 == hhdr) goto exit_label; \ + if (NULL == hhdr) break; /* go to the enclosing loop end */ \ } \ - } while (0) + } typedef struct bi { hdr * index[BOTTOM_SZ]; diff --git a/src/bdwgc/include/private/gc_locks.h b/src/bdwgc/include/private/gc_locks.h index 6507609bd..d08dcc401 100644 --- a/src/bdwgc/include/private/gc_locks.h +++ b/src/bdwgc/include/private/gc_locks.h @@ -36,8 +36,12 @@ # include # include GC_EXTERN PCR_Th_ML GC_allocate_ml; -# define DCL_LOCK_STATE \ +# if defined(CPPCHECK) +# define DCL_LOCK_STATE /* empty */ +# else +# define DCL_LOCK_STATE \ PCR_ERes GC_fastLockRes; PCR_sigset_t GC_old_sig_mask +# endif # define UNCOND_LOCK() PCR_Th_ML_Acquire(&GC_allocate_ml) # define UNCOND_UNLOCK() PCR_Th_ML_Release(&GC_allocate_ml) # endif @@ -99,7 +103,7 @@ # define NUMERIC_THREAD_ID_UNIQUE # endif # else /* pthreads-win32 */ -# define NUMERIC_THREAD_ID(id) ((unsigned long)(id.p)) +# define NUMERIC_THREAD_ID(id) ((unsigned long)(word)(id.p)) /* Using documented internal details of pthreads-win32 library. */ /* Faster than pthread_equal(). Should not change with */ /* future versions of pthreads-win32 library. */ @@ -133,8 +137,7 @@ AO_CLEAR(&GC_allocate_lock); } # else # define UNCOND_LOCK() \ - { GC_ASSERT(I_DONT_HOLD_LOCK()); \ - if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \ + { if (AO_test_and_set_acquire(&GC_allocate_lock) == AO_TS_SET) \ GC_lock(); } # define UNCOND_UNLOCK() AO_CLEAR(&GC_allocate_lock) # endif /* !GC_ASSERTIONS */ @@ -154,11 +157,7 @@ pthread_mutex_unlock(&GC_allocate_ml); } # else /* !GC_ASSERTIONS */ # if defined(NO_PTHREAD_TRYLOCK) -# ifdef USE_SPIN_LOCK -# define UNCOND_LOCK() GC_lock() -# else -# define UNCOND_LOCK() pthread_mutex_lock(&GC_allocate_ml) -# endif +# define UNCOND_LOCK() pthread_mutex_lock(&GC_allocate_ml) # else # define UNCOND_LOCK() \ { if (0 != pthread_mutex_trylock(&GC_allocate_ml)) \ @@ -183,15 +182,25 @@ || GC_lock_holder != NUMERIC_THREAD_ID(pthread_self())) # endif # endif /* GC_ASSERTIONS */ - GC_EXTERN volatile GC_bool GC_collecting; -# define ENTER_GC() GC_collecting = 1; -# define EXIT_GC() GC_collecting = 0; +# ifndef GC_WIN32_THREADS + GC_EXTERN volatile GC_bool GC_collecting; +# define ENTER_GC() (void)(GC_collecting = TRUE) +# define EXIT_GC() (void)(GC_collecting = FALSE) +# endif GC_INNER void GC_lock(void); -# endif /* GC_PTHREADS with linux_threads.c implementation */ -# ifdef GC_ALWAYS_MULTITHREADED +# endif /* GC_PTHREADS */ +# if defined(GC_ALWAYS_MULTITHREADED) \ + && (defined(USE_PTHREAD_LOCKS) || defined(USE_SPIN_LOCK)) # define GC_need_to_lock TRUE +# define set_need_to_lock() (void)0 # else +# if defined(GC_ALWAYS_MULTITHREADED) && !defined(CPPCHECK) +# error Runtime initialization of GC lock is needed! +# endif +# undef GC_ALWAYS_MULTITHREADED GC_EXTERN GC_bool GC_need_to_lock; +# define set_need_to_lock() (void)(GC_need_to_lock = TRUE) + /* We are multi-threaded now. */ # endif # else /* !THREADS */ @@ -207,7 +216,8 @@ # endif /* !THREADS */ #if defined(UNCOND_LOCK) && !defined(LOCK) -# if defined(LINT2) || defined(GC_ALWAYS_MULTITHREADED) +# if (defined(LINT2) && defined(USE_PTHREAD_LOCKS)) \ + || defined(GC_ALWAYS_MULTITHREADED) /* Instruct code analysis tools not to care about GC_need_to_lock */ /* influence to LOCK/UNLOCK semantic. */ # define LOCK() UNCOND_LOCK() diff --git a/src/bdwgc/include/private/gc_pmark.h b/src/bdwgc/include/private/gc_pmark.h index 76fcd1f51..4766a5350 100644 --- a/src/bdwgc/include/private/gc_pmark.h +++ b/src/bdwgc/include/private/gc_pmark.h @@ -22,7 +22,7 @@ #ifndef GC_PMARK_H #define GC_PMARK_H -#ifdef HAVE_CONFIG_H +#if defined(HAVE_CONFIG_H) && !defined(GC_PRIVATE_H) # include "config.h" #endif @@ -30,6 +30,12 @@ # define GC_BUILD #endif +#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)) \ + && !defined(_GNU_SOURCE) && defined(GC_PTHREADS) \ + && !defined(GC_NO_PTHREAD_SIGMASK) +# define _GNU_SOURCE 1 +#endif + #if defined(KEEP_BACK_PTRS) || defined(PRINT_BLACK_LIST) # include "dbg_mlc.h" #endif @@ -130,57 +136,54 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp); /* Push the contents of current onto the mark stack if it is a valid */ /* ptr to a currently unmarked object. Mark it. */ -/* If we assumed a standard-conforming compiler, we could probably */ -/* generate the exit_label transparently. */ -#define PUSH_CONTENTS(current, mark_stack_top, mark_stack_limit, \ - source, exit_label) \ +#define PUSH_CONTENTS(current, mark_stack_top, mark_stack_limit, source) \ do { \ hdr * my_hhdr; \ - HC_GET_HDR(current, my_hhdr, source, exit_label); \ + HC_GET_HDR(current, my_hhdr, source); /* contains "break" */ \ PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \ - source, exit_label, my_hhdr, TRUE); \ - exit_label: ; \ + source, my_hhdr, TRUE); \ } while (0) -/* Set mark bit, exit if it was already set. */ +/* Set mark bit, exit (using "break" statement) if it is already set. */ #ifdef USE_MARK_BYTES /* There is a race here, and we may set */ /* the bit twice in the concurrent case. This can result in the */ /* object being pushed twice. But that's only a performance issue. */ -# define SET_MARK_BIT_EXIT_IF_SET(hhdr,bit_no,exit_label) \ - do { \ +# define SET_MARK_BIT_EXIT_IF_SET(hhdr, bit_no) \ + { /* cannot use do-while(0) here */ \ char * mark_byte_addr = (char *)hhdr -> hb_marks + (bit_no); \ - if (*mark_byte_addr) goto exit_label; \ + if (*mark_byte_addr != 0) break; /* go to the enclosing loop end */ \ *mark_byte_addr = 1; \ - } while (0) + } #else # ifdef PARALLEL_MARK /* This is used only if we explicitly set USE_MARK_BITS. */ /* The following may fail to exit even if the bit was already set. */ /* For our uses, that's benign: */ -# define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \ - do { \ +# define OR_WORD_EXIT_IF_SET(addr, bits) \ + { /* cannot use do-while(0) here */ \ if (!(*(addr) & (bits))) { \ AO_or((volatile AO_t *)(addr), (AO_t)(bits)); \ } else { \ - goto exit_label; \ + break; /* go to the enclosing loop end */ \ } \ - } while (0) + } # else -# define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \ - do { \ +# define OR_WORD_EXIT_IF_SET(addr, bits) \ + { /* cannot use do-while(0) here */ \ word old = *(addr); \ word my_bits = (bits); \ - if (old & my_bits) goto exit_label; \ - *(addr) = (old | my_bits); \ - } while (0) + if ((old & my_bits) != 0) \ + break; /* go to the enclosing loop end */ \ + *(addr) = old | my_bits; \ + } # endif /* !PARALLEL_MARK */ -# define SET_MARK_BIT_EXIT_IF_SET(hhdr,bit_no,exit_label) \ - do { \ +# define SET_MARK_BIT_EXIT_IF_SET(hhdr, bit_no) \ + { /* cannot use do-while(0) here */ \ word * mark_word_addr = hhdr -> hb_marks + divWORDSZ(bit_no); \ - OR_WORD_EXIT_IF_SET(mark_word_addr, (word)1 << modWORDSZ(bit_no), \ - exit_label); \ - } while (0) + OR_WORD_EXIT_IF_SET(mark_word_addr, \ + (word)1 << modWORDSZ(bit_no)); /* contains "break" */ \ + } #endif /* !USE_MARK_BYTES */ #ifdef PARALLEL_MARK @@ -228,7 +231,7 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp); /* interior of a large object. */ #ifdef MARK_BIT_PER_GRANULE # define PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \ - source, exit_label, hhdr, do_offset_check) \ + source, hhdr, do_offset_check) \ do { \ size_t displ = HBLKDISPL(current); /* Displacement in block; in bytes. */\ /* displ is always within range. If current doesn't point to */ \ @@ -252,7 +255,7 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp); } else { \ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \ - goto exit_label; \ + break; /* go to the end of PUSH_CONTENTS_HDR */ \ } \ } \ gran_displ = 0; \ @@ -264,7 +267,7 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp); + byte_offset; \ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \ - goto exit_label; \ + break; \ } \ gran_displ -= gran_offset; \ base -= obj_displ; \ @@ -274,31 +277,27 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp); GC_ASSERT(gran_displ % BYTES_TO_GRANULES(hhdr -> hb_sz) == 0); \ TRACE(source, GC_log_printf("GC #%u: passed validity tests\n", \ (unsigned)GC_gc_no)); \ - SET_MARK_BIT_EXIT_IF_SET(hhdr, gran_displ, exit_label); \ + SET_MARK_BIT_EXIT_IF_SET(hhdr, gran_displ); \ TRACE(source, GC_log_printf("GC #%u: previously unmarked\n", \ (unsigned)GC_gc_no)); \ TRACE_TARGET(base, \ GC_log_printf("GC #%u: marking %p from %p instead\n", \ - (unsigned)GC_gc_no, base, source)); \ + (unsigned)GC_gc_no, (void *)base, (void *)(source))); \ INCR_MARKS(hhdr); \ - GC_STORE_BACK_PTR((ptr_t)source, base); \ + GC_STORE_BACK_PTR((ptr_t)(source), base); \ PUSH_OBJ(base, hhdr, mark_stack_top, mark_stack_limit); \ } while (0) #endif /* MARK_BIT_PER_GRANULE */ #ifdef MARK_BIT_PER_OBJ # define PUSH_CONTENTS_HDR(current, mark_stack_top, mark_stack_limit, \ - source, exit_label, hhdr, do_offset_check) \ + source, hhdr, do_offset_check) \ do { \ size_t displ = HBLKDISPL(current); /* Displacement in block; in bytes. */\ - unsigned32 low_prod, high_prod; \ + unsigned32 high_prod; \ unsigned32 inv_sz = hhdr -> hb_inv_sz; \ - ptr_t base = current; \ - LONG_MULT(high_prod, low_prod, displ, inv_sz); \ - /* product is > and within sz_in_bytes of displ * sz_in_bytes * 2**32 */ \ - if (EXPECT(low_prod >> 16 != 0, FALSE)) { \ - /* FIXME: fails if offset is a multiple of HBLKSIZE which becomes 0 */ \ - if (inv_sz == LARGE_INV_SZ) { \ + ptr_t base; \ + if (EXPECT(inv_sz == LARGE_INV_SZ, FALSE)) { \ size_t obj_displ; \ base = (ptr_t)(hhdr -> hb_block); \ obj_displ = (ptr_t)(current) - base; \ @@ -309,19 +308,25 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp); } else { \ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \ - goto exit_label; \ + break; /* go to the end of PUSH_CONTENTS_HDR */ \ } \ } \ GC_ASSERT(hhdr -> hb_sz > HBLKSIZE || \ hhdr -> hb_block == HBLKPTR(current)); \ - GC_ASSERT((word)hhdr->hb_block < (word)(current)); \ - } else { \ + GC_ASSERT((word)(hhdr)->hb_block <= (word)(current)); \ + high_prod = 0; \ + } else { \ + unsigned32 low_prod; \ + base = (ptr_t)(current); \ + LONG_MULT(high_prod, low_prod, (unsigned32)displ, inv_sz); \ + if ((low_prod >> 16) != 0) { \ + size_t obj_displ; \ /* Accurate enough if HBLKSIZE <= 2**15. */ \ GC_STATIC_ASSERT(HBLKSIZE <= (1 << 15)); \ - size_t obj_displ = (((low_prod >> 16) + 1) * (hhdr->hb_sz)) >> 16; \ + obj_displ = (((low_prod >> 16) + 1) * hhdr->hb_sz) >> 16; \ if (do_offset_check && !GC_valid_offsets[obj_displ]) { \ GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \ - goto exit_label; \ + break; \ } \ base -= obj_displ; \ } \ @@ -331,14 +336,14 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp); GC_ASSERT(high_prod <= HBLK_OBJS(hhdr -> hb_sz)); \ TRACE(source, GC_log_printf("GC #%u: passed validity tests\n", \ (unsigned)GC_gc_no)); \ - SET_MARK_BIT_EXIT_IF_SET(hhdr, high_prod, exit_label); \ + SET_MARK_BIT_EXIT_IF_SET(hhdr, high_prod); \ TRACE(source, GC_log_printf("GC #%u: previously unmarked\n", \ (unsigned)GC_gc_no)); \ TRACE_TARGET(base, \ GC_log_printf("GC #%u: marking %p from %p instead\n", \ - (unsigned)GC_gc_no, base, source)); \ + (unsigned)GC_gc_no, (void *)base, (void *)(source))); \ INCR_MARKS(hhdr); \ - GC_STORE_BACK_PTR((ptr_t)source, base); \ + GC_STORE_BACK_PTR((ptr_t)(source), base); \ PUSH_OBJ(base, hhdr, mark_stack_top, mark_stack_limit); \ } while (0) #endif /* MARK_BIT_PER_OBJ */ @@ -359,7 +364,7 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp); * if the mark stack overflows. */ -#if NEED_FIXUP_POINTER +#ifdef NEED_FIXUP_POINTER /* Try both the raw version and the fixed up one. */ # define GC_PUSH_ONE_STACK(p, source) \ do { \ @@ -439,34 +444,34 @@ typedef int mark_state_t; /* Current state of marking, as follows:*/ /* grungy if it was marked dirty in the */ /* last set of bits we retrieved. */ - /* Invariant I: all roots and marked */ + /* Invariant "I": all roots and marked */ /* objects p are either dirty, or point */ /* to objects q that are either marked */ /* or a pointer to q appears in a range */ /* on the mark stack. */ -#define MS_NONE 0 /* No marking in progress. I holds. */ +#define MS_NONE 0 /* No marking in progress. "I" holds. */ /* Mark stack is empty. */ #define MS_PUSH_RESCUERS 1 /* Rescuing objects are currently */ - /* being pushed. I holds, except */ + /* being pushed. "I" holds, except */ /* that grungy roots may point to */ /* unmarked objects, as may marked */ /* grungy objects above scan_ptr. */ -#define MS_PUSH_UNCOLLECTABLE 2 /* I holds, except that marked */ +#define MS_PUSH_UNCOLLECTABLE 2 /* "I" holds, except that marked */ /* uncollectible objects above scan_ptr */ /* may point to unmarked objects. */ /* Roots may point to unmarked objects */ -#define MS_ROOTS_PUSHED 3 /* I holds, mark stack may be nonempty */ +#define MS_ROOTS_PUSHED 3 /* "I" holds, mark stack may be nonempty. */ -#define MS_PARTIALLY_INVALID 4 /* I may not hold, e.g. because of M.S. */ - /* overflow. However marked heap */ - /* objects below scan_ptr point to */ - /* marked or stacked objects. */ +#define MS_PARTIALLY_INVALID 4 /* "I" may not hold, e.g. because of */ + /* the mark stack overflow. However */ + /* marked heap objects below scan_ptr */ + /* point to marked or stacked objects. */ -#define MS_INVALID 5 /* I may not hold. */ +#define MS_INVALID 5 /* "I" may not hold. */ GC_EXTERN mark_state_t GC_mark_state; diff --git a/src/bdwgc/include/private/gc_priv.h b/src/bdwgc/include/private/gc_priv.h index ffbcc5ba7..9080f05c0 100644 --- a/src/bdwgc/include/private/gc_priv.h +++ b/src/bdwgc/include/private/gc_priv.h @@ -37,6 +37,12 @@ # define _USING_POSIX4A_DRAFT10 1 #endif +#if defined(__MINGW32__) && !defined(__MINGW_EXCPT_DEFINE_PSDK) \ + && defined(__i386__) && defined(GC_EXTERN) /* defined in gc.c */ + /* See the description in mark.c. */ +# define __MINGW_EXCPT_DEFINE_PSDK 1 +#endif + # if defined(NO_DEBUGGING) && !defined(GC_ASSERTIONS) && !defined(NDEBUG) /* To turn off assertion checking (in atomic_ops.h). */ # define NDEBUG 1 @@ -90,10 +96,30 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /* byte displacements and which can be used */ /* for address comparisons. */ +#ifndef SIZE_MAX +# include +#endif +#if defined(SIZE_MAX) && !defined(CPPCHECK) +# define GC_SIZE_MAX ((size_t)SIZE_MAX) + /* Extra cast to workaround some buggy SIZE_MAX definitions. */ +#else +# define GC_SIZE_MAX (~(size_t)0) +#endif + +/* Saturated addition of size_t values. Used to avoid value wrap */ +/* around on overflow. The arguments should have no side effects. */ +#define SIZET_SAT_ADD(a, b) \ + ((a) < GC_SIZE_MAX - (b) ? (a) + (b) : GC_SIZE_MAX) + #ifndef GCCONFIG_H # include "gcconfig.h" #endif +#if !defined(GC_ATOMIC_UNCOLLECTABLE) && defined(ATOMIC_UNCOLLECTABLE) + /* For compatibility with old-style naming. */ +# define GC_ATOMIC_UNCOLLECTABLE +#endif + #ifndef GC_INNER /* This tagging macro must be used at the start of every variable */ /* definition which is declared with GC_EXTERN. Should be also used */ @@ -104,7 +130,7 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /* located in the "extra" folder). */ # if defined(GC_DLL) && defined(__GNUC__) && !defined(MSWIN32) \ && !defined(MSWINCE) && !defined(CYGWIN32) -# if __GNUC__ >= 4 +# if (__GNUC__ >= 4) && !defined(GC_NO_VISIBILITY) /* See the corresponding GC_API definition. */ # define GC_INNER __attribute__((__visibility__("hidden"))) # else @@ -129,6 +155,26 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # include "gc_hdrs.h" #endif +#ifndef GC_ATTR_NO_SANITIZE_ADDR +# ifndef ADDRESS_SANITIZER +# define GC_ATTR_NO_SANITIZE_ADDR /* empty */ +# elif __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 8) +# define GC_ATTR_NO_SANITIZE_ADDR __attribute__((no_sanitize("address"))) +# else +# define GC_ATTR_NO_SANITIZE_ADDR __attribute__((no_sanitize_address)) +# endif +#endif /* !GC_ATTR_NO_SANITIZE_ADDR */ + +#ifndef GC_ATTR_NO_SANITIZE_MEMORY +# ifndef MEMORY_SANITIZER +# define GC_ATTR_NO_SANITIZE_MEMORY /* empty */ +# elif __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 8) +# define GC_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) +# else +# define GC_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +# endif +#endif /* !GC_ATTR_NO_SANITIZE_MEMORY */ + #ifndef GC_ATTR_UNUSED # if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) # define GC_ATTR_UNUSED __attribute__((__unused__)) @@ -157,10 +203,20 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # define GC_INLINE static #endif +#ifndef GC_ATTR_NOINLINE +# if __GNUC__ >= 4 +# define GC_ATTR_NOINLINE __attribute__((__noinline__)) +# elif _MSC_VER >= 1400 +# define GC_ATTR_NOINLINE __declspec(noinline) +# else +# define GC_ATTR_NOINLINE /* empty */ +# endif +#endif + #ifndef GC_API_OSCALL /* This is used to identify GC routines called by name from OS. */ # if defined(__GNUC__) -# if __GNUC__ >= 4 +# if (__GNUC__ >= 4) && !defined(GC_NO_VISIBILITY) /* Same as GC_API if GC_DLL. */ # define GC_API_OSCALL extern __attribute__((__visibility__("default"))) # else @@ -250,36 +306,39 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ #ifndef GC_NO_FINALIZATION -# define GC_INVOKE_FINALIZERS() GC_notify_or_invoke_finalizers() - GC_INNER void GC_notify_or_invoke_finalizers(void); +# define GC_INVOKE_FINALIZERS() GC_notify_or_invoke_finalizers() + GC_INNER void GC_notify_or_invoke_finalizers(void); /* If GC_finalize_on_demand is not set, invoke */ /* eligible finalizers. Otherwise: */ /* Call *GC_finalizer_notifier if there are */ /* finalizers to be run, and we haven't called */ /* this procedure yet this GC cycle. */ - GC_INNER void GC_push_finalizer_structures(void); - GC_INNER void GC_finalize(void); + GC_INNER void GC_finalize(void); /* Perform all indicated finalization actions */ /* on unmarked objects. */ /* Unreachable finalizable objects are enqueued */ /* for processing by GC_invoke_finalizers. */ /* Invoked with lock. */ -# ifndef SMALL_CONFIG - GC_INNER void GC_print_finalization_stats(void); -# endif +# ifndef GC_TOGGLE_REFS_NOT_NEEDED + GC_INNER void GC_process_togglerefs(void); + /* Process the toggle-refs before GC starts. */ +# endif +# ifndef SMALL_CONFIG + GC_INNER void GC_print_finalization_stats(void); +# endif #else -# define GC_INVOKE_FINALIZERS() (void)0 +# define GC_INVOKE_FINALIZERS() (void)0 #endif /* GC_NO_FINALIZATION */ #if !defined(DONT_ADD_BYTE_AT_END) # ifdef LINT2 /* Explicitly instruct the code analysis tool that */ /* GC_all_interior_pointers is assumed to have only 0 or 1 value. */ -# define EXTRA_BYTES (GC_all_interior_pointers? 1 : 0) +# define EXTRA_BYTES ((size_t)(GC_all_interior_pointers? 1 : 0)) # else -# define EXTRA_BYTES GC_all_interior_pointers +# define EXTRA_BYTES (size_t)GC_all_interior_pointers # endif # define MAX_EXTRA_BYTES 1 #else @@ -420,7 +479,7 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # define BCOPY_EXISTS # endif -# ifndef BCOPY_EXISTS +# if !defined(BCOPY_EXISTS) || defined(CPPCHECK) # include # define BCOPY(x,y,n) memcpy(y, x, (size_t)(n)) # define BZERO(x,n) memset(x, 0, (size_t)(n)) @@ -455,8 +514,19 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ # endif # endif +#ifdef THREADS + GC_EXTERN GC_on_thread_event_proc GC_on_thread_event; +#endif + /* Abandon ship */ -# ifdef PCR +# if defined(SMALL_CONFIG) || defined(PCR) +# define GC_on_abort(msg) (void)0 /* be silent on abort */ +# else + GC_API_PRIV GC_abort_func GC_on_abort; +# endif +# if defined(CPPCHECK) +# define ABORT(msg) { GC_on_abort(msg); abort(); } +# elif defined(PCR) # define ABORT(s) PCR_Base_Panic(s) # else # if defined(MSWINCE) && !defined(DebugBreak) \ @@ -468,11 +538,6 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /* instead of defining it as a macro). */ # define DebugBreak() _exit(-1) /* there is no abort() in WinCE */ # endif -# ifdef SMALL_CONFIG -# define GC_on_abort(msg) (void)0 /* be silent on abort */ -# else - GC_API_PRIV GC_abort_func GC_on_abort; -# endif /* !SMALL_CONFIG */ # if defined(MSWIN32) && (defined(NO_DEBUGGING) || defined(LINT2)) /* A more user-friendly abort after showing fatal message. */ # define ABORT(msg) (GC_on_abort(msg), _exit(-1)) @@ -494,17 +559,18 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /* should match their format specifiers. */ #define ABORT_ARG1(C_msg, C_fmt, arg1) \ do { \ - GC_COND_LOG_PRINTF(C_msg /* + */ C_fmt, arg1); \ + GC_INFOLOG_PRINTF(C_msg /* + */ C_fmt "\n", arg1); \ ABORT(C_msg); \ } while (0) #define ABORT_ARG2(C_msg, C_fmt, arg1, arg2) \ do { \ - GC_COND_LOG_PRINTF(C_msg /* + */ C_fmt, arg1, arg2); \ + GC_INFOLOG_PRINTF(C_msg /* + */ C_fmt "\n", arg1, arg2); \ ABORT(C_msg); \ } while (0) #define ABORT_ARG3(C_msg, C_fmt, arg1, arg2, arg3) \ do { \ - GC_COND_LOG_PRINTF(C_msg /* + */ C_fmt, arg1, arg2, arg3); \ + GC_INFOLOG_PRINTF(C_msg /* + */ C_fmt "\n", \ + arg1, arg2, arg3); \ ABORT(C_msg); \ } while (0) @@ -524,7 +590,7 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /* The argument (if any) format specifier should be: */ /* "%s", "%p" or "%"WARN_PRIdPTR. */ #define WARN(msg, arg) (*GC_current_warn_proc)("GC Warning: " msg, \ - (GC_word)(arg)) + (word)(arg)) GC_EXTERN GC_warn_proc GC_current_warn_proc; /* Print format type macro for decimal signed_word value passed WARN(). */ @@ -537,11 +603,16 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; # define WARN_PRIdPTR "ld" #endif +/* A tagging macro (for a code static analyzer) to indicate that the */ +/* string obtained from an untrusted source (e.g., argv[], getenv) is */ +/* safe to use in a vulnerable operation (e.g., open, exec). */ +#define TRUSTED_STRING(s) (char*)COVERT_DATAFLOW(s) + /* Get environment entry */ #ifdef GC_READ_ENV_FILE GC_INNER char * GC_envfile_getenv(const char *name); # define GETENV(name) GC_envfile_getenv(name) -#elif defined(NO_GETENV) +#elif defined(NO_GETENV) && !defined(CPPCHECK) # define GETENV(name) NULL #elif defined(EMPTY_GETENV_RESULTS) /* Workaround for a reputed Wine bug. */ @@ -586,7 +657,8 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; # define GC_MACH_THREAD_STATE x86_THREAD_STATE64 # define GC_MACH_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT # endif -# elif defined(ARM32) && defined(ARM_UNIFIED_THREAD_STATE) +# elif defined(ARM32) && defined(ARM_UNIFIED_THREAD_STATE) \ + && !defined(CPPCHECK) # define GC_THREAD_STATE_T arm_unified_thread_state_t # define GC_MACH_THREAD_STATE ARM_UNIFIED_THREAD_STATE # define GC_MACH_THREAD_STATE_COUNT ARM_UNIFIED_THREAD_STATE_COUNT @@ -600,7 +672,7 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; # define GC_THREAD_STATE_T arm_thread_state64_t # define GC_MACH_THREAD_STATE ARM_THREAD_STATE64 # define GC_MACH_THREAD_STATE_COUNT ARM_THREAD_STATE64_COUNT -# else +# elif !defined(CPPCHECK) # error define GC_THREAD_STATE_T # endif # ifndef GC_MACH_THREAD_STATE @@ -624,17 +696,14 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; /* without __, thus hopefully, not breaking any existing */ /* Makefile.direct builds. */ # if __DARWIN_UNIX03 -# if defined(ARM32) && defined(ARM_UNIFIED_THREAD_STATE) -# define THREAD_FLD(x) ts_32.__ ## x -# else -# define THREAD_FLD(x) __ ## x -# endif +# define THREAD_FLD_NAME(x) __ ## x # else -# if defined(ARM32) && defined(ARM_UNIFIED_THREAD_STATE) -# define THREAD_FLD(x) ts_32. ## x -# else -# define THREAD_FLD(x) x -# endif +# define THREAD_FLD_NAME(x) x +# endif +# if defined(ARM32) && defined(ARM_UNIFIED_THREAD_STATE) +# define THREAD_FLD(x) ts_32.THREAD_FLD_NAME(x) +# else +# define THREAD_FLD(x) THREAD_FLD_NAME(x) # endif #endif /* DARWIN */ @@ -739,7 +808,7 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; # elif HBLKSIZE == 16384 # define CPP_LOG_HBLKSIZE 14 # else - --> fix HBLKSIZE +# error fix HBLKSIZE # endif # undef HBLKSIZE #endif @@ -748,11 +817,11 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; # define LOG_HBLKSIZE ((size_t)CPP_LOG_HBLKSIZE) # define HBLKSIZE ((size_t)CPP_HBLKSIZE) +#define GC_SQRT_SIZE_MAX ((((size_t)1) << (WORDSZ / 2)) - 1) -/* max size objects supported by freelist (larger objects are */ +/* Max size objects supported by freelist (larger objects are */ /* allocated directly with allchblk(), by rounding to the next */ -/* multiple of HBLKSIZE. */ - +/* multiple of HBLKSIZE). */ #define CPP_MAXOBJBYTES (CPP_HBLKSIZE/2) #define MAXOBJBYTES ((size_t)CPP_MAXOBJBYTES) #define CPP_MAXOBJWORDS BYTES_TO_WORDS(CPP_MAXOBJBYTES) @@ -772,17 +841,17 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; # define modHBLKSZ(n) ((n) & (HBLKSIZE-1)) -# define HBLKPTR(objptr) ((struct hblk *)(((word) (objptr)) & ~(HBLKSIZE-1))) - +# define HBLKPTR(objptr) ((struct hblk *)(((word)(objptr)) \ + & ~(word)(HBLKSIZE-1))) # define HBLKDISPL(objptr) (((size_t) (objptr)) & (HBLKSIZE-1)) /* Round up allocation size (in bytes) to a multiple of a granule. */ -#define ROUNDUP_GRANULE_SIZE(bytes) \ - (((bytes) + (GRANULE_BYTES - 1)) & ~(GRANULE_BYTES - 1)) +#define ROUNDUP_GRANULE_SIZE(lb) /* lb should have no side-effect */ \ + (SIZET_SAT_ADD(lb, GRANULE_BYTES - 1) & ~(GRANULE_BYTES - 1)) /* Round up byte allocation requests to integral number of words, etc. */ -# define ROUNDED_UP_GRANULES(n) \ - BYTES_TO_GRANULES((n) + (GRANULE_BYTES - 1 + EXTRA_BYTES)) +# define ROUNDED_UP_GRANULES(lb) /* lb should have no side-effect */ \ + BYTES_TO_GRANULES(SIZET_SAT_ADD(lb, GRANULE_BYTES - 1 + EXTRA_BYTES)) # if MAX_EXTRA_BYTES == 0 # define SMALL_OBJ(bytes) EXPECT((bytes) <= (MAXOBJBYTES), TRUE) # else @@ -792,7 +861,8 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; /* This really just tests bytes <= MAXOBJBYTES - EXTRA_BYTES. */ /* But we try to avoid looking up EXTRA_BYTES. */ # endif -# define ADD_SLOP(bytes) ((bytes) + EXTRA_BYTES) +# define ADD_SLOP(lb) /* lb should have no side-effect */ \ + SIZET_SAT_ADD(lb, EXTRA_BYTES) # ifndef MIN_WORDS # define MIN_WORDS 2 /* FIXME: obsolete */ # endif @@ -943,9 +1013,9 @@ struct hblkhdr { /* without generating a negative result. We avoid */ /* generating free blocks larger than that. */ word hb_descr; /* object descriptor for marking. See */ - /* mark.h. */ + /* gc_mark.h. */ # ifdef MARK_BIT_PER_GRANULE - short * hb_map; /* Essentially a table of remainders */ + unsigned short * hb_map; /* Essentially a table of remainders */ /* mod BYTES_TO_GRANULES(hb_sz), except */ /* for large blocks. See GC_obj_map. */ # endif @@ -1010,9 +1080,11 @@ struct hblk { # define HBLK_IS_FREE(hdr) (((hdr) -> hb_flags & FREE_BLK) != 0) -# define OBJ_SZ_TO_BLOCKS(sz) divHBLKSZ((sz) + HBLKSIZE-1) +# define OBJ_SZ_TO_BLOCKS(lb) divHBLKSZ((lb) + HBLKSIZE-1) +# define OBJ_SZ_TO_BLOCKS_CHECKED(lb) /* lb should have no side-effect */ \ + divHBLKSZ(SIZET_SAT_ADD(lb, HBLKSIZE - 1)) /* Size of block (in units of HBLKSIZE) needed to hold objects of */ - /* given sz (in bytes). */ + /* given lb (in bytes). The checked variant prevents wrap around. */ /* Object free list link */ # define obj_link(p) (*(void **)(p)) @@ -1206,17 +1278,17 @@ struct _GC_arrays { /* free list for objects */ # define GC_aobjfreelist GC_arrays._aobjfreelist void *_aobjfreelist[MAXOBJGRANULES+1]; - /* free list for atomic objs */ + /* free list for atomic objects */ # endif void *_uobjfreelist[MAXOBJGRANULES+1]; - /* Uncollectible but traced objs */ - /* objects on this and auobjfreelist */ + /* Uncollectible but traced objects. */ + /* Objects on this and _auobjfreelist */ /* are always marked, except during */ /* garbage collections. */ -# ifdef ATOMIC_UNCOLLECTABLE +# ifdef GC_ATOMIC_UNCOLLECTABLE # define GC_auobjfreelist GC_arrays._auobjfreelist void *_auobjfreelist[MAXOBJGRANULES+1]; - /* Atomic uncollectible but traced objs */ + /* Atomic uncollectible but traced objects. */ # endif size_t _size_map[MAXOBJBYTES+1]; /* Number of granules to allocate when asked for a certain */ @@ -1228,7 +1300,7 @@ struct _GC_arrays { # endif # ifdef MARK_BIT_PER_GRANULE # define GC_obj_map GC_arrays._obj_map - short * _obj_map[MAXOBJGRANULES+1]; + unsigned short * _obj_map[MAXOBJGRANULES + 1]; /* If not NULL, then a pointer to a map of valid */ /* object addresses. */ /* _obj_map[sz_in_granules][i] is */ @@ -1266,7 +1338,7 @@ struct _GC_arrays { volatile page_hash_table _dirty_pages; /* Pages dirtied since last GC_read_dirty. */ # endif -# if defined(PROC_VDB) || defined(GWW_VDB) +# if (defined(CHECKSUMS) && defined(GWW_VDB)) || defined(PROC_VDB) # define GC_written_pages GC_arrays._written_pages page_hash_table _written_pages; /* Pages ever dirtied */ # endif @@ -1335,16 +1407,17 @@ GC_API_PRIV GC_FAR struct _GC_arrays GC_arrays; #define USED_HEAP_SIZE (GC_heapsize - GC_large_free_bytes) /* Object kinds: */ -#define MAXOBJKINDS 16 - +#ifndef MAXOBJKINDS +# define MAXOBJKINDS 16 +#endif GC_EXTERN struct obj_kind { - void **ok_freelist; /* Array of free listheaders for this kind of object */ - /* Point either to GC_arrays or to storage allocated */ - /* with GC_scratch_alloc. */ + void **ok_freelist; /* Array of free list headers for this kind of */ + /* object. Point either to GC_arrays or to */ + /* storage allocated with GC_scratch_alloc. */ struct hblk **ok_reclaim_list; - /* List headers for lists of blocks waiting to be */ - /* swept. */ - /* Indexed by object size in granules. */ + /* List headers for lists of blocks waiting to */ + /* be swept. Indexed by object size in */ + /* granules. */ word ok_descriptor; /* Descriptor template for objects in this */ /* block. */ GC_bool ok_relocate_descr; @@ -1385,7 +1458,7 @@ GC_EXTERN struct obj_kind { # define endGC_objfreelist (beginGC_objfreelist + sizeof(GC_objfreelist)) extern ptr_t GC_aobjfreelist[MAXOBJGRANULES+1]; - /* free list for atomic (PTRFREE) objs */ + /* free list for atomic (PTRFREE) objects */ # define beginGC_aobjfreelist ((ptr_t)(&GC_aobjfreelist)) # define endGC_aobjfreelist (beginGC_aobjfreelist + sizeof(GC_aobjfreelist)) #endif /* SEPARATE_GLOBALS */ @@ -1394,7 +1467,7 @@ GC_EXTERN struct obj_kind { #define PTRFREE 0 #define NORMAL 1 #define UNCOLLECTABLE 2 -#ifdef ATOMIC_UNCOLLECTABLE +#ifdef GC_ATOMIC_UNCOLLECTABLE # define AUNCOLLECTABLE 3 # define STUBBORN 4 # define IS_UNCOLLECTABLE(k) (((k) & ~1) == UNCOLLECTABLE) @@ -1413,18 +1486,18 @@ GC_EXTERN word GC_n_heap_sects; /* Number of separately added heap */ /* sections. */ #endif -GC_EXTERN word GC_page_size; +GC_EXTERN size_t GC_page_size; /* Round up allocation size to a multiple of a page size. */ /* GC_setpagesize() is assumed to be already invoked. */ -#define ROUNDUP_PAGESIZE(bytes) \ - (((bytes) + GC_page_size - 1) & ~(GC_page_size - 1)) +#define ROUNDUP_PAGESIZE(lb) /* lb should have no side-effect */ \ + (SIZET_SAT_ADD(lb, GC_page_size - 1) & ~(GC_page_size - 1)) /* Same as above but used to make GET_MEM() argument safe. */ #ifdef MMAP_SUPPORTED -# define ROUNDUP_PAGESIZE_IF_MMAP(bytes) ROUNDUP_PAGESIZE(bytes) +# define ROUNDUP_PAGESIZE_IF_MMAP(lb) ROUNDUP_PAGESIZE(lb) #else -# define ROUNDUP_PAGESIZE_IF_MMAP(bytes) (bytes) +# define ROUNDUP_PAGESIZE_IF_MMAP(lb) (lb) #endif #if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) @@ -1451,7 +1524,8 @@ GC_EXTERN word GC_black_list_spacing; # define TRUE_INCREMENTAL FALSE #else GC_EXTERN GC_bool GC_incremental; - /* Using incremental/generational collection. */ + /* Using incremental/generational collection. */ + /* Assumes dirty bits are being maintained. */ # define TRUE_INCREMENTAL \ (GC_incremental && GC_time_limit != GC_TIME_UNLIMITED) /* True incremental, not just generational, mode */ @@ -1589,23 +1663,12 @@ GC_INNER void GC_initiate_gc(void); GC_INNER GC_bool GC_collection_in_progress(void); /* Collection is in progress, or was abandoned. */ -#ifndef GC_DISABLE_INCREMENTAL -# define GC_PUSH_CONDITIONAL(b, t, all) \ - GC_push_conditional((ptr_t)(b), (ptr_t)(t), all) - /* Do either of GC_push_all or GC_push_selected */ - /* depending on the third arg. */ -#else -# define GC_PUSH_CONDITIONAL(b, t, all) GC_push_all((ptr_t)(b), (ptr_t)(t)) -#endif +#define GC_PUSH_ALL_SYM(sym) \ + GC_push_all((ptr_t)&(sym), (ptr_t)&(sym) + sizeof(sym)) GC_INNER void GC_push_all_stack(ptr_t b, ptr_t t); /* As GC_push_all but consider */ /* interior pointers as valid. */ -GC_INNER void GC_push_all_eager(ptr_t b, ptr_t t); - /* Same as GC_push_all_stack, but */ - /* ensures that stack is scanned */ - /* immediately, not just scheduled */ - /* for scanning. */ /* In the threads case, we push part of the current thread stack */ /* with GC_push_all_eager when we push the registers. This gets the */ @@ -1634,7 +1697,7 @@ GC_EXTERN void (*GC_push_typed_structures)(void); /* the typed allocation support if unused. */ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), - ptr_t arg); + volatile ptr_t arg); #if defined(SPARC) || defined(IA64) /* Cause all stacked registers to be saved in memory. Return a */ @@ -1676,6 +1739,9 @@ GC_INNER void GC_set_fl_marks(ptr_t p); /* set. Abort if not. */ #endif void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp); +#ifdef USE_PROC_FOR_LIBRARIES + GC_INNER void GC_remove_roots_subregion(ptr_t b, ptr_t e); +#endif GC_INNER void GC_exclude_static_roots_inner(void *start, void *finish); #if defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(MSWINCE) \ || defined(CYGWIN32) || defined(PCR) @@ -1748,6 +1814,14 @@ GC_INNER ptr_t GC_scratch_alloc(size_t bytes); /* small objects. Deallocation is not */ /* possible. May return NULL. */ +#ifdef GWW_VDB + /* GC_scratch_recycle_no_gww() not used. */ +#else +# define GC_scratch_recycle_no_gww GC_scratch_recycle_inner +#endif +GC_INNER void GC_scratch_recycle_inner(void *ptr, size_t bytes); + /* Reuse the memory region by the heap. */ + /* Heap block layout maps: */ GC_INNER GC_bool GC_add_map_entry(size_t sz); /* Add a heap block map for objects of */ @@ -1829,6 +1903,13 @@ GC_INNER GC_bool GC_try_to_collect_inner(GC_stop_func f); #define GC_gcollect_inner() \ (void)GC_try_to_collect_inner(GC_never_stop_func) +#if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) + GC_EXTERN GC_bool GC_in_thread_creation; + /* We may currently be in thread creation or destruction. */ + /* Only set to TRUE while allocation lock is held. */ + /* When set, it is OK to run GC from unknown thread. */ +#endif + GC_EXTERN GC_bool GC_is_initialized; /* GC_init() has been run. */ #if defined(MSWIN32) || defined(MSWINCE) @@ -1846,12 +1927,15 @@ GC_INNER void GC_collect_a_little_inner(int n); GC_INNER void * GC_generic_malloc_inner(size_t lb, int k); /* Allocate an object of the given */ /* kind but assuming lock already held. */ -GC_INNER void * GC_generic_malloc_inner_ignore_off_page(size_t lb, int k); +#if defined(DBG_HDRS_ALL) || defined(GC_GCJ_SUPPORT) \ + || !defined(GC_NO_FINALIZATION) + GC_INNER void * GC_generic_malloc_inner_ignore_off_page(size_t lb, int k); /* Allocate an object, where */ /* the client guarantees that there */ /* will always be a pointer to the */ /* beginning of the object while the */ /* object is live. */ +#endif GC_INNER ptr_t GC_allocobj(size_t sz, int kind); /* Make the indicated */ @@ -1862,7 +1946,7 @@ GC_INNER ptr_t GC_allocobj(size_t sz, int kind); /* GC_DBG_EXTRAS is used by GC debug API functions (unlike GC_EXTRAS */ /* used by GC debug API macros) thus GC_RETURN_ADDR_PARENT (pointing */ /* to client caller) should be used if possible. */ -# ifdef GC_RETURN_ADDR_PARENT +# ifdef GC_HAVE_RETURN_ADDR_PARENT # define GC_DBG_EXTRAS GC_RETURN_ADDR_PARENT, NULL, 0 # else # define GC_DBG_EXTRAS GC_RETURN_ADDR, NULL, 0 @@ -1889,13 +1973,9 @@ GC_INNER ptr_t GC_allocobj(size_t sz, int kind); #endif /* !GC_COLLECT_AT_MALLOC */ /* Allocation routines that bypass the thread local cache. */ -#ifdef THREAD_LOCAL_ALLOC - GC_INNER void * GC_core_malloc(size_t); - GC_INNER void * GC_core_malloc_atomic(size_t); -# ifdef GC_GCJ_SUPPORT +#if defined(THREAD_LOCAL_ALLOC) && defined(GC_GCJ_SUPPORT) GC_INNER void * GC_core_gcj_malloc(size_t, void *); -# endif -#endif /* THREAD_LOCAL_ALLOC */ +#endif GC_INNER void GC_init_headers(void); GC_INNER struct hblkhdr * GC_install_header(struct hblk *h); @@ -1973,6 +2053,11 @@ GC_EXTERN GC_bool GC_have_errors; /* We saw a smashed or leaked object. */ GC_INNER void GC_generate_random_backtrace_no_gc(void); #endif +#ifdef LINT2 +# define GC_RAND_MAX (~0U >> 1) + GC_API_PRIV long GC_random(void); +#endif + GC_EXTERN GC_bool GC_print_back_height; #ifdef MAKE_BACK_GRAPH @@ -2037,26 +2122,40 @@ GC_EXTERN GC_bool GC_print_back_height; #endif #ifndef GC_DISABLE_INCREMENTAL - GC_EXTERN GC_bool GC_dirty_maintained; - /* Dirty bits are being maintained, */ - /* either for incremental collection, */ - /* or to limit the root set. */ - /* Virtual dirty bit implementation: */ /* Each implementation exports the following: */ GC_INNER void GC_read_dirty(void); /* Retrieve dirty bits. */ GC_INNER GC_bool GC_page_was_dirty(struct hblk *h); /* Read retrieved dirty bits. */ + GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, GC_bool pointerfree); - /* h is about to be written or allocated. Ensure */ - /* that it's not write protected by the virtual */ - /* dirty bit implementation. */ + /* h is about to be written or allocated. Ensure that */ + /* it is not write protected by the virtual dirty bit */ + /* implementation. I.e., this is a call that: */ + /* - hints that [h, h+nblocks) is about to be written; */ + /* - guarantees that protection is removed; */ + /* - may speed up some dirty bit implementations; */ + /* - may be essential if we need to ensure that */ + /* pointer-free system call buffers in the heap are */ + /* not protected. */ - GC_INNER void GC_dirty_init(void); + GC_INNER GC_bool GC_dirty_init(void); + /* Returns true if dirty bits are maintained (otherwise */ + /* it is OK to be called again if the client invokes */ + /* GC_enable_incremental once more). */ #endif /* !GC_DISABLE_INCREMENTAL */ +#ifdef MANUAL_VDB + GC_INNER void GC_dirty_inner(const void *p); /* does not require locking */ +# define GC_dirty(p) (GC_incremental ? GC_dirty_inner(p) : (void)0) +# define REACHABLE_AFTER_DIRTY(p) GC_reachable_here(p) +#else +# define GC_dirty(p) (void)(p) +# define REACHABLE_AFTER_DIRTY(p) (void)(p) +#endif + /* Same as GC_base but excepts and returns a pointer to const object. */ #define GC_base_C(p) ((const void *)GC_base((/* no const */ void *)(p))) @@ -2244,12 +2343,13 @@ GC_INNER void GC_initialize_offsets(void); /* defined in obj_map.c */ GC_INNER void GC_bl_init(void); GC_INNER void GC_bl_init_no_interiors(void); /* defined in blacklst.c */ -GC_INNER void GC_start_debugging(void); /* defined in dbg_mlc.c */ +GC_INNER void GC_start_debugging_inner(void); /* defined in dbg_mlc.c. */ + /* Should not be called if GC_debugging_started. */ /* Store debugging info into p. Return displaced pointer. */ -/* Assumes we don't hold allocation lock. */ -GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, - int linenum); +/* Assumes we hold the allocation lock. */ +GC_INNER void *GC_store_debug_info_inner(void *p, word sz, const char *str, + int linenum); #ifdef REDIRECT_MALLOC # ifdef GC_LINUX_THREADS @@ -2350,6 +2450,14 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, # define GC_STATIC_ASSERT(expr) (void)sizeof(char[(expr)? 1 : -1]) #endif +/* Runtime check for an argument declared as non-null is actually not null. */ +#if defined(__GNUC__) && __GNUC__ >= 4 + /* Workaround tautological-pointer-compare Clang warning. */ +# define NONNULL_ARG_NOT_NULL(arg) (*(volatile void **)&(arg) != NULL) +#else +# define NONNULL_ARG_NOT_NULL(arg) (NULL != (arg)) +#endif + #define COND_DUMP_CHECKS \ do { \ GC_ASSERT(GC_compute_large_free_bytes() == GC_large_free_bytes); \ @@ -2386,12 +2494,13 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, /* GC_notify_all_builder() is called when GC_fl_builder_count */ /* reaches 0. */ + GC_INNER void GC_wait_for_markers_init(void); GC_INNER void GC_acquire_mark_lock(void); GC_INNER void GC_release_mark_lock(void); GC_INNER void GC_notify_all_builder(void); GC_INNER void GC_wait_for_reclaim(void); - GC_EXTERN word GC_fl_builder_count; /* Protected by mark lock. */ + GC_EXTERN signed_word GC_fl_builder_count; /* Protected by mark lock. */ GC_INNER void GC_notify_all_marker(void); GC_INNER void GC_wait_marker(void); @@ -2402,6 +2511,8 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, /* my_mark_no. Returns if the mark cycle finishes or */ /* was already done, or there was nothing to do for */ /* some other reason. */ + + GC_INNER void GC_start_mark_threads_inner(void); #endif /* PARALLEL_MARK */ #if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) && !defined(NACL) \ @@ -2426,7 +2537,7 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, # ifndef GC_OPENBSD_UTHREADS # define SIG_SUSPEND SIGXFSZ # endif -# elif defined(_SIGRTMIN) +# elif defined(_SIGRTMIN) && !defined(CPPCHECK) # define SIG_SUSPEND _SIGRTMIN + 6 # else # define SIG_SUSPEND SIGRTMIN + 6 @@ -2473,18 +2584,19 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, # define NEED_FIND_LIMIT #endif -#if (defined(SVR4) || defined(AUX) || defined(DGUX) \ +#if (defined(SVR4) || defined(AIX) || defined(DGUX) \ || (defined(LINUX) && defined(SPARC))) && !defined(PCR) # define NEED_FIND_LIMIT #endif -#if defined(FREEBSD) && (defined(I386) || defined(X86_64) \ - || defined(powerpc) || defined(__powerpc__)) +#if defined(DATASTART_USES_BSDGETDATASTART) # include # if !defined(PCR) # define NEED_FIND_LIMIT # endif -#endif /* FREEBSD */ + GC_INNER ptr_t GC_FreeBSDGetDataStart(size_t, ptr_t); +# define DATASTART_IS_FUNC +#endif /* DATASTART_USES_BSDGETDATASTART */ #if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__) \ && !defined(NEED_FIND_LIMIT) @@ -2499,10 +2611,10 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str, #if defined(NEED_FIND_LIMIT) \ || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS)) - JMP_BUF GC_jmp_buf; + GC_EXTERN JMP_BUF GC_jmp_buf; /* Set up a handler for address faults which will longjmp to */ - /* GC_jmp_buf; */ + /* GC_jmp_buf. */ GC_INNER void GC_setup_temporary_fault_handler(void); /* Undo the effect of GC_setup_temporary_fault_handler. */ GC_INNER void GC_reset_fault_handler(void); diff --git a/src/bdwgc/include/private/gcconfig.h b/src/bdwgc/include/private/gcconfig.h index 9dfcc064d..3d6161764 100644 --- a/src/bdwgc/include/private/gcconfig.h +++ b/src/bdwgc/include/private/gcconfig.h @@ -32,6 +32,18 @@ # include /* For size_t etc. */ # endif +#ifdef LINT2 + /* A macro (based on a tricky expression) to prevent false warnings */ + /* like "Array compared to 0", "Comparison of identical expressions", */ + /* "Untrusted loop bound" output by some static code analysis tools. */ + /* The argument should not be a literal value. The result is */ + /* converted to word type. (Actually, GC_word is used instead of */ + /* word type as the latter might be undefined at the place of use.) */ +# define COVERT_DATAFLOW(w) (~(GC_word)(w)^(~(GC_word)0)) +#else +# define COVERT_DATAFLOW(w) ((GC_word)(w)) +#endif + /* Machine dependent parameters. Some tuning parameters can be found */ /* near the top of gc_private.h. */ @@ -62,9 +74,9 @@ # define SA_RESTART 0 # define HEURISTIC1 extern char etext[]; -# define DATASTART ((ptr_t)(etext)) extern int _end[]; -# define DATAEND (_end) +# define DATASTART ((ptr_t)(etext)) +# define DATAEND ((ptr_t)(_end)) # define mach_type_known # endif @@ -87,34 +99,42 @@ /* And one for Darwin: */ # if defined(macosx) || (defined(__APPLE__) && defined(__MACH__)) # define DARWIN +# include # endif /* Determine the machine type: */ # if defined(__native_client__) # define NACL -# define I386 -# define mach_type_known +# if !defined(__portable_native_client__) && !defined(__arm__) +# define I386 +# define mach_type_known +# else + /* Here we will rely upon arch-specific defines. */ +# endif # endif # if defined(__aarch64__) # define AARCH64 -# if !defined(LINUX) && !defined(DARWIN) +# if !defined(LINUX) && !defined(DARWIN) && !defined(FREEBSD) \ + && !defined(NETBSD) # define NOSYS # define mach_type_known # endif # endif # if defined(__arm) || defined(__arm__) || defined(__thumb__) # define ARM32 -# if !defined(LINUX) && !defined(NETBSD) && !defined(FREEBSD) \ +# if defined(NACL) +# define mach_type_known +# elif !defined(LINUX) && !defined(NETBSD) && !defined(FREEBSD) \ && !defined(OPENBSD) && !defined(DARWIN) \ && !defined(_WIN32) && !defined(__CEGCC__) && !defined(SYMBIAN) # define NOSYS # define mach_type_known # endif # endif -# if defined(sun) && defined(mc68000) +# if defined(sun) && defined(mc68000) && !defined(CPPCHECK) # error SUNOS4 no longer supported # endif -# if defined(hp9000s300) +# if defined(hp9000s300) && !defined(CPPCHECK) # error M68K based HP machines no longer supported. # endif # if defined(OPENBSD) && defined(m68k) @@ -146,6 +166,10 @@ # define ARM32 # define mach_type_known # endif +# if defined(NETBSD) && defined(__aarch64__) +# define AARCH64 +# define mach_type_known +# endif # if defined(NETBSD) && defined(__sh__) # define SH # define mach_type_known @@ -181,6 +205,10 @@ # endif # define mach_type_known # endif +# if defined(__NIOS2__) || defined(__NIOS2) || defined(__nios2__) +# define NIOS2 /* Altera NIOS2 */ +# define mach_type_known +# endif # if defined(__or1k__) # define OR1K /* OpenRISC/or1k */ # define mach_type_known @@ -197,12 +225,12 @@ # define SEQUENT # define mach_type_known # endif -# if defined(sun) && (defined(i386) || defined(__i386__)) +# if (defined(sun) || defined(__sun)) && (defined(i386) || defined(__i386__)) # define I386 # define SOLARIS # define mach_type_known # endif -# if defined(sun) && defined(__amd64) +# if (defined(sun) || defined(__sun)) && defined(__amd64) # define X86_64 # define SOLARIS # define mach_type_known @@ -212,19 +240,18 @@ # define OS2 # define mach_type_known # endif -# if defined(ibm032) +# if defined(ibm032) && !defined(CPPCHECK) # error IBM PC/RT no longer supported. # endif -# if defined(sun) && (defined(sparc) || defined(__sparc)) +# if (defined(sun) || defined(__sun)) && (defined(sparc) || defined(__sparc)) # define SPARC /* Test for SunOS 5.x */ -# include -# define SOLARIS +# include +# define SOLARIS # define mach_type_known -# endif -# if defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \ - && !defined(__OpenBSD__) && !defined(__NetBSD__) \ - && !defined(__FreeBSD__) && !defined(__DragonFly__) +# elif defined(sparc) && defined(unix) && !defined(sun) && !defined(linux) \ + && !defined(__OpenBSD__) && !defined(__NetBSD__) \ + && !defined(__FreeBSD__) && !defined(__DragonFly__) # define SPARC # define DRSNX # define mach_type_known @@ -248,7 +275,7 @@ # endif # define mach_type_known # endif -# if defined(_AUX_SOURCE) +# if defined(_AUX_SOURCE) && !defined(CPPCHECK) # error A/UX no longer supported # endif # if defined(_PA_RISC1_0) || defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \ @@ -266,9 +293,14 @@ # endif # define mach_type_known # endif -# if defined(__BEOS__) && defined(_X86_) +# if (defined(__BEOS__) || defined(__HAIKU__)) && defined(_X86_) # define I386 -# define BEOS +# define HAIKU +# define mach_type_known +# endif +# if defined(__HAIKU__) && (defined(__amd64__) || defined(__x86_64__)) +# define X86_64 +# define HAIKU # define mach_type_known # endif # if defined(OPENBSD) && defined(__amd64__) @@ -371,11 +403,9 @@ # elif defined(__arm__) # define ARM32 # define mach_type_known -# define DARWIN_DONT_PARSE_STACK # elif defined(__aarch64__) # define AARCH64 # define mach_type_known -# define DARWIN_DONT_PARSE_STACK # endif # endif # if defined(__rtems__) && (defined(i386) || defined(__i386__)) @@ -414,10 +444,6 @@ # define X86_64 # define mach_type_known # endif -# if defined(FREEBSD) && defined(__ia64__) -# define IA64 -# define mach_type_known -# endif # if defined(FREEBSD) && defined(__sparc__) # define SPARC # define mach_type_known @@ -430,6 +456,14 @@ # define ARM32 # define mach_type_known # endif +# if defined(FREEBSD) && defined(__aarch64__) +# define AARCH64 +# define mach_type_known +# endif +# if defined(FREEBSD) && (defined(mips) || defined(__mips) || defined(_mips)) +# define MIPS +# define mach_type_known +# endif # if defined(bsdi) && (defined(i386) || defined(__i386__)) # define I386 # define BSDI @@ -472,7 +506,9 @@ # else # define I386 # endif -# define MSWIN32 /* or Win64 */ +# ifndef MSWIN32 +# define MSWIN32 /* or Win64 */ +# endif # define mach_type_known # endif # if defined(_MSC_VER) && defined(_M_IA64) @@ -512,7 +548,7 @@ # define UTS4 # define mach_type_known # endif -# if defined(__pj__) +# if defined(__pj__) && !defined(CPPCHECK) # error PicoJava no longer supported /* The implementation had problems, and I haven't heard of users */ /* in ages. If you want it resurrected, let me know. */ @@ -561,6 +597,18 @@ # define HEXAGON # define mach_type_known # endif +# if defined(__tile__) && defined(LINUX) +# ifdef __tilegx__ +# define TILEGX +# else +# define TILEPRO +# endif +# define mach_type_known +# endif +# if defined(__riscv) && defined(LINUX) +# define RISCV +# define mach_type_known +# endif # if defined(SYMBIAN) # define mach_type_known @@ -579,7 +627,7 @@ /* Macros such as LINUX, FREEBSD, etc. distinguish them. */ /* SYSV on an M68K actually means A/UX. */ /* The distinction in these cases is usually the stack starting address */ -# ifndef mach_type_known +# if !defined(mach_type_known) && !defined(CPPCHECK) # error "The collector has not been ported to this machine/OS combination." # endif /* Mapping is: M68K ==> Motorola 680X0 */ @@ -622,6 +670,8 @@ /* CRIS ==> Axis Etrax */ /* M32R ==> Renesas M32R */ /* HEXAGON ==> Qualcomm Hexagon */ + /* TILEPRO ==> Tilera TILEPro */ + /* TILEGX ==> Tilera TILE-Gx */ /* @@ -667,7 +717,7 @@ * LINUX_STACKBOTTOM * HEURISTIC1 * HEURISTIC2 - * If STACKBOTTOM is defined, then it's value will be used directly as the + * If STACKBOTTOM is defined, then its value will be used directly as the * stack base. If LINUX_STACKBOTTOM is defined, then it will be determined * with a method appropriate for most Linux systems. Currently we look * first for __libc_stack_end (currently only if USE_LIBC_PRIVATES is @@ -708,7 +758,7 @@ * the original main program. The new main program would read something * like (provided real_main() is not inlined by the compiler): * - * # include "gc_private.h" + * #include "gc.h" * * main(argc, argv, envp) * int argc; @@ -736,7 +786,7 @@ * An architecture may define PREFETCH(x) to preload the cache with *x. * This defaults to GCC built-in operation (or a no-op for other compilers). * - * PREFETCH_FOR_WRITE(x) is used if *x is about to be written. + * GC_PREFETCH_FOR_WRITE(x) is used if *x is about to be written. * * An architecture may also define CLEAR_DOUBLE(x) to be a fast way to * clear the two words at GC_malloc-aligned address x. By default, @@ -754,6 +804,7 @@ && !defined(__FUJITSU) /* for FX10 system */ \ && !(defined(POWERPC) && defined(DARWIN)) /* for MacOS X 10.3.9 */ \ && !defined(RTEMS) \ + && !defined(__ARMCC_VERSION) /* does not exist in armcc gnu emu */ \ && !defined(__clang__) /* since no-op in clang (3.0) */ # define HAVE_BUILTIN_UNWIND_INIT # endif @@ -763,16 +814,16 @@ # define OS_TYPE "SYMBIAN" # define CPP_WORDSZ 32 # define ALIGNMENT 4 -# define DATASTART NULL -# define DATAEND NULL +# define DATASTART (ptr_t)ALIGNMENT /* cannot be null */ +# define DATAEND (ptr_t)ALIGNMENT # endif # ifdef __EMSCRIPTEN__ # define OS_TYPE "EMSCRIPTEN" # define CPP_WORDSZ 32 # define ALIGNMENT 4 -# define DATASTART NULL -# define DATAEND NULL +# define DATASTART (ptr_t)ALIGNMENT +# define DATAEND (ptr_t)ALIGNMENT # define STACK_NOT_SCANNED # endif @@ -830,10 +881,10 @@ /* that we'd rather not scan. */ # endif /* !GLIBC2 */ extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # else extern int etext[]; -# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff)) +# define DATASTART ((ptr_t)((((word)(etext)) + 0xfff) & ~0xfff)) # endif # endif # ifdef AMIGA @@ -849,15 +900,15 @@ # endif # define OS_TYPE "MACOS" /* see os_dep.c for details of global data segments. */ -# define STACKBOTTOM ((ptr_t) LMGetCurStackBase()) +# define STACKBOTTOM ((ptr_t)LMGetCurStackBase()) # define DATAEND /* not needed */ # define GETPAGESIZE() 4096 # endif # ifdef NEXT # define OS_TYPE "NEXT" -# define DATASTART ((ptr_t) get_etext()) +# define DATASTART ((ptr_t)get_etext()) # define DATASTART_IS_FUNC -# define STACKBOTTOM ((ptr_t) 0x4000000) +# define STACKBOTTOM ((ptr_t)0x4000000) # define DATAEND /* not needed */ # endif # endif @@ -871,7 +922,7 @@ # endif # define OS_TYPE "MACOS" /* see os_dep.c for details of global data segments. */ -# define STACKBOTTOM ((ptr_t) LMGetCurStackBase()) +# define STACKBOTTOM ((ptr_t)LMGetCurStackBase()) # define DATAEND /* not needed */ # endif # ifdef LINUX @@ -898,7 +949,7 @@ # define DYNAMIC_LOADING # define SEARCH_FOR_DATA_START extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # endif # ifdef DARWIN # define OS_TYPE "DARWIN" @@ -906,31 +957,31 @@ # if defined(__ppc64__) # define ALIGNMENT 8 # define CPP_WORDSZ 64 -# define STACKBOTTOM ((ptr_t) 0x7fff5fc00000) +# define STACKBOTTOM ((ptr_t)0x7fff5fc00000) # define CACHE_LINE_SIZE 64 # ifndef HBLKSIZE # define HBLKSIZE 4096 # endif # else # define ALIGNMENT 4 -# define STACKBOTTOM ((ptr_t) 0xc0000000) +# define STACKBOTTOM ((ptr_t)0xc0000000) # endif /* XXX: see get_end(3), get_etext() and get_end() should not be used. */ /* These aren't used when dyld support is enabled (it is by default). */ -# define DATASTART ((ptr_t) get_etext()) -# define DATAEND ((ptr_t) get_end()) +# define DATASTART ((ptr_t)get_etext()) +# define DATAEND ((ptr_t)get_end()) # ifndef USE_MMAP # define USE_MMAP # endif # define USE_MMAP_ANON # define MPROTECT_VDB # include -# define GETPAGESIZE() getpagesize() +# define GETPAGESIZE() (unsigned)getpagesize() # if defined(USE_PPC_PREFETCH) && defined(__GNUC__) /* The performance impact of prefetches is untested */ # define PREFETCH(x) \ __asm__ __volatile__ ("dcbt 0,%0" : : "r" ((const void *) (x))) -# define PREFETCH_FOR_WRITE(x) \ +# define GC_PREFETCH_FOR_WRITE(x) \ __asm__ __volatile__ ("dcbtst 0,%0" : : "r" ((const void *) (x))) # endif /* There seems to be some issues with trylock hanging on darwin. */ @@ -943,11 +994,17 @@ # ifndef GC_OPENBSD_THREADS # include # include -# define STACKBOTTOM ((ptr_t) USRSTACK) + /* USRSTACK is defined in but that is */ + /* protected by _KERNEL in file. */ +# ifdef USRSTACK +# define STACKBOTTOM ((ptr_t)USRSTACK) +# else +# define HEURISTIC2 +# endif # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) - extern char _end[]; + extern int _end[]; # define DATAEND ((ptr_t)(&_end)) # define DYNAMIC_LOADING # endif @@ -972,9 +1029,8 @@ # define DYNAMIC_LOADING # endif extern char etext[]; - ptr_t GC_FreeBSDGetDataStart(size_t, ptr_t); # define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext) -# define DATASTART_IS_FUNC +# define DATASTART_USES_BSDGETDATASTART # endif # ifdef NETBSD # define ALIGNMENT 4 @@ -988,10 +1044,10 @@ # define NO_GETENV # define CPP_WORDSZ 32 # define ALIGNMENT 4 - extern int _end []; + extern int _end[]; extern int __bss_start; -# define DATAEND (ptr_t)(_end) -# define DATASTART (ptr_t)(__bss_start) +# define DATASTART ((ptr_t)(__bss_start)) +# define DATAEND ((ptr_t)(_end)) # define STACKBOTTOM ((ptr_t)ps3_get_stack_bottom()) # define NO_PTHREAD_TRYLOCK /* Current GC LOCK() implementation for PS3 explicitly */ @@ -1035,8 +1091,8 @@ # define ALIGNMENT 4 # define OS_TYPE "NOSYS" extern void __end[], __dso_handle[]; -# define DATASTART (__dso_handle) /* OK, that's ugly. */ -# define DATAEND (ptr_t)(__end) +# define DATASTART ((ptr_t)__dso_handle) /* OK, that's ugly. */ +# define DATAEND ((ptr_t)(__end)) /* Stack starts at 0xE0000000 for the simulator. */ # undef STACK_GRAN # define STACK_GRAN 0x10000000 @@ -1044,6 +1100,26 @@ # endif # endif +# ifdef NACL +# define OS_TYPE "NACL" +# if defined(__GLIBC__) +# define DYNAMIC_LOADING +# endif +# define DATASTART ((ptr_t)0x10020000) + extern int _end[]; +# define DATAEND ((ptr_t)_end) +# undef STACK_GRAN +# define STACK_GRAN 0x10000 +# define HEURISTIC1 +# define NO_PTHREAD_GETATTR_NP +# define USE_MMAP +# define USE_MUNMAP +# define USE_MMAP_ANON +# undef USE_MMAP_FIXED +# define GETPAGESIZE() 65536 +# define MAX_NACL_GC_THREADS 1024 +# endif + # ifdef VAX # define MACH_TYPE "VAX" # define ALIGNMENT 4 /* Pointers are longword aligned by 4.2 C compiler */ @@ -1056,7 +1132,7 @@ # endif # ifdef ULTRIX # define OS_TYPE "ULTRIX" -# define STACKBOTTOM ((ptr_t) 0x7fffc800) +# define STACKBOTTOM ((ptr_t)0x7fffc800) # endif # endif @@ -1079,7 +1155,7 @@ ptr_t GC_SysVGetDataStart(size_t, ptr_t); # define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext) # define DATASTART_IS_FUNC -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # if !defined(USE_MMAP) && defined(REDIRECT_MALLOC) # define USE_MMAP /* Otherwise we now use calloc. Mmap may result in the */ @@ -1101,24 +1177,24 @@ # include # ifdef USERLIMIT /* This should work everywhere, but doesn't. */ -# define STACKBOTTOM ((ptr_t) USRSTACK) +# define STACKBOTTOM ((ptr_t)USRSTACK) # else # define HEURISTIC2 # endif # include -# define GETPAGESIZE() sysconf(_SC_PAGESIZE) +# define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE) /* getpagesize() appeared to be missing from at least one */ /* Solaris 5.4 installation. Weird. */ # define DYNAMIC_LOADING # endif # ifdef DRSNX # define OS_TYPE "DRSNX" - ptr_t GC_SysVGetDataStart(size_t, ptr_t); extern int etext[]; + ptr_t GC_SysVGetDataStart(size_t, ptr_t); # define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext) # define DATASTART_IS_FUNC # define MPROTECT_VDB -# define STACKBOTTOM ((ptr_t) 0xdfff0000) +# define STACKBOTTOM ((ptr_t)0xdfff0000) # define DYNAMIC_LOADING # endif # ifdef LINUX @@ -1130,7 +1206,7 @@ # endif extern int _end[]; extern int _etext[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # define SVR4 ptr_t GC_SysVGetDataStart(size_t, ptr_t); # ifdef __arch64__ @@ -1146,11 +1222,15 @@ # ifndef GC_OPENBSD_THREADS # include # include -# define STACKBOTTOM ((ptr_t) USRSTACK) +# ifdef USRSTACK +# define STACKBOTTOM ((ptr_t)USRSTACK) +# else +# define HEURISTIC2 +# endif # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) - extern char _end[]; + extern int _end[]; # define DATAEND ((ptr_t)(&_end)) # define DYNAMIC_LOADING # endif @@ -1180,8 +1260,9 @@ # define NEED_FIND_LIMIT # define DATASTART ((ptr_t)(&etext)) ptr_t GC_find_limit(ptr_t, GC_bool); -# define DATAEND (GC_find_limit (DATASTART, TRUE)) +# define DATAEND GC_find_limit(DATASTART, TRUE) # define DATAEND_IS_FUNC +# define GC_HAVE_DATAREGION2 # define DATASTART2 ((ptr_t)(&edata)) # define DATAEND2 ((ptr_t)(&end)) # endif @@ -1201,15 +1282,17 @@ # ifdef SEQUENT # define OS_TYPE "SEQUENT" extern int etext[]; -# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff)) -# define STACKBOTTOM ((ptr_t) 0x3ffff000) +# define DATASTART ((ptr_t)((((word)(etext)) + 0xfff) & ~0xfff)) +# define STACKBOTTOM ((ptr_t)0x3ffff000) # endif -# ifdef BEOS -# define OS_TYPE "BEOS" +# ifdef HAIKU +# define OS_TYPE "HAIKU" # include -# define GETPAGESIZE() B_PAGE_SIZE +# define GETPAGESIZE() (unsigned)B_PAGE_SIZE extern int etext[]; -# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff)) +# define DATASTART ((ptr_t)((((word)(etext)) + 0xfff) & ~0xfff)) +# define DYNAMIC_LOADING +# define MPROTECT_VDB # endif # ifdef SOLARIS # define OS_TYPE "SOLARIS" @@ -1217,14 +1300,22 @@ ptr_t GC_SysVGetDataStart(size_t, ptr_t); # define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext) # define DATASTART_IS_FUNC -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) /* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */ /* but reportedly breaks under 2.8. It appears that the stack */ /* base is a property of the executable, so this should not break */ /* old executables. */ /* HEURISTIC2 probably works, but this appears to be preferable. */ -# include -# define STACKBOTTOM ((ptr_t) USRSTACK) +/* Apparently USRSTACK is defined to be USERLIMIT, but in some */ +/* installations that's undefined. We work around this with a */ +/* gross hack: */ +# include +# ifdef USERLIMIT + /* This should work everywhere, but doesn't. */ +# define STACKBOTTOM ((ptr_t)USRSTACK) +# else +# define HEURISTIC2 +# endif /* At least in Solaris 2.5, PROC_VDB gives wrong values for dirty bits. */ /* It appears to be fixed in 2.8 and 2.9. */ # ifdef SOLARIS25_PROC_VDB_BUG_FIXED @@ -1250,16 +1341,15 @@ # ifdef SCO # define OS_TYPE "SCO" extern int etext[]; -# define DATASTART ((ptr_t)((((word) (etext)) + 0x3fffff) \ - & ~0x3fffff) \ - +((word)etext & 0xfff)) -# define STACKBOTTOM ((ptr_t) 0x7ffffffc) +# define DATASTART ((ptr_t)((((word)(etext)) + 0x3fffff) & ~0x3fffff) \ + + ((word)(etext) & 0xfff)) +# define STACKBOTTOM ((ptr_t)0x7ffffffc) # endif # ifdef SCO_ELF # define OS_TYPE "SCO_ELF" extern int etext[]; # define DATASTART ((ptr_t)(etext)) -# define STACKBOTTOM ((ptr_t) 0x08048000) +# define STACKBOTTOM ((ptr_t)0x08048000) # define DYNAMIC_LOADING # define ELF_CLASS ELFCLASS32 # endif @@ -1269,11 +1359,11 @@ ptr_t GC_SysVGetDataStart(size_t, ptr_t); # define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)(&_etext)) # define DATASTART_IS_FUNC -# define DATAEND (ptr_t)(&_end) +# define DATAEND ((ptr_t)(&_end)) # define STACK_GROWS_DOWN # define HEURISTIC2 # include -# define GETPAGESIZE() sysconf(_SC_PAGESIZE) +# define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE) # define DYNAMIC_LOADING # ifndef USE_MMAP # define USE_MMAP @@ -1285,24 +1375,6 @@ # define HEAP_START DATAEND # endif # endif /* DGUX */ - -# ifdef NACL -# define OS_TYPE "NACL" - extern int etext[]; -/* #define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff)) */ -# define DATASTART ((ptr_t)0x10000000) - extern int _end[]; -# define DATAEND (_end) -# undef STACK_GRAN -# define STACK_GRAN 0x10000 -# define HEURISTIC1 -# define NO_PTHREAD_GETATTR_NP -# define GETPAGESIZE() 65536 -# ifndef MAX_NACL_GC_THREADS -# define MAX_NACL_GC_THREADS 1024 -# endif -# endif /* NACL */ - # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM @@ -1318,10 +1390,6 @@ /* thus allowing the heap to grow to ~3GB */ # ifdef __ELF__ # define DYNAMIC_LOADING -# ifdef UNDEFINED /* includes ro data */ - extern int _etext[]; -# define DATASTART ((ptr_t)((((word) (_etext)) + 0xfff) & ~0xfff)) -# endif # include # if defined(__GLIBC__) && __GLIBC__ >= 2 \ || defined(PLATFORM_ANDROID) @@ -1339,15 +1407,21 @@ /* that we'd rather not scan. */ # endif extern int _end[]; -# define DATAEND (ptr_t)(_end) -# if defined(PLATFORM_ANDROID) && !defined(GC_NO_SIGSETJMP) - /* As of Android NDK r8b, _sigsetjmp is still missing */ - /* for x86 (setjmp is used instead to find data_start). */ +# define DATAEND ((ptr_t)(_end)) +# if defined(PLATFORM_ANDROID) && !defined(GC_NO_SIGSETJMP) \ + && !(__ANDROID_API__ >= 18 || __GNUC__ > 4 \ + || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) \ + || __clang_major__ > 3 \ + || (__clang_major__ == 3 && __clang_minor__ >= 2)) + /* Older Android NDK releases lack sigsetjmp in x86 libc */ + /* (setjmp is used instead to find data_start). The bug */ + /* is fixed in Android NDK r8e (so, ok to use sigsetjmp */ + /* if gcc4.8+, clang3.2+ or Android API level 18+). */ # define GC_NO_SIGSETJMP # endif # else extern int etext[]; -# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff)) +# define DATASTART ((ptr_t)((((word)(etext)) + 0xfff) & ~0xfff)) # endif # ifdef USE_I686_PREFETCH # define PREFETCH(x) \ @@ -1359,7 +1433,7 @@ # ifdef FORCE_WRITE_PREFETCH /* Using prefetches for write seems to have a slight negative */ /* impact on performance, at least for a PIII/500. */ -# define PREFETCH_FOR_WRITE(x) \ +# define GC_PREFETCH_FOR_WRITE(x) \ __asm__ __volatile__ ("prefetcht0 %0" : : "m"(*(char *)(x))) # else # define NO_PREFETCH_FOR_WRITE @@ -1367,10 +1441,10 @@ # elif defined(USE_3DNOW_PREFETCH) # define PREFETCH(x) \ __asm__ __volatile__ ("prefetch %0" : : "m"(*(char *)(x))) -# define PREFETCH_FOR_WRITE(x) \ +# define GC_PREFETCH_FOR_WRITE(x) \ __asm__ __volatile__ ("prefetchw %0" : : "m"(*(char *)(x))) # endif -# if defined(__GLIBC__) +# if defined(__GLIBC__) && !defined(__UCLIBC__) /* Workaround lock elision implementation for some glibc. */ # define GLIBC_2_19_TSX_BUG # include /* for gnu_get_libc_version() */ @@ -1412,9 +1486,9 @@ extern int etext[]; extern int _stklen; extern int __djgpp_stack_limit; -# define DATASTART ((ptr_t)((((word) (etext)) + 0x1ff) & ~0x1ff)) +# define DATASTART ((ptr_t)((((word)(etext)) + 0x1ff) & ~0x1ff)) /* #define STACKBOTTOM ((ptr_t)((word)_stubinfo+_stubinfo->size+_stklen)) */ -# define STACKBOTTOM ((ptr_t)((word) __djgpp_stack_limit + _stklen)) +# define STACKBOTTOM ((ptr_t)((word)__djgpp_stack_limit + _stklen)) /* This may not be right. */ # endif # ifdef OPENBSD @@ -1422,11 +1496,15 @@ # ifndef GC_OPENBSD_THREADS # include # include -# define STACKBOTTOM ((ptr_t) USRSTACK) +# ifdef USRSTACK +# define STACKBOTTOM ((ptr_t)USRSTACK) +# else +# define HEURISTIC2 +# endif # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) - extern char _end[]; + extern int _end[]; # define DATAEND ((ptr_t)(&_end)) # define DYNAMIC_LOADING # endif @@ -1439,7 +1517,7 @@ # define SIG_SUSPEND (32+6) # define SIG_THR_RESTART (32+5) extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # else # define SIG_SUSPEND SIGUSR1 # define SIG_THR_RESTART SIGUSR2 @@ -1450,9 +1528,8 @@ # define DYNAMIC_LOADING # endif extern char etext[]; - char * GC_FreeBSDGetDataStart(size_t, ptr_t); # define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext) -# define DATASTART_IS_FUNC +# define DATASTART_USES_BSDGETDATASTART # endif # ifdef NETBSD # define OS_TYPE "NETBSD" @@ -1473,7 +1550,7 @@ # endif # ifdef NEXT # define OS_TYPE "NEXT" -# define DATASTART ((ptr_t) get_etext()) +# define DATASTART ((ptr_t)get_etext()) # define DATASTART_IS_FUNC # define STACKBOTTOM ((ptr_t)0xc0000000) # define DATAEND /* not needed */ @@ -1501,10 +1578,10 @@ /* Make sure startup code variables always have the same names. */ #pragma aux __nullarea "*"; #pragma aux _end "*"; -# define STACKBOTTOM ((ptr_t) _STACKTOP) +# define STACKBOTTOM ((ptr_t)_STACKTOP) /* confused? me too. */ -# define DATASTART ((ptr_t) &__nullarea) -# define DATAEND ((ptr_t) &_end) +# define DATASTART ((ptr_t)(&__nullarea)) +# define DATAEND ((ptr_t)(&_end)) # endif # ifdef HURD # define OS_TYPE "HURD" @@ -1514,29 +1591,39 @@ # define SIG_THR_RESTART SIGUSR2 # define SEARCH_FOR_DATA_START extern int _end[]; -# define DATAEND ((ptr_t) (_end)) +# define DATAEND ((ptr_t)(_end)) /* # define MPROTECT_VDB Not quite working yet? */ # define DYNAMIC_LOADING +# ifndef USE_MMAP +# define USE_MMAP +# endif +# define USE_MMAP_ANON # endif # ifdef DARWIN # define OS_TYPE "DARWIN" # define DARWIN_DONT_PARSE_STACK -# define DYNAMIC_LOADING +# ifndef GC_DONT_REGISTER_MAIN_STATIC_DATA +# define DYNAMIC_LOADING +# endif /* XXX: see get_end(3), get_etext() and get_end() should not be used. */ /* These aren't used when dyld support is enabled (it is by default). */ -# define DATASTART ((ptr_t) get_etext()) -# define DATAEND ((ptr_t) get_end()) -# define STACKBOTTOM ((ptr_t) 0xc0000000) +# define DATASTART ((ptr_t)get_etext()) +# define DATAEND ((ptr_t)get_end()) +# define STACKBOTTOM ((ptr_t)0xc0000000) # ifndef USE_MMAP # define USE_MMAP # endif # define USE_MMAP_ANON # define MPROTECT_VDB # include -# define GETPAGESIZE() getpagesize() +# define GETPAGESIZE() (unsigned)getpagesize() /* There seems to be some issues with trylock hanging on darwin. */ /* This should be looked into some more. */ # define NO_PTHREAD_TRYLOCK +# if TARGET_OS_IPHONE && !defined(NO_DYLD_BIND_FULLY_IMAGE) + /* iPhone/iPad simulator */ +# define NO_DYLD_BIND_FULLY_IMAGE +# endif # endif /* DARWIN */ # endif @@ -1549,7 +1636,7 @@ /* word in crt0.o, and delimits the start */ /* of the data segment, no matter which */ /* ld options were passed through. */ -# define STACKBOTTOM ((ptr_t) 0xfffff000) /* for Encore */ +# define STACKBOTTOM ((ptr_t)0xfffff000) /* for Encore */ # endif # ifdef MIPS @@ -1558,10 +1645,10 @@ # define OS_TYPE "LINUX" # define DYNAMIC_LOADING extern int _end[]; -# define DATAEND (ptr_t)(_end) # pragma weak __data_start extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) +# define DATAEND ((ptr_t)(_end)) # ifdef _MIPS_SZPTR # define CPP_WORDSZ _MIPS_SZPTR # define ALIGNMENT (_MIPS_SZPTR/8) @@ -1588,20 +1675,21 @@ # else extern int etext[], edata[], end[]; extern int _DYNAMIC_LINKING[], _gp[]; -# define DATASTART ((ptr_t)((((word)etext + 0x3ffff) & ~0x3ffff) \ - + ((word)etext & 0xffff))) -# define DATAEND (ptr_t)(edata) +# define DATASTART ((ptr_t)((((word)(etext) + 0x3ffff) & ~0x3ffff) \ + + ((word)(etext) & 0xffff))) +# define DATAEND ((ptr_t)(edata)) +# define GC_HAVE_DATAREGION2 # define DATASTART2 (_DYNAMIC_LINKING \ ? (ptr_t)(((word)_gp + 0x8000 + 0x3ffff) & ~0x3ffff) \ : (ptr_t)edata) -# define DATAEND2 (ptr_t)(end) +# define DATAEND2 ((ptr_t)(end)) # define ALIGNMENT 4 # endif # define OS_TYPE "EWS4800" # endif # ifdef ULTRIX # define HEURISTIC2 -# define DATASTART (ptr_t)0x10000000 +# define DATASTART ((ptr_t)0x10000000) /* Could probably be slightly higher since */ /* startup code allocates lots of stuff. */ # define OS_TYPE "ULTRIX" @@ -1647,35 +1735,73 @@ # define NEED_FIND_LIMIT # define DYNAMIC_LOADING # else -# define DATASTART ((ptr_t) 0x10000000) -# define STACKBOTTOM ((ptr_t) 0x7ffff000) +# define DATASTART ((ptr_t)0x10000000) +# define STACKBOTTOM ((ptr_t)0x7ffff000) # endif /* _ELF_ */ # endif # ifdef OPENBSD -# define OS_TYPE "OPENBSD" -# define ALIGNMENT 4 +# define OS_TYPE "OPENBSD" +# define ALIGNMENT 4 # ifndef GC_OPENBSD_THREADS -# include -# include -# define STACKBOTTOM ((ptr_t) USRSTACK) -# endif - extern int _fdata[]; -# define DATASTART ((ptr_t)_fdata) - extern char _end[]; -# define DATAEND ((ptr_t)(&_end)) -# define DYNAMIC_LOADING +# include +# include +# ifdef USRSTACK +# define STACKBOTTOM ((ptr_t)USRSTACK) +# else +# define HEURISTIC2 +# endif +# endif + extern int _fdata[]; +# define DATASTART ((ptr_t)_fdata) + extern int _end[]; +# define DATAEND ((ptr_t)(&_end)) +# define DYNAMIC_LOADING # endif +# ifdef FREEBSD +# define OS_TYPE "FREEBSD" +# define ALIGNMENT 4 +# ifndef GC_FREEBSD_THREADS +# define MPROTECT_VDB +# endif +# define SIG_SUSPEND SIGUSR1 +# define SIG_THR_RESTART SIGUSR2 +# define FREEBSD_STACKBOTTOM +# ifdef __ELF__ +# define DYNAMIC_LOADING +# endif + extern char etext[]; +# define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext) +# define DATASTART_USES_BSDGETDATASTART +# endif /* FreeBSD */ # if defined(NONSTOP) # define CPP_WORDSZ 32 # define OS_TYPE "NONSTOP" # define ALIGNMENT 4 -# define DATASTART ((ptr_t) 0x08000000) +# define DATASTART ((ptr_t)0x08000000) extern char **environ; # define DATAEND ((ptr_t)(environ - 0x10)) -# define STACKBOTTOM ((ptr_t) 0x4fffffff) +# define STACKBOTTOM ((ptr_t)0x4fffffff) # endif # endif +# ifdef NIOS2 +# define CPP_WORDSZ 32 +# define MACH_TYPE "NIOS2" +# ifdef LINUX +# define OS_TYPE "LINUX" +# define DYNAMIC_LOADING + extern int _end[]; + extern int __data_start[]; +# define DATASTART ((ptr_t)(__data_start)) +# define DATAEND ((ptr_t)(_end)) +# define ALIGNMENT 4 +# ifndef HBLKSIZE +# define HBLKSIZE 4096 +# endif +# define LINUX_STACKBOTTOM +# endif /* Linux */ +# endif + # ifdef OR1K # define CPP_WORDSZ 32 # define MACH_TYPE "OR1K" @@ -1683,9 +1809,9 @@ # define OS_TYPE "LINUX" # define DYNAMIC_LOADING extern int _end[]; -# define DATAEND (ptr_t)(_end) extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) +# define DATAEND ((ptr_t)(_end)) # define ALIGNMENT 4 # ifndef HBLKSIZE # define HBLKSIZE 4096 @@ -1720,7 +1846,7 @@ /* default, since it may not work on older machine/OS */ /* combinations. (Thanks to Raymond X.T. Nijssen for uncovering */ /* this.) */ -# define STACKBOTTOM ((ptr_t) 0x7b033000) /* from /etc/conf/h/param.h */ +# define STACKBOTTOM ((ptr_t)0x7b033000) /* from /etc/conf/h/param.h */ # else /* Gustavo Rodriguez-Rivera suggested changing HEURISTIC2 */ /* to this. Note that the GC must be initialized before the */ @@ -1730,7 +1856,7 @@ # endif # define DYNAMIC_LOADING # include -# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE) +# define GETPAGESIZE() (unsigned)sysconf(_SC_PAGE_SIZE) # ifndef __GNUC__ # define PREFETCH(x) do { \ register long addr = (long)(x); \ @@ -1744,18 +1870,22 @@ # define DYNAMIC_LOADING # define SEARCH_FOR_DATA_START extern int _end[]; -# define DATAEND (ptr_t)(&_end) +# define DATAEND ((ptr_t)(&_end)) # endif /* LINUX */ # ifdef OPENBSD # define OS_TYPE "OPENBSD" # ifndef GC_OPENBSD_THREADS # include # include -# define STACKBOTTOM ((ptr_t) USRSTACK) +# ifdef USRSTACK +# define STACKBOTTOM ((ptr_t)USRSTACK) +# else +# define HEURISTIC2 +# endif # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) - extern char _end[]; + extern int _end[]; # define DATAEND ((ptr_t)(&_end)) # define DYNAMIC_LOADING # endif @@ -1781,11 +1911,15 @@ # ifndef GC_OPENBSD_THREADS # include # include -# define STACKBOTTOM ((ptr_t) USRSTACK) +# ifdef USRSTACK +# define STACKBOTTOM ((ptr_t)USRSTACK) +# else +# define HEURISTIC2 +# endif # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) - extern char _end[]; + extern int _end[]; # define DATAEND ((ptr_t)(&_end)) # define DYNAMIC_LOADING # endif @@ -1806,16 +1940,17 @@ # define NEED_FIND_LIMIT # define DATASTART ((ptr_t)(&etext)) ptr_t GC_find_limit(ptr_t, GC_bool); -# define DATAEND (GC_find_limit (DATASTART, TRUE)) +# define DATAEND GC_find_limit(DATASTART, TRUE) # define DATAEND_IS_FUNC +# define GC_HAVE_DATAREGION2 # define DATASTART2 ((ptr_t)(&edata)) # define DATAEND2 ((ptr_t)(&end)) # endif # ifdef OSF1 # define OS_TYPE "OSF1" -# define DATASTART ((ptr_t) 0x140000000) +# define DATASTART ((ptr_t)0x140000000) extern int _end[]; -# define DATAEND ((ptr_t) &_end) +# define DATAEND ((ptr_t)(&_end)) extern char ** environ; /* round up from the value of environ to the nearest page boundary */ /* Probably breaks if putenv is called before collector */ @@ -1841,10 +1976,10 @@ # define SEARCH_FOR_DATA_START # define DYNAMIC_LOADING # else -# define DATASTART ((ptr_t) 0x140000000) +# define DATASTART ((ptr_t)0x140000000) # endif extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # define MPROTECT_VDB /* Has only been superficially tested. May not */ /* work on all versions. */ @@ -1877,7 +2012,7 @@ # define HPUX_STACKBOTTOM # define DYNAMIC_LOADING # include -# define GETPAGESIZE() sysconf(_SC_PAGE_SIZE) +# define GETPAGESIZE() (unsigned)sysconf(_SC_PAGE_SIZE) /* The following was empirically determined, and is probably */ /* not very robust. */ /* Note that the backing store base seems to be at a nice */ @@ -1911,19 +2046,19 @@ # define MPROTECT_VDB /* Requires Linux 2.3.47 or later. */ extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # ifdef __GNUC__ # ifndef __INTEL_COMPILER # define PREFETCH(x) \ __asm__ (" lfetch [%0]": : "r"(x)) -# define PREFETCH_FOR_WRITE(x) \ +# define GC_PREFETCH_FOR_WRITE(x) \ __asm__ (" lfetch.excl [%0]": : "r"(x)) # define CLEAR_DOUBLE(x) \ __asm__ (" stf.spill [%0]=f0": : "r"((void *)(x))) # else # include # define PREFETCH(x) __lfetch(__lfhint_none, (x)) -# define PREFETCH_FOR_WRITE(x) __lfetch(__lfhint_nta, (x)) +# define GC_PREFETCH_FOR_WRITE(x) __lfetch(__lfhint_nta, (x)) # define CLEAR_DOUBLE(x) __stf_spill((void *)(x), 0) # endif /* __INTEL_COMPILER */ # endif @@ -1960,7 +2095,8 @@ extern int etext[]; # ifdef CX_UX # define OS_TYPE "CX_UX" -# define DATASTART ((((word)etext + 0x3fffff) & ~0x3fffff) + 0x10000) +# define DATASTART ((ptr_t)((((word)(etext) + 0x3fffff) & ~0x3fffff) \ + + 0x10000)) # endif # ifdef DGUX # define OS_TYPE "DGUX" @@ -1984,7 +2120,7 @@ ptr_t GC_SysVGetDataStart(size_t, ptr_t); # define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext) # define DATASTART_IS_FUNC -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # define HEURISTIC2 # endif # endif @@ -2008,7 +2144,7 @@ extern int __data_start[] __attribute__((__weak__)); # define DATASTART ((ptr_t)(__data_start)) extern int _end[] __attribute__((__weak__)); -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # define CACHE_LINE_SIZE 256 # define GETPAGESIZE() 4096 # endif @@ -2031,33 +2167,55 @@ # define LINUX_STACKBOTTOM # define DYNAMIC_LOADING extern int __data_start[]; + extern int _end[]; # define DATASTART ((ptr_t)__data_start) - extern char _end[]; # define DATAEND ((ptr_t)(&_end)) # endif # ifdef DARWIN /* iOS */ # define OS_TYPE "DARWIN" +# define DARWIN_DONT_PARSE_STACK # ifndef GC_DONT_REGISTER_MAIN_STATIC_DATA # define DYNAMIC_LOADING # endif -# define DATASTART ((ptr_t) get_etext()) -# define DATAEND ((ptr_t) get_end()) -# define STACKBOTTOM ((ptr_t) 0x16fdfffff) +# define DATASTART ((ptr_t)get_etext()) +# define DATAEND ((ptr_t)get_end()) +# define STACKBOTTOM ((ptr_t)0x16fdfffff) # ifndef USE_MMAP # define USE_MMAP # endif # define USE_MMAP_ANON # define MPROTECT_VDB # include -# define GETPAGESIZE() getpagesize() +# define GETPAGESIZE() (unsigned)getpagesize() /* FIXME: There seems to be some issues with trylock hanging on */ /* darwin. This should be looked into some more. */ # define NO_PTHREAD_TRYLOCK -# ifndef NO_DYLD_BIND_FULLY_IMAGE +# if TARGET_OS_IPHONE && !defined(NO_DYLD_BIND_FULLY_IMAGE) # define NO_DYLD_BIND_FULLY_IMAGE # endif # endif +# ifdef FREEBSD +# define OS_TYPE "FREEBSD" +# ifndef GC_FREEBSD_THREADS +# define MPROTECT_VDB +# endif +# define FREEBSD_STACKBOTTOM +# ifdef __ELF__ +# define DYNAMIC_LOADING +# endif + extern char etext[]; +# define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext) +# define DATASTART_USES_BSDGETDATASTART +# endif +# ifdef NETBSD +# define OS_TYPE "NETBSD" +# define HEURISTIC2 + extern ptr_t GC_data_start; +# define DATASTART GC_data_start +# define ELF_CLASS ELFCLASS64 +# define DYNAMIC_LOADING +# endif # ifdef NOSYS /* __data_start is usually defined in the target linker script. */ extern int __data_start[]; @@ -2068,8 +2226,12 @@ # endif # ifdef ARM32 +# if defined(NACL) +# define MACH_TYPE "NACL" +# else +# define MACH_TYPE "ARM32" +# endif # define CPP_WORDSZ 32 -# define MACH_TYPE "ARM32" # define ALIGNMENT 4 # ifdef NETBSD # define OS_TYPE "NETBSD" @@ -2107,10 +2269,10 @@ /* that we'd rather not scan. */ # endif extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # else extern int etext[]; -# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff)) +# define DATASTART ((ptr_t)((((word)(etext)) + 0xfff) & ~0xfff)) # endif # endif # ifdef MSWINCE @@ -2119,35 +2281,41 @@ # endif # ifdef FREEBSD /* FreeBSD/arm */ -# define ALIGNMENT 4 # define OS_TYPE "FREEBSD" +# ifndef GC_FREEBSD_THREADS +# define MPROTECT_VDB +# endif +# define SIG_SUSPEND SIGUSR1 +# define SIG_THR_RESTART SIGUSR2 +# define FREEBSD_STACKBOTTOM # ifdef __ELF__ # define DYNAMIC_LOADING # endif -# define HEURISTIC2 extern char etext[]; -# define SEARCH_FOR_DATA_START +# define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext) +# define DATASTART_USES_BSDGETDATASTART # endif # ifdef DARWIN - /* iPhone */ + /* iOS */ # define OS_TYPE "DARWIN" +# define DARWIN_DONT_PARSE_STACK # ifndef GC_DONT_REGISTER_MAIN_STATIC_DATA # define DYNAMIC_LOADING # endif -# define DATASTART ((ptr_t) get_etext()) -# define DATAEND ((ptr_t) get_end()) -# define STACKBOTTOM ((ptr_t) 0x30000000) +# define DATASTART ((ptr_t)get_etext()) +# define DATAEND ((ptr_t)get_end()) +# define STACKBOTTOM ((ptr_t)0x30000000) # ifndef USE_MMAP # define USE_MMAP # endif # define USE_MMAP_ANON # define MPROTECT_VDB # include -# define GETPAGESIZE() getpagesize() +# define GETPAGESIZE() (unsigned)getpagesize() /* FIXME: There seems to be some issues with trylock hanging on */ /* darwin. This should be looked into some more. */ # define NO_PTHREAD_TRYLOCK -# ifndef NO_DYLD_BIND_FULLY_IMAGE +# if TARGET_OS_IPHONE && !defined(NO_DYLD_BIND_FULLY_IMAGE) # define NO_DYLD_BIND_FULLY_IMAGE # endif # endif @@ -2157,21 +2325,25 @@ # ifndef GC_OPENBSD_THREADS # include # include -# define STACKBOTTOM ((ptr_t) USRSTACK) +# ifdef USRSTACK +# define STACKBOTTOM ((ptr_t)USRSTACK) +# else +# define HEURISTIC2 +# endif # endif extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) - extern char _end[]; + extern int _end[]; # define DATAEND ((ptr_t)(&_end)) # define DYNAMIC_LOADING # endif # ifdef NOSYS /* __data_start is usually defined in the target linker script. */ extern int __data_start[]; -# define DATASTART (ptr_t)(__data_start) +# define DATASTART ((ptr_t)(__data_start)) /* __stack_base__ is set in newlib/libc/sys/arm/crt0.S */ extern void *__stack_base__; -# define STACKBOTTOM ((ptr_t) (__stack_base__)) +# define STACKBOTTOM ((ptr_t)(__stack_base__)) # endif #endif @@ -2184,7 +2356,7 @@ # define LINUX_STACKBOTTOM # define SEARCH_FOR_DATA_START extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # endif # if defined(SH) && !defined(SH4) @@ -2200,7 +2372,7 @@ # define DYNAMIC_LOADING # define SEARCH_FOR_DATA_START extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # endif # ifdef NETBSD # define OS_TYPE "NETBSD" @@ -2210,17 +2382,21 @@ # define DYNAMIC_LOADING # endif # ifdef OPENBSD -# define OS_TYPE "OPENBSD" -# ifndef GC_OPENBSD_THREADS -# include -# include -# define STACKBOTTOM ((ptr_t) USRSTACK) -# endif - extern int __data_start[]; -# define DATASTART ((ptr_t)__data_start) - extern char _end[]; -# define DATAEND ((ptr_t)(&_end)) -# define DYNAMIC_LOADING +# define OS_TYPE "OPENBSD" +# ifndef GC_OPENBSD_THREADS +# include +# include +# ifdef USRSTACK +# define STACKBOTTOM ((ptr_t)USRSTACK) +# else +# define HEURISTIC2 +# endif +# endif + extern int __data_start[]; +# define DATASTART ((ptr_t)__data_start) + extern int _end[]; +# define DATAEND ((ptr_t)(&_end)) +# define DYNAMIC_LOADING # endif # endif @@ -2240,7 +2416,7 @@ # define LINUX_STACKBOTTOM # define SEARCH_FOR_DATA_START extern int _end[]; -# define DATAEND (_end) +# define DATAEND ((ptr_t)(_end)) # endif # ifdef M32R @@ -2255,7 +2431,7 @@ # define DYNAMIC_LOADING # define SEARCH_FOR_DATA_START extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # endif # endif @@ -2278,11 +2454,15 @@ # ifndef GC_OPENBSD_THREADS # include # include -# define STACKBOTTOM ((ptr_t) USRSTACK) +# ifdef USRSTACK +# define STACKBOTTOM ((ptr_t)USRSTACK) +# else +# define HEURISTIC2 +# endif # endif extern int __data_start[]; + extern int _end[]; # define DATASTART ((ptr_t)__data_start) - extern char _end[]; # define DATAEND ((ptr_t)(&_end)) # define DYNAMIC_LOADING # endif @@ -2298,17 +2478,13 @@ # endif # ifdef __ELF__ # define DYNAMIC_LOADING -# ifdef UNDEFINED /* includes ro data */ - extern int _etext[]; -# define DATASTART ((ptr_t)((((word) (_etext)) + 0xfff) & ~0xfff)) -# endif # include # define SEARCH_FOR_DATA_START extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # else extern int etext[]; -# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff)) +# define DATASTART ((ptr_t)((((word)(etext)) + 0xfff) & ~0xfff)) # endif # if defined(__GLIBC__) && !defined(__UCLIBC__) /* At present, there's a bug in GLibc getcontext() on */ @@ -2317,7 +2493,7 @@ /* FIXME: This seems to be fixed in GLibc v2.14. */ # define GETCONTEXT_FPU_EXCMASK_BUG # endif -# if defined(__GLIBC__) +# if defined(__GLIBC__) && !defined(__UCLIBC__) /* Workaround lock elision implementation for some glibc. */ # define GLIBC_2_19_TSX_BUG # include /* for gnu_get_libc_version() */ @@ -2326,22 +2502,28 @@ # ifdef DARWIN # define OS_TYPE "DARWIN" # define DARWIN_DONT_PARSE_STACK -# define DYNAMIC_LOADING +# ifndef GC_DONT_REGISTER_MAIN_STATIC_DATA +# define DYNAMIC_LOADING +# endif /* XXX: see get_end(3), get_etext() and get_end() should not be used. */ /* These aren't used when dyld support is enabled (it is by default) */ -# define DATASTART ((ptr_t) get_etext()) -# define DATAEND ((ptr_t) get_end()) -# define STACKBOTTOM ((ptr_t) 0x7fff5fc00000) +# define DATASTART ((ptr_t)get_etext()) +# define DATAEND ((ptr_t)get_end()) +# define STACKBOTTOM ((ptr_t)0x7fff5fc00000) # ifndef USE_MMAP # define USE_MMAP # endif # define USE_MMAP_ANON # define MPROTECT_VDB # include -# define GETPAGESIZE() getpagesize() +# define GETPAGESIZE() (unsigned)getpagesize() /* There seems to be some issues with trylock hanging on darwin. */ /* This should be looked into some more. */ # define NO_PTHREAD_TRYLOCK +# if TARGET_OS_IPHONE && !defined(NO_DYLD_BIND_FULLY_IMAGE) + /* iPhone/iPad simulator */ +# define NO_DYLD_BIND_FULLY_IMAGE +# endif # endif # ifdef FREEBSD # define OS_TYPE "FREEBSD" @@ -2352,7 +2534,7 @@ # define SIG_SUSPEND (32+6) # define SIG_THR_RESTART (32+5) extern int _end[]; -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) # else # define SIG_SUSPEND SIGUSR1 # define SIG_THR_RESTART SIGUSR2 @@ -2363,9 +2545,8 @@ # define DYNAMIC_LOADING # endif extern char etext[]; - ptr_t GC_FreeBSDGetDataStart(size_t, ptr_t); # define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext) -# define DATASTART_IS_FUNC +# define DATASTART_USES_BSDGETDATASTART # endif # ifdef NETBSD # define OS_TYPE "NETBSD" @@ -2378,6 +2559,15 @@ # define SEARCH_FOR_DATA_START # endif # endif +# ifdef HAIKU +# define OS_TYPE "HAIKU" +# include +# define GETPAGESIZE() (unsigned)B_PAGE_SIZE +# define HEURISTIC2 +# define SEARCH_FOR_DATA_START +# define DYNAMIC_LOADING +# define MPROTECT_VDB +# endif # ifdef SOLARIS # define OS_TYPE "SOLARIS" # define ELF_CLASS ELFCLASS64 @@ -2385,7 +2575,7 @@ ptr_t GC_SysVGetDataStart(size_t, ptr_t); # define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext) # define DATASTART_IS_FUNC -# define DATAEND (ptr_t)(_end) +# define DATAEND ((ptr_t)(_end)) /* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */ /* but reportedly breaks under 2.8. It appears that the stack */ /* base is a property of the executable, so this should not break */ @@ -2397,7 +2587,7 @@ # include # ifdef USERLIMIT /* This should work everywhere, but doesn't. */ -# define STACKBOTTOM ((ptr_t) USRSTACK) +# define STACKBOTTOM ((ptr_t)USRSTACK) # else # define HEURISTIC2 # endif @@ -2454,8 +2644,8 @@ # error --> unknown Hexagon libc configuration # endif extern int _end[]; -# define DATAEND (ptr_t)(_end) -# else +# define DATAEND ((ptr_t)(_end)) +# elif !defined(CPPCHECK) # error --> bad Hexagon Linux configuration # endif # else @@ -2463,6 +2653,52 @@ # endif # endif +# ifdef TILEPRO +# define CPP_WORDSZ 32 +# define MACH_TYPE "TILEPro" +# define ALIGNMENT 4 +# define PREFETCH(x) __insn_prefetch(x) +# define CACHE_LINE_SIZE 64 +# ifdef LINUX +# define OS_TYPE "LINUX" + extern int __data_start[]; +# define DATASTART ((ptr_t)__data_start) +# define LINUX_STACKBOTTOM +# define DYNAMIC_LOADING +# endif +# endif + +# ifdef TILEGX +# define CPP_WORDSZ (__SIZEOF_POINTER__ * 8) +# define MACH_TYPE "TILE-Gx" +# define ALIGNMENT __SIZEOF_POINTER__ +# if CPP_WORDSZ < 64 +# define CLEAR_DOUBLE(x) (*(long long *)(x) = 0) +# endif +# define PREFETCH(x) __insn_prefetch_l1(x) +# define CACHE_LINE_SIZE 64 +# ifdef LINUX +# define OS_TYPE "LINUX" + extern int __data_start[]; +# define DATASTART ((ptr_t)__data_start) +# define LINUX_STACKBOTTOM +# define DYNAMIC_LOADING +# endif +# endif + +# ifdef RISCV +# define MACH_TYPE "RISC-V" +# define CPP_WORDSZ __riscv_xlen /* 32 or 64 */ +# define ALIGNMENT (CPP_WORDSZ/8) +# ifdef LINUX +# define OS_TYPE "LINUX" + extern int __data_start[]; +# define DATASTART ((ptr_t)__data_start) +# define LINUX_STACKBOTTOM +# define DYNAMIC_LOADING +# endif +# endif /* RISCV */ + #if defined(__GLIBC__) && !defined(DONT_USE_LIBC_PRIVATES) /* Use glibc's stack-end marker. */ # define USE_LIBC_PRIVATES @@ -2507,7 +2743,6 @@ /* even with USE_PROC_FOR_LIBRARIES, we don't scan parts of stack */ /* segments that appear to be out of bounds. Thus we actually */ /* do both, which seems to yield the best results. */ - # define USE_PROC_FOR_LIBRARIES #endif @@ -2525,20 +2760,22 @@ #ifndef DATAEND extern int end[]; -# define DATAEND (ptr_t)(end) +# define DATAEND ((ptr_t)(end)) #endif -#if defined(PLATFORM_ANDROID) && !defined(THREADS) \ - && !defined(USE_GET_STACKBASE_FOR_MAIN) - /* Always use pthread_attr_getstack on Android ("-lpthread" option is */ - /* not needed to be specified manually) since GC_linux_main_stack_base */ - /* causes app crash if invoked inside Dalvik VM. */ -# define USE_GET_STACKBASE_FOR_MAIN +/* Workaround for Android NDK clang 3.5+ (as of NDK r10e) which does */ +/* not provide correct _end symbol. Unfortunately, alternate __end__ */ +/* symbol is provided only by NDK "bfd" linker. */ +#if defined(PLATFORM_ANDROID) && defined(__clang__) +# undef DATAEND +# pragma weak __end__ + extern int __end__[]; +# define DATAEND (__end__ != 0 ? (ptr_t)__end__ : (ptr_t)_end) #endif #if (defined(SVR4) || defined(PLATFORM_ANDROID)) && !defined(GETPAGESIZE) # include -# define GETPAGESIZE() sysconf(_SC_PAGESIZE) +# define GETPAGESIZE() (unsigned)sysconf(_SC_PAGESIZE) #endif #ifndef GETPAGESIZE @@ -2546,7 +2783,15 @@ || defined(NETBSD) || defined(FREEBSD) || defined(HPUX) # include # endif -# define GETPAGESIZE() getpagesize() +# define GETPAGESIZE() (unsigned)getpagesize() +#endif + +#if defined(PLATFORM_ANDROID) && !(__ANDROID_API__ >= 16) \ + && ((defined(MIPS) && (CPP_WORDSZ == 32)) \ + || defined(ARM32) || defined(I386) /* but not x32 */) + /* tkill() exists only on arm32/mips(32)/x86. */ + /* NDK r11+ deprecates tkill() but keeps it for Mono clients. */ +# define USE_TKILL_ON_ANDROID #endif #if defined(SOLARIS) || defined(DRSNX) || defined(UTS4) @@ -2577,6 +2822,17 @@ # define GC_EXPLICIT_SIGNALS_UNBLOCK #endif +#if !defined(NO_SIGNALS_UNBLOCK_IN_MAIN) && defined(GC_NO_PTHREAD_SIGMASK) +# define NO_SIGNALS_UNBLOCK_IN_MAIN +#endif + +#if !defined(NO_MARKER_SPECIAL_SIGMASK) \ + && (defined(NACL) || defined(GC_WIN32_PTHREADS)) + /* Either there is no pthread_sigmask(), or GC marker thread cannot */ + /* steal and drop user signal calls. */ +# define NO_MARKER_SPECIAL_SIGMASK +#endif + #ifdef GC_NETBSD_THREADS # define SIGRTMIN 33 # define SIGRTMAX 63 @@ -2593,16 +2849,21 @@ #if defined(SVR4) || defined(LINUX) || defined(IRIX5) || defined(HPUX) \ || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \ - || defined(DGUX) || defined(BSD) || defined(HURD) \ + || defined(DGUX) || defined(BSD) || defined(HAIKU) || defined(HURD) \ || defined(AIX) || defined(DARWIN) || defined(OSF1) # define UNIX_LIKE /* Basic Unix-like system calls work. */ #endif +#if defined(CPPCHECK) +# undef CPP_WORDSZ +# define CPP_WORDSZ (__SIZEOF_POINTER__ * 8) +#endif + #if CPP_WORDSZ != 32 && CPP_WORDSZ != 64 # error --> bad word size #endif -#ifndef ALIGNMENT +#if !defined(ALIGNMENT) && !defined(CPPCHECK) # error --> undefined ALIGNMENT #endif @@ -2616,7 +2877,8 @@ # define PCR_VDB #endif -#if !defined(STACKBOTTOM) && (defined(ECOS) || defined(NOSYS)) +#if !defined(STACKBOTTOM) && (defined(ECOS) || defined(NOSYS)) \ + && !defined(CPPCHECK) # error --> undefined STACKBOTTOM #endif @@ -2678,18 +2940,32 @@ # undef MPROTECT_VDB #endif +#if defined(SIGBUS) && !defined(HAVE_SIGBUS) && !defined(CPPCHECK) +# define HAVE_SIGBUS +#endif + +#ifndef SA_SIGINFO +# define NO_SA_SIGACTION +#endif + +#if defined(NO_SA_SIGACTION) && defined(MPROTECT_VDB) && !defined(DARWIN) \ + && !defined(MSWIN32) && !defined(MSWINCE) +# undef MPROTECT_VDB +#endif + #if !defined(PCR_VDB) && !defined(PROC_VDB) && !defined(MPROTECT_VDB) \ && !defined(GWW_VDB) && !defined(MANUAL_VDB) \ && !defined(GC_DISABLE_INCREMENTAL) # define DEFAULT_VDB #endif -#if ((defined(UNIX_LIKE) && (defined(DARWIN) || defined(HURD) \ - || defined(OPENBSD) || defined(ARM32) \ - || defined(MIPS) || defined(AVR32) \ - || defined(OR1K))) \ - || (defined(LINUX) && (defined(SPARC) || defined(M68K))) \ - || ((defined(RTEMS) || defined(PLATFORM_ANDROID)) && defined(I386))) \ +#if ((defined(UNIX_LIKE) && (defined(DARWIN) || defined(HAIKU) \ + || defined(HURD) || defined(OPENBSD) \ + || defined(ARM32) \ + || defined(AVR32) || defined(MIPS) \ + || defined(NIOS2) || defined(OR1K))) \ + || (defined(LINUX) && !defined(__gnu_linux__)) \ + || (defined(RTEMS) && defined(I386)) || defined(PLATFORM_ANDROID)) \ && !defined(NO_GETCONTEXT) # define NO_GETCONTEXT #endif @@ -2702,11 +2978,11 @@ # endif #endif -#ifndef PREFETCH_FOR_WRITE +#ifndef GC_PREFETCH_FOR_WRITE # if defined(__GNUC__) && __GNUC__ >= 3 && !defined(NO_PREFETCH_FOR_WRITE) -# define PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1) +# define GC_PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1) # else -# define PREFETCH_FOR_WRITE(x) (void)0 +# define GC_PREFETCH_FOR_WRITE(x) (void)0 # endif #endif @@ -2741,6 +3017,10 @@ # define DATASTART GC_data_start #endif +#ifndef HEAP_START +# define HEAP_START ((ptr_t)0) +#endif + #ifndef CLEAR_DOUBLE # define CLEAR_DOUBLE(x) (((word*)(x))[0] = 0, ((word*)(x))[1] = 0) #endif @@ -2752,6 +3032,7 @@ # define INCLUDE_LINUX_THREAD_DESCR #endif +#if !defined(CPPCHECK) #if defined(GC_IRIX_THREADS) && !defined(IRIX5) # error --> inconsistent configuration #endif @@ -2780,16 +3061,64 @@ && !defined(MSWINCE) # error --> inconsistent configuration #endif +#endif /* !CPPCHECK */ #if defined(PCR) || defined(GC_WIN32_THREADS) || defined(GC_PTHREADS) \ || defined(SN_TARGET_PS3) # define THREADS #endif -#if defined(PARALLEL_MARK) && !defined(THREADS) +#if defined(PARALLEL_MARK) && !defined(THREADS) && !defined(CPPCHECK) # error "invalid config - PARALLEL_MARK requires GC_THREADS" #endif +#if (((defined(MSWIN32) || defined(MSWINCE)) && !defined(__GNUC__)) \ + || (defined(MSWIN32) && defined(I386)) /* for Win98 */ \ + || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS))) \ + && !defined(NO_WRAP_MARK_SOME) + /* Under rare conditions, we may end up marking from nonexistent */ + /* memory. Hence we need to be prepared to recover by running */ + /* GC_mark_some with a suitable handler in place. */ + /* TODO: Probably replace __GNUC__ above with ndef GC_PTHREADS. */ + /* FIXME: Should we really need it for WinCE? If yes then */ + /* WRAP_MARK_SOME should be also defined for CeGCC which requires */ + /* CPU/OS-specific code in mark_ex_handler and GC_mark_some (for */ + /* manual stack unwinding and exception handler installation). */ +# define WRAP_MARK_SOME +#endif + +#if defined(PARALLEL_MARK) && !defined(DEFAULT_STACK_MAYBE_SMALL) \ + && (defined(HPUX) || defined(GC_DGUX386_THREADS) \ + || defined(NO_GETCONTEXT) /* e.g. musl */) + /* TODO: Test default stack size in configure. */ +# define DEFAULT_STACK_MAYBE_SMALL +#endif + +#ifdef PARALLEL_MARK +# define MIN_STACK_SIZE (8 * HBLKSIZE * sizeof(word)) +#elif defined(THREADS) +# define MIN_STACK_SIZE 65536 +#endif + +#if defined(PLATFORM_ANDROID) && !defined(THREADS) \ + && !defined(USE_GET_STACKBASE_FOR_MAIN) + /* Always use pthread_attr_getstack on Android ("-lpthread" option is */ + /* not needed to be specified manually) since GC_linux_main_stack_base */ + /* causes app crash if invoked inside Dalvik VM. */ +# define USE_GET_STACKBASE_FOR_MAIN +#endif + +/* Outline pthread primitives to use in GC_get_[main_]stack_base. */ +#if ((defined(FREEBSD) && defined(__GLIBC__)) /* kFreeBSD */ \ + || defined(LINUX) || defined(NETBSD) || defined(PLATFORM_ANDROID)) \ + && !defined(NO_PTHREAD_GETATTR_NP) +# define HAVE_PTHREAD_GETATTR_NP 1 +#elif defined(FREEBSD) && !defined(__GLIBC__) \ + && !defined(NO_PTHREAD_ATTR_GET_NP) +# define HAVE_PTHREAD_NP_H 1 /* requires include pthread_np.h */ +# define HAVE_PTHREAD_ATTR_GET_NP 1 +#endif + #if defined(UNIX_LIKE) && defined(THREADS) && !defined(NO_CANCEL_SAFE) \ && !defined(PLATFORM_ANDROID) /* Make the code cancellation-safe. This basically means that we */ @@ -2824,7 +3153,8 @@ #endif #if defined(CAN_HANDLE_FORK) && !defined(CAN_CALL_ATFORK) \ - && !defined(HURD) && !defined(PLATFORM_ANDROID) + && !defined(HURD) \ + && (!defined(PLATFORM_ANDROID) || __ANDROID_API__ >= 21) /* Have working pthread_atfork(). */ # define CAN_CALL_ATFORK #endif @@ -2870,6 +3200,21 @@ # endif #endif /* !GC_WORD_C */ +#if defined(__has_feature) + /* __has_feature() is supported. */ +# if __has_feature(address_sanitizer) && !defined(ADDRESS_SANITIZER) +# define ADDRESS_SANITIZER +# endif +# if __has_feature(memory_sanitizer) && !defined(MEMORY_SANITIZER) +# define MEMORY_SANITIZER +# endif +#else +# ifdef __SANITIZE_ADDRESS__ + /* GCC v4.8+ */ +# define ADDRESS_SANITIZER +# endif +#endif /* !__has_feature */ + #if defined(SPARC) # define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */ /* include assembly code to do it well. */ @@ -2905,7 +3250,7 @@ # endif #endif #ifdef SAVE_CALL_CHAIN -# ifndef SAVE_CALL_COUNT +# if !defined(SAVE_CALL_COUNT) || defined(CPPCHECK) # define NFRAMES 6 /* Number of frames to save. Even for */ /* alignment reasons. */ # else @@ -2935,17 +3280,20 @@ #endif #if defined(POINTER_SHIFT) && !defined(POINTER_MASK) -# define POINTER_MASK ((GC_word)(-1)) +# define POINTER_MASK ((word)(-1)) #endif #if !defined(FIXUP_POINTER) && defined(POINTER_MASK) -# define FIXUP_POINTER(p) (p = ((p) & POINTER_MASK) << POINTER_SHIFT) +# if defined(CPPCHECK) +# define FIXUP_POINTER(p) (p = (p) << 4) /* e.g. */ +# else +# define FIXUP_POINTER(p) (p = ((p) & POINTER_MASK) << POINTER_SHIFT) +# endif #endif #if defined(FIXUP_POINTER) -# define NEED_FIXUP_POINTER 1 +# define NEED_FIXUP_POINTER #else -# define NEED_FIXUP_POINTER 0 # define FIXUP_POINTER(p) #endif @@ -2954,6 +3302,7 @@ #endif /* Some static sanity tests. */ +#if !defined(CPPCHECK) #if defined(MARK_BIT_PER_GRANULE) && defined(MARK_BIT_PER_OBJ) # error Define only one of MARK_BIT_PER_GRANULE and MARK_BIT_PER_OBJ. #endif @@ -2965,9 +3314,11 @@ # error "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd." #endif -#if defined(REDIRECT_MALLOC) && defined(THREADS) && !defined(LINUX) +#if defined(REDIRECT_MALLOC) && defined(THREADS) && !defined(LINUX) \ + && !defined(REDIRECT_MALLOC_IN_HEADER) # error "REDIRECT_MALLOC with THREADS works at most on Linux." #endif +#endif /* !CPPCHECK */ #ifdef GC_PRIVATE_H /* This relies on some type definitions from gc_priv.h, from */ @@ -2978,7 +3329,8 @@ /* usually makes it possible to merge consecutively allocated */ /* chunks. It also avoids unintended recursion with */ /* REDIRECT_MALLOC macro defined. */ - /* GET_MEM() returns a HLKSIZE aligned chunk. */ + /* GET_MEM() argument should be of size_t type and have */ + /* no side-effect. GET_MEM() returns HBLKSIZE-aligned chunk; */ /* 0 is taken to mean failure. */ /* In case of MMAP_SUPPORTED, the argument must also be */ /* a multiple of a physical page size. */ @@ -2988,45 +3340,55 @@ struct hblk; /* See gc_priv.h. */ # if defined(PCR) char * real_malloc(size_t bytes); -# define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)(bytes) + GC_page_size) \ +# define GET_MEM(bytes) HBLKPTR(real_malloc(SIZET_SAT_ADD(bytes, \ + GC_page_size)) \ + GC_page_size-1) # elif defined(OS2) void * os2_alloc(size_t bytes); -# define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc((size_t)(bytes) \ - + GC_page_size) + GC_page_size-1) +# define GET_MEM(bytes) HBLKPTR((ptr_t)os2_alloc( \ + SIZET_SAT_ADD(bytes, \ + GC_page_size)) \ + + GC_page_size-1) # elif defined(NEXT) || defined(DOS4GW) || defined(NONSTOP) \ || (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) \ || (defined(SOLARIS) && !defined(USE_MMAP)) || defined(RTEMS) \ || defined(__CC_ARM) # define GET_MEM(bytes) HBLKPTR((size_t)calloc(1, \ - (size_t)(bytes) + GC_page_size) \ + SIZET_SAT_ADD(bytes, \ + GC_page_size)) \ + GC_page_size - 1) # elif defined(MSWIN32) || defined(CYGWIN32) - ptr_t GC_win32_get_mem(GC_word bytes); + ptr_t GC_win32_get_mem(size_t bytes); # define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes) # elif defined(MACOS) # if defined(USE_TEMPORARY_MEMORY) Ptr GC_MacTemporaryNewPtr(size_t size, Boolean clearMemory); -# define GET_MEM(bytes) HBLKPTR( \ - GC_MacTemporaryNewPtr((bytes) + GC_page_size, true) \ +# define GET_MEM(bytes) HBLKPTR(GC_MacTemporaryNewPtr( \ + SIZET_SAT_ADD(bytes, \ + GC_page_size), true) \ + GC_page_size-1) # else -# define GET_MEM(bytes) HBLKPTR(NewPtrClear((bytes) + GC_page_size) \ +# define GET_MEM(bytes) HBLKPTR(NewPtrClear(SIZET_SAT_ADD(bytes, \ + GC_page_size)) \ + GC_page_size-1) # endif # elif defined(MSWINCE) - ptr_t GC_wince_get_mem(GC_word bytes); + ptr_t GC_wince_get_mem(size_t bytes); # define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes) # elif defined(AMIGA) && defined(GC_AMIGA_FASTALLOC) - void *GC_amiga_get_mem(size_t size); -# define GET_MEM(bytes) HBLKPTR((size_t) \ - GC_amiga_get_mem((size_t)(bytes) + GC_page_size) \ + void *GC_amiga_get_mem(size_t bytes); +# define GET_MEM(bytes) HBLKPTR((size_t)GC_amiga_get_mem( \ + SIZET_SAT_ADD(bytes, \ + GC_page_size)) \ + GC_page_size-1) # elif defined(SN_TARGET_PS3) - void *ps3_get_mem(size_t size); + void *ps3_get_mem(size_t bytes); # define GET_MEM(bytes) (struct hblk*)ps3_get_mem(bytes) +# elif defined(HAIKU) + ptr_t GC_haiku_get_mem(size_t bytes); +# define GET_MEM(bytes) (struct hblk*)GC_haiku_get_mem(bytes) # else - ptr_t GC_unix_get_mem(GC_word bytes); + ptr_t GC_unix_get_mem(size_t bytes); # define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes) # endif #endif /* GC_PRIVATE_H */ diff --git a/src/bdwgc/include/private/pthread_stop_world.h b/src/bdwgc/include/private/pthread_stop_world.h index 483742867..ec5dfea62 100644 --- a/src/bdwgc/include/private/pthread_stop_world.h +++ b/src/bdwgc/include/private/pthread_stop_world.h @@ -19,10 +19,10 @@ #define GC_PTHREAD_STOP_WORLD_H struct thread_stop_info { -# ifndef GC_OPENBSD_UTHREADS - word last_stop_count; /* GC_last_stop_count value when thread */ - /* last successfully handled a suspend */ - /* signal. */ +# if !defined(GC_OPENBSD_UTHREADS) && !defined(NACL) + volatile AO_t last_stop_count; + /* The value of GC_stop_count when the thread */ + /* last successfully handled a suspend signal. */ # endif ptr_t stack_ptr; /* Valid only when stopped. */ @@ -34,7 +34,12 @@ struct thread_stop_info { /* saved registers, they may be pushed to the stack much earlier. */ /* Also, on amd64 'push' puts 8 bytes on the stack even though */ /* our pointers are 4 bytes. */ -# define NACL_GC_REG_STORAGE_SIZE 20 +# ifdef ARM32 + /* Space for r4-r8, r10-r12, r14. */ +# define NACL_GC_REG_STORAGE_SIZE 9 +# else +# define NACL_GC_REG_STORAGE_SIZE 20 +# endif ptr_t reg_storage[NACL_GC_REG_STORAGE_SIZE]; # endif }; diff --git a/src/bdwgc/include/private/pthread_support.h b/src/bdwgc/include/private/pthread_support.h index 525a9aac2..1bdb3267e 100644 --- a/src/bdwgc/include/private/pthread_support.h +++ b/src/bdwgc/include/private/pthread_support.h @@ -46,12 +46,17 @@ typedef struct GC_Thread_Rep { /* guaranteed to be dead, but we may */ /* not yet have registered the join.) */ pthread_t id; -# ifdef PLATFORM_ANDROID +# ifdef USE_TKILL_ON_ANDROID pid_t kernel_id; # endif /* Extra bookkeeping information the stopping code uses */ struct thread_stop_info stop_info; +# if defined(GC_ENABLE_SUSPEND_THREAD) && !defined(GC_DARWIN_THREADS) \ + && !defined(GC_OPENBSD_UTHREADS) && !defined(NACL) + volatile AO_t suspended_ext; /* Thread was suspended externally. */ +# endif + unsigned char flags; # define FINISHED 1 /* Thread has exited. */ # define DETACHED 2 /* Thread is treated as detached. */ @@ -62,9 +67,6 @@ typedef struct GC_Thread_Rep { /* it unregisters itself, since it */ /* may not return a GC pointer. */ # define MAIN_THREAD 4 /* True for the original thread only. */ -# define SUSPENDED_EXT 8 /* Thread was suspended externally */ - /* (this is not used by the unmodified */ - /* GC itself at present). */ # define DISABLED_GC 0x10 /* Collections are disabled while the */ /* thread is exiting. */ @@ -86,6 +88,12 @@ typedef struct GC_Thread_Rep { ptr_t stack_end; /* Cold end of the stack (except for */ /* main thread). */ + ptr_t altstack; /* The start of the alt-stack if there */ + /* is one, NULL otherwise. */ + word altstack_size; /* The size of the alt-stack if exists. */ + ptr_t stack; /* The start and size of the normal */ + /* stack (set by GC_register_altstack). */ + word stack_size; # if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK) ptr_t topOfStack; /* Result of GC_FindTopOfStack(0); */ /* valid only if the thread is blocked; */ @@ -114,18 +122,15 @@ typedef struct GC_Thread_Rep { # endif } * GC_thread; -# define THREAD_TABLE_SZ 256 /* Must be power of 2 */ +#ifndef THREAD_TABLE_SZ +# define THREAD_TABLE_SZ 256 /* Power of 2 (for speed). */ +#endif GC_EXTERN volatile GC_thread GC_threads[THREAD_TABLE_SZ]; GC_EXTERN GC_bool GC_thr_initialized; GC_INNER GC_thread GC_lookup_thread(pthread_t id); -GC_EXTERN GC_bool GC_in_thread_creation; - /* We may currently be in thread creation or destruction. */ - /* Only set to TRUE while allocation lock is held. */ - /* When set, it is OK to run GC from unknown thread. */ - #ifdef NACL GC_EXTERN __thread GC_thread GC_nacl_gc_thread_self; GC_INNER void GC_nacl_initialize_gc_thread(void); diff --git a/src/bdwgc/include/private/specific.h b/src/bdwgc/include/private/specific.h index 7302fe32c..b10a9cf54 100644 --- a/src/bdwgc/include/private/specific.h +++ b/src/bdwgc/include/private/specific.h @@ -31,7 +31,7 @@ /* An entry describing a thread-specific value for a given thread. */ /* All such accessible structures preserve the invariant that if either */ -/* thread is a valid pthread id or qtid is a valid "quick tread id" */ +/* thread is a valid pthread id or qtid is a valid "quick thread id" */ /* for a thread, then value holds the corresponding thread specific */ /* value. This invariant must be preserved at ALL times, since */ /* asynchronous reads are allowed. */ @@ -76,7 +76,9 @@ typedef tsd * GC_key_t; #define GC_key_create(key, d) GC_key_create_inner(key) GC_INNER int GC_key_create_inner(tsd ** key_ptr); GC_INNER int GC_setspecific(tsd * key, void * value); -GC_INNER void GC_remove_specific(tsd * key); +#define GC_remove_specific(key) \ + GC_remove_specific_after_fork(key, pthread_self()) +GC_INNER void GC_remove_specific_after_fork(tsd * key, pthread_t t); /* An internal version of getspecific that assumes a cache miss. */ GC_INNER void * GC_slow_getspecific(tsd * key, word qtid, diff --git a/src/bdwgc/include/private/thread_local_alloc.h b/src/bdwgc/include/private/thread_local_alloc.h index 82fe29871..36e8c6d71 100644 --- a/src/bdwgc/include/private/thread_local_alloc.h +++ b/src/bdwgc/include/private/thread_local_alloc.h @@ -38,7 +38,7 @@ # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) # if defined(CYGWIN32) && (__GNUC__ >= 4) # if defined(__clang__) - /* As of Cygwin clang3.1, thread-local storage is unsupported. */ + /* As of Cygwin clang3.5.2, thread-local storage is unsupported. */ # define USE_PTHREAD_SPECIFIC # else # define USE_COMPILER_TLS @@ -51,14 +51,16 @@ # elif (defined(LINUX) && !defined(ARM32) && !defined(AVR32) \ && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) \ && !(defined(__clang__) && defined(PLATFORM_ANDROID))) \ - || (defined(PLATFORM_ANDROID) && defined(ARM32) \ + || (defined(PLATFORM_ANDROID) && !defined(__clang__) \ + && defined(ARM32) \ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) - /* As of Android NDK r8e, Clang cannot find __tls_get_addr. */ + /* As of Android NDK r10e, Clang cannot find __tls_get_addr. */ # define USE_COMPILER_TLS # elif defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) \ || defined(GC_AIX_THREADS) || defined(GC_DARWIN_THREADS) \ || defined(GC_FREEBSD_THREADS) || defined(GC_NETBSD_THREADS) \ - || defined(GC_LINUX_THREADS) || defined(GC_RTEMS_PTHREADS) + || defined(GC_LINUX_THREADS) || defined(GC_HAIKU_THREADS) \ + || defined(GC_RTEMS_PTHREADS) # define USE_PTHREAD_SPECIFIC # elif defined(GC_HPUX_THREADS) # ifdef __GNUC__ @@ -74,19 +76,26 @@ #include +#ifndef THREAD_FREELISTS_KINDS +# ifdef ENABLE_DISCLAIM +# define THREAD_FREELISTS_KINDS (NORMAL+2) +# else +# define THREAD_FREELISTS_KINDS (NORMAL+1) +# endif +#endif /* !THREAD_FREELISTS_KINDS */ + /* One of these should be declared as the tlfs field in the */ /* structure pointed to by a GC_thread. */ typedef struct thread_local_freelists { - void * ptrfree_freelists[TINY_FREELISTS]; - void * normal_freelists[TINY_FREELISTS]; + void * _freelists[THREAD_FREELISTS_KINDS][TINY_FREELISTS]; +# define ptrfree_freelists _freelists[PTRFREE] +# define normal_freelists _freelists[NORMAL] + /* Note: Preserve *_freelists names for some clients. */ # ifdef GC_GCJ_SUPPORT void * gcj_freelists[TINY_FREELISTS]; # define ERROR_FL ((void *)(word)-1) - /* Value used for gcj_freelist[-1]; allocation is */ + /* Value used for gcj_freelists[-1]; allocation is */ /* erroneous. */ -# endif -# ifdef ENABLE_DISCLAIM - void * finalized_freelists[TINY_FREELISTS]; # endif /* Free lists contain either a pointer or a small count */ /* reflecting the number of granules allocated at that */ @@ -108,13 +117,18 @@ typedef struct thread_local_freelists { # define GC_getspecific pthread_getspecific # define GC_setspecific pthread_setspecific # define GC_key_create pthread_key_create -# define GC_remove_specific(key) /* No need for cleanup on exit. */ +# define GC_remove_specific(key) pthread_setspecific(key, NULL) + /* Explicitly delete the value to stop the TLS */ + /* destructor from being called repeatedly. */ +# define GC_remove_specific_after_fork(key, t) (void)0 + /* Should not need any action. */ typedef pthread_key_t GC_key_t; #elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS) # define GC_getspecific(x) (x) # define GC_setspecific(key, v) ((key) = (v), 0) # define GC_key_create(key, d) 0 # define GC_remove_specific(key) /* No need for cleanup on exit. */ +# define GC_remove_specific_after_fork(key, t) (void)0 typedef void * GC_key_t; #elif defined(USE_WIN32_SPECIFIC) # ifndef WIN32_LEAN_AND_MEAN @@ -133,6 +147,7 @@ typedef struct thread_local_freelists { ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0) # define GC_remove_specific(key) /* No need for cleanup on exit. */ /* Need TlsFree on process exit/detach? */ +# define GC_remove_specific_after_fork(key, t) (void)0 typedef DWORD GC_key_t; #elif defined(USE_CUSTOM_SPECIFIC) # include "private/specific.h" @@ -155,17 +170,17 @@ GC_INNER void GC_destroy_thread_local(GC_tlfs p); /* we take care of an individual thread freelist structure. */ GC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p); -#ifdef ENABLE_DISCLAIM - GC_EXTERN ptr_t * GC_finalized_objfreelist; +#ifndef GC_ATTR_TLS_FAST +# define GC_ATTR_TLS_FAST /* empty */ #endif extern #if defined(USE_COMPILER_TLS) - __thread + __thread GC_ATTR_TLS_FAST #elif defined(USE_WIN32_COMPILER_TLS) - __declspec(thread) + __declspec(thread) GC_ATTR_TLS_FAST #endif -GC_key_t GC_thread_key; + GC_key_t GC_thread_key; /* This is set up by the thread_local_alloc implementation. No need */ /* for cleanup on thread exit. But the thread support layer makes sure */ /* that GC_thread_key is traced, if necessary. */ diff --git a/src/bdwgc/libatomic_ops/AUTHORS b/src/bdwgc/libatomic_ops/AUTHORS index 8ff28acc3..b34db3ff5 100644 --- a/src/bdwgc/libatomic_ops/AUTHORS +++ b/src/bdwgc/libatomic_ops/AUTHORS @@ -3,24 +3,28 @@ imported from the Boehm-Demers-Weiser GC, where it was contributed by many others. Currently maintained by Ivan Maidanski. -Andreas Tobler +Andreas Tobler Andrew Agno +Andy Li Bradley Smith Bruce Mitchener Carlos O'Donell +Chris Metcalf Daniel Grayson Doug Lea Earl Chew Emmanuel Stapf +Fabrizio Fabbri Frank Schaefer Gilles Talis Gregory Farnum H.J. Lu Hans Boehm -Hans-Peter Nilsson -Ian Wienand +Hans-Peter Nilsson +Ian Wienand Ivan Maidanski James Cowgill +Jean Girardet Jeremy Huddleston Jim Marshall Joerg Wagner @@ -29,7 +33,9 @@ Luca Barbato Kochin Chang Maged Michael Manuel Serrano +Marek Vasut Michael Hope +Mikael Urankar Patrick Marlier Pavel Raiskup Petter Urkedal @@ -37,9 +43,12 @@ Philipp Zambelli Ranko Zivojnovic Roger Hoover Sebastian Siewior +Shea Levy Steve Capper Takashi Yoshii Thiemo Seufer Thorsten Glaser +Tobias Leich Tony Mantler +YunQiang Su Yvan Roux diff --git a/src/bdwgc/libatomic_ops/COPYING b/src/bdwgc/libatomic_ops/COPYING index d60c31a97..d159169d1 100644 --- a/src/bdwgc/libatomic_ops/COPYING +++ b/src/bdwgc/libatomic_ops/COPYING @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to +the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not @@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - - GNU GENERAL PUBLIC LICENSE + + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions: License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in @@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - + 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is @@ -225,7 +225,7 @@ impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License @@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) year name of author + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. @@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names: This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General +library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. diff --git a/src/bdwgc/libatomic_ops/ChangeLog b/src/bdwgc/libatomic_ops/ChangeLog index 9418cbc72..22d9377e5 100644 --- a/src/bdwgc/libatomic_ops/ChangeLog +++ b/src/bdwgc/libatomic_ops/ChangeLog @@ -1,349 +1,556 @@ -== [7.5.0] (development) == +== [7.6.6] 2018-08-07 == -* Relax shareability domain for dmb st in AO_nop_write (ARM/AArch64). -* Use LLD and SCD instructions on mips64. +* COPYING: sync with FSF's gpl-2.0.txt +* Fix 'undefined reference to __atomic_load/store/cas_16' error (gcc-7/x64) +* Fix a typo in the overview section of README +* Fix comments style in configure.ac and Makefile.am +* Update copyright information in README and some header files -== [7.4.4] (unset) == +== [7.6.4] 2018-03-27 == -* Eliminate 'variable set but not used' Cppcheck warnings in test_stack. -* Fix makefile preventing AO_pause undefined in libatomic_ops_gpl. -* Fix missing casts to match printf format specifier in test_atomic. -* Fix missing output folder on making auto-generated test files (Automake). -* Minor fix of code alignment in mips AO_compare_and_swap. -* Restore contribution info in ChangeLog for authors not listed in git log. +* Add RISC-V support +* Convert atomic_ops_malloc.c and tests to valid C++ code +* Eliminate 'function is never used' cppcheck warning for load_before_cas +* Eliminate 'using argument that points at uninitialized var' cppcheck error +* Fix 'AO_pt_lock undefined' error if cross-compiling manually (MinGW) +* Fix public headers inclusion from clients C++ code +* Remove gcc/nios2.h file (include gcc/generic.h directly for nios2) +* Support MIPS rel6 + + +== [7.6.2] 2017-12-24 == + +* Allow to alter DEFAULT/MAX_NTHREADS values in test_malloc/stack +* Allow to select almost-non-blocking stack implementation explicitly +* Annotate AO_malloc with 'alloc_size' and 'malloc' attributes +* Avoid misleading 'AO_t undefined' error if wrong atomic_ops.h included +* Define AO_TS_SET to 1 (true) if GCC atomic_test_and_set is used +* Disable workaround in stack_pop_acquire that was needed for ancient Clang +* Do not define AO_GCC_FORCE_HAVE_CAS for Clang 3.8+ (Aarch64) +* Do not disallow to define double_load using built-in atomics (Aarch64) +* Do not expose AO_GCC_FORCE_HAVE_CAS macro to client code (GCC) +* Do not install documentation if configure --disable-docs (new option) +* Do not produce .tar.bz2 distribution file (configure) +* Eliminate '-pedantic is not an option that controls warnings' GCC message +* Eliminate data race in cons() of test_malloc +* Eliminate GCC-5 ASan global-buffer-overflow false positive for AO_stack_bl +* Fill in allocated memory with values depending on thread id (test_malloc) +* Fix 'bad register name %sil' assembler error (GCC-4.4/x86) +* Fix 'unknown attribute no_sanitize' compiler warning for GCC +* Fix AO_malloc for sizes near CHUNK_SIZE +* Fix memory leak in test_malloc +* Fix test failures for Clang-3.8 and older (Aarch64) +* Fix test_stack failure if AO_PREFER_BUILTIN_ATOMICS (GCC/Aarch64) +* Fix typo in AO_REAL_NEXT_PTR comment +* Increase the default number of threads to 16 in test_malloc/stack +* Mark unallocated/freed memory as inaccessible using ASan functionality +* New macro (DONT_USE_MMAP) to support testing as if mmap() is unavailable +* New macro to select stack implementation based on CAS-double +* Place no_sanitize attributes in a GCC-compliant way +* Prevent too long run of test_atomic_generalized (especially with TSan) +* Simplify '#if' expressions in gcc/x86.h (code refactoring) +* Test smallest allocation of large type (test_malloc) +* Use __builtin_expect in atomic_ops_malloc +* Use built-in atomics for load/store/CAS for Clang by default (Aarch64) +* Use double-word atomic intrinsics for recent Clang versions (gcc/x86.h) +* Use GCC atomic intrinsics for Hexagon (clang 3.9+) +* Use generalized double-wide load/store if AO_PREFER_GENERALIZED (Aarch64) +* Workaround 'unused result' code defects in atomic_ops.c, list_atomic +* Workaround Thread Sanitizer (TSan) false positive warnings +Also, includes 7.4.8 changes + + +== [7.6.0] 2017-05-19 == + +* Add *_and/or/xor* and *_[fetch_]compare_and_swap* tests to test_atomic +* Add asm-based and/or/xor implementation for char/short/int (gcc/x86) +* Add asm-based char/short/int CAS implementation for gcc/x86[_64] +* Add configure '--disable-atomic-intrinsics' option +* Add dd_acquire_read case to test_atomic +* Add initial nios2 architecture support +* Add Makefile target (check-nolink) to compile all source without linking +* Add Makefile target to run all tests without test-driver +* Add test_atomic_generalized to Makefile and Makefile.msft +* Allow alternate CC (CROSS_CC) for AC_TRY_COMPILE (configure) +* Always define word-wide CAS for x86 (MS VC++ 8+) +* Avoid atomic_compare_exchange_n if no __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n +* Avoid extra nop_full in stack_pop_acquire if atomic intrinsics used (x86) +* Basic support of TILE-Gx and TILEPro CPUs +* Code refactoring of int-wide primitives in gcc/x86.h +* Define AO_TS_SET as __GCC_ATOMIC_TEST_AND_SET_TRUEVAL if applicable +* Define CLANG/GNUC_PREREQ macros to check gcc/clang minimum version +* Do not define print_list() unless used (tests) +* Eliminate 'condition sizeof(long)>4 is always true' cppcheck style warning +* Eliminate 'ISO C90 does not support long long' compiler pedantic warning +* Eliminate 'scope of variable can be reduced' cppcheck warnings +* Eliminate redundant lwsync 2nd call in CAS_full on fail (gcc/PowerPC) +* Fix 'unknown attribute no_sanitize' compiler warning (clang prior to v3.8) +* Fix 'variable new value is never used' cppcheck style warning +* Fix missing double_compare_and_swap_dd_acquire_read +* Fix reporting about missing and/or/xor_dd_acquire_read (test_atomic) +* Hide AO_locks symbol +* Implement AO_CLEAR using C11 atomic intrinsic (GCC) +* Implement CAS_acquire/release/full using __atomic_compare_exchange_n (gcc) +* Implement char and/or/xor and short CAS for msftc ARM and X86[_64] +* Implement char CAS and char/short add for msftc X86[_64] (VS 2013+) +* Implement compiler_barrier using C11 __atomic_signal_fence (GCC) +* Implement int CAS/inc/dec for msftc/x86_64 +* Implement short inc/dec directly for msftc ARM and X86[_64] +* Initial ibmc/powerpc (xlc) support +* New configure option (--enable-werror) to treat warnings as compiler errors +* New macro AO_PREFER_BUILTIN_ATOMICS to rely on C11 atomics fully (AArch64) +* Refine AO_nop_write comment for ARM big.LITTLE architecture +* Refine configure messages when checking for compiler options +* Refine documentation about _full memory ordering suffix +* Refine README how to build the library source from the repository +* Relax shareability domain for dmb st in AO_nop_write (ARM/AArch64) +* Remove redundant include windows.h from headers (msftc/x86[_64]) +* Remove spaces at EOLn in asm code +* Report gcc/clang pedantic warnings (configure) +* Support NaCl/arm +* Suppress 'ISO C does not support __int128 type' GCC/Clang pedantic warning +* Test store/CAS emulation explicitly +* Update shared libraries version info to 2:0:1 +* Use GCC atomic intrinsics for PowerPC 32/64 (GCC 4.8+ and clang 3.8+) +* Use GCC atomic intrinsics for x86, x64, ARM, MIPS (gcc 4.9+, clang 3.5+) +* Use generalized double-wide load/store if AO_PREFER_GENERALIZED (gcc/x86) +* Workaround '#error' cppcheck error messages +* Workaround 'condition always true', 'unused stored value' cppcheck warnings +* Workaround 'function is never used' cppcheck style warnings +* Workaround 'obsolescent ftime called' cppcheck style warning (POSIX) +* Workaround 'overflow in pointer subtraction' cppcheck warning +* Workaround 'shifting 32-bit value by 32 bits undefined' cppcheck warning +* Workaround 'uninitialized memory use' code analyzer false warning (tests) +* Workaround 'uninitialized variable' cppcheck error in hpc/hppa.h +* Workaround 'value of macro is unknown' cppcheck information messages +* Workaround a bug in double-wide intrinsics of Clang/x64 with ASan enabled +* Workaround MSan warning about uninitialized data read by generalized store +Also, includes 7.4.6 changes + + +== [7.4.10] 2017-12-22 == + +* Fix AO_malloc for sizes near CHUNK_SIZE +* Fix memory leak in test_malloc +* Fix typo in AO_REAL_NEXT_PTR comment + + +== [7.4.8] 2017-10-18 == + +* Fix 'missing select.h', 'undefined sigprocmask' compiler errors (Hexagon) +* Update README about bugs reporting and new releases notification +* Workaround misspelling in GCC to detect ARMv6KZ platform + + +== [7.4.6] 2017-05-18 == + +* Add assertion that double-wide CAS target is aligned (msftc/x86[_64]) +* Add configure --enable-gcov option (enable code coverage analysis) +* Code refactoring of gcc/powerpc.h to avoid code duplication +* Eliminate 'cast to long from void*' compiler warning in test_atomic +* Eliminate 'implicit declaration of close' warning in 'strict ANSI' mode +* Eliminate 'missing braces around initializer' gcc warning (hppa) +* Eliminate 'printf format specifies type void*' GCC pedantic warnings +* Eliminate 'value shift followed by expansion' false code defect warning +* Enable limited testing in Makefile.msft without Cygwin +* Fix (delete) comment for AO_and_full (x86) +* Fix block_all_signals compilation in 'strict ANSI' mode +* Fix missing .exe for test filenames in Makefile (MinGW) +* Fix missing printed value names (test_stack) +* Implement fetch-CAS for s390[x] (gcc) +* Move libraries version info to the beginning of Makefile.am +* Refine documentation in Makefile.msft how to run all tests (MS VC) +* Refine README about library downloading +* Rename doc/README.txt to doc/README_details.txt +* Support AIX/ppc (gcc) +* Support CFLAGS_EXTRA to pass extra user-defined compiler flags (make) +* Support n32 ABI for mips64 +* Update shared libraries version info for 7.4.6+ (to 1:4:0) +* Use 'inline code' format for commands in README.md +* Use LLD and SCD instructions on mips64 +* Workaround 'resource leak' false positives in AO_malloc, add_elements +* Workaround 'uninitialized memory use' MemorySanitizer warning (test_atomic) +Also, includes 7.2h changes + + +== [7.4.4] 2016-05-24 == + +* Eliminate 'signed-to-unsigned value extension' compiler warning in malloc +* Eliminate 'variable set but not used' Cppcheck warnings in test_stack +* Fix GCC 5.x compatibility for AArch64 double-wide primitives +* Fix makefile preventing AO_pause undefined in libatomic_ops_gpl +* Fix missing casts to match printf format specifier in test_atomic +* Fix missing output folder on making auto-generated test files (Automake) +* Fix typo in configure.ac (in description of AO_ASM_X64_AVAILABLE) +* Minor fix of code alignment in mips AO_compare_and_swap +* Remove TODO file +* Restore contribution info in ChangeLog for authors not listed in git log +Also, includes 7.2g changes == [7.4.2] 2014-05-02 == -* Fix a typo in doc/README.txt (remove redundant "an" article). -* Update emails/links due to project site transition. +* Fix a typo in doc/README.txt (remove redundant "an" article) +* Update emails/links due to project site transition +Also, includes 7.2f changes == [7.4.0] 2013-11-17 == -* Add and/or/xor entries to list_atomic (tests). -* Add char/short/int/AO_double_t and dd_acquire cases to list_atomic (tests). -* Add compile-time assertion for size of 'standard' AO_double_t. -* Add double_store pthread-based implementation and tests. -* Add generalized CAS primitives of char/short/int size. -* Add generalized atomic and/or/xor operations for char/short/int types. -* Add generalized fetch_and_add_acquire/release (for ARMv6+). -* Add generic implementation of double_load primitives. -* Add information about AO_ASSUME_VISTA to README_win32. -* Add internal header containing only char/short/int/AO_t atomic loads. -* Add load/store primitives generalization based on CAS. -* Add lock-based implementation of char/short/int_fetch_compare_and_swap. -* Add makefile rule to test list_atomic.template syntax (tests). -* Add missing 'const' in aligned-atomic XSIZE_load implementation. -* Add missing double_compare_and_swap to generalization. -* Add missing generalization of no-barrier CAS in template. -* Add negative double-CAS test cases to test_atomic_include (tests). -* Add test_stack to Makefile.msft (tests). -* Adjust fprintf arguments type matching specifier in test_stack (tests). -* Adjust included filenames in atomic_ops_malloc and test_stack. -* Adjust quotes in echo command of Makefile.msft (Win32). -* Always use 'mfence' for nop_full if target CPU supports SSE2 (gcc/x86). -* Better document configure THREADDLLIBS variable. -* Cast away volatile on dereference in CAS-based generalization primitives. -* Change policy regarding version numbers ("micro" part instead of "alpha"). -* Convert README to Markdown format. -* Define AO_NO_PTHREADS in configure if no pthreads (Win32 and VxWorks). -* Define AO_int_X operations for ARM and avr32. -* Define double-wide ordered loads/stores for x86. -* Define int_and/or/xor primitives in ao_t_is_int header. -* Define nop_full as compiler barrier for pre-ARMv6 single-core case. -* Do not duplicate BUILT_SOURCES entries in nobase_private_HEADERS (Makefile). -* Do not include standard_ao_double_t.h where double-CAS is unimplemented. -* Do not report absence of meaningless nop, load and store in test_atomic. -* Do not use deprecated AO_T and AO_TS_T (tests). -* Eliminate 'missing initializer' warning for AO_stack_t value initializer. -* Eliminate 64-bit compiler warnings in atomic_ops_malloc. -* Eliminate arithmetic shifts in double-CAS (gcc/arm, msftc/x86). -* Eliminate warning for fetch_and_add argument in test_atomic_include (tests). -* Enable Makefile.msft for Win64. -* Enable build using toolchain without pthreads. -* Enable double_compare_and_swap for non-cpp code (msftc/x86.h). -* Enable generalization of all variants of CAS via fetch_compare_and_swap. -* Enable test_stack for pthreads-w32 and Win32 with native threads. -* Fix generalized AO_char/short_compare_and_swap args (missing 'unsigned'). -* Fix makefile sed rule for list_atomic (tests). -* Fix missing abort() usage in atomic_ops_malloc and tests on WinCE. -* Generalize compare_double_and_swap_double using double_compare_and_swap. -* Generalize double_load/store for x86_64 (GCC). -* Generate ao_t_is_int, 'loadstore' headers from templates. -* Generate generalized AO_t load/store/fetch_and_add primitives from template. -* Generate ordered_loads/stores_only headers from templates. -* Group all X_acquire_release_volatile.h and X_[aligned_]atomic_load_store.h. -* Implement and/or/xor, AO_double_load for ARM. -* Implement atomic store using direct write by default on ARMv6+. -* Implement char/short/int-wide primitives using GCC built-in atomic/sync. -* Implement char/short/int_fetch_and_add for msftc/x86[_64] (Win32). -* Implement char/short_fetch_and_add, char/short_load for ARMv6+ (GCC). -* Implement char/short_store primitives at aligned addresses for ARM. -* Implement compare_double_and_swap_double for SunCC/x86. -* Implement double_load/store based on guaranteed x86 access atomicity. -* Implement double_store for ARMv7 using LDREXD/STREXD. -* Implement load/store via simple LDR/STR for ARMv6+ (msftc). -* Implement nop_full/write using 'dmb' instruction if available (gcc/arm). -* Improve debug printing in test_stack (tests). -* Log messages to stdout instead of stderr (tests). -* Make AO_ASSUME_VISTA also enables Win98 code in msftc/x86.h (Win32). -* Minimize gcc/generic-arithm template by factoring out barriers. -* Move 'unsigned' keyword to XCTYPE in generalize-small template. -* Move default compiler options to CFLAGS in Makefile.msft (Win32). -* Move definitions of ordered loads/stores to inner separate headers. -* Move gcc-generic AO_t-wide primitives to generic-small/arithm headers. -* Move generalized arithmetical primitives to 'generalize-arithm' template. -* Optimize AO_spin manually to minimize compiler influence on its duration. -* Parameterize list_atomic template with XSIZE (tests). -* Perform only few list reversals in test_malloc if AO based on pthreads. -* Put autogen.sh to 'dist' package (Automake). -* Remote duplicate definition of test_and_set_acquire in generalize.h. -* Remove X_aligned_atomic_load_store headers and template. -* Remove duplicate AO_spin and AO_pause definition in atomic_ops_stack. -* Remove gcc/x86_64.h eliminating code duplication of gcc/x86.h. -* Remove nested AO_USE_PTHREAD_DEFS macro check in atomic_ops.h (gcc/arm). -* Remove redundant 'cc' clobber for LDREXD instruction (gcc/arm). -* Remove store_full from msftc/arm.h in favor of generalized primitive. -* Remove sunc/x86_64.h eliminating code duplication of sunc/x86.h. -* Remove unsafe emulation-based implementation of double CAS (SunCC/x86_64). -* Remove useless 'perror' call in run_parallel.h (tests). -* Reorder AO_double_t union elements for AO_DOUBLE_T_INITIALIZER portability. -* Replace atomic_load_store.template with atomic_load and atomic_store ones. -* Replace some FIXME items with TODO in atomic_ops.c and sysdeps headers. -* Specify fetch_and_add/sub1 result as unused in test_atomic (tests). -* Support AArch64 (64-bit ARM) target (GCC). -* Support ARMv8 target (gcc/arm). -* Test double_compare_and_swap in test_atomic (tests). -* Use AO_ prefix for internal functions in arm_v6.h, hppa.h. -* Use __atomic GCC built-in to implement generic double-wide CAS. -* Use built-in __sync CAS for double-CAS if AO_USE_SYNC_CAS_BUILTIN for x86. -* Workaround GCC 4.4.3 warning reported for 'val' of list_atomic.c (tests). +* Add and/or/xor entries to list_atomic (tests) +* Add char/short/int/AO_double_t and dd_acquire cases to list_atomic (tests) +* Add compile-time assertion for size of 'standard' AO_double_t +* Add double_store pthread-based implementation and tests +* Add generalized CAS primitives of char/short/int size +* Add generalized atomic and/or/xor operations for char/short/int types +* Add generalized fetch_and_add_acquire/release (for ARMv6+) +* Add generic implementation of double_load primitives +* Add information about AO_ASSUME_VISTA to README_win32 +* Add internal header containing only char/short/int/AO_t atomic loads +* Add load/store primitives generalization based on CAS +* Add lock-based implementation of char/short/int_fetch_compare_and_swap +* Add makefile rule to test list_atomic.template syntax (tests) +* Add missing 'const' in aligned-atomic XSIZE_load implementation +* Add missing double_compare_and_swap to generalization +* Add missing generalization of no-barrier CAS in template +* Add negative double-CAS test cases to test_atomic_include (tests) +* Add test_stack to Makefile.msft (tests) +* Adjust fprintf arguments type matching specifier in test_stack (tests) +* Adjust included filenames in atomic_ops_malloc and test_stack +* Adjust quotes in echo command of Makefile.msft (Win32) +* Always use 'mfence' for nop_full if target CPU supports SSE2 (gcc/x86) +* Better document configure THREADDLLIBS variable +* Cast away volatile on dereference in CAS-based generalization primitives +* Change policy regarding version numbers ("micro" part instead of "alpha") +* Convert README to Markdown format +* Define AO_NO_PTHREADS in configure if no pthreads (Win32 and VxWorks) +* Define AO_int_X operations for ARM and avr32 +* Define double-wide ordered loads/stores for x86 +* Define int_and/or/xor primitives in ao_t_is_int header +* Define nop_full as compiler barrier for pre-ARMv6 single-core case +* Do not duplicate BUILT_SOURCES entries in nobase_private_HEADERS (Makefile) +* Do not include standard_ao_double_t.h where double-CAS is unimplemented +* Do not report absence of meaningless nop, load and store in test_atomic +* Do not use deprecated AO_T and AO_TS_T (tests) +* Eliminate 'missing initializer' warning for AO_stack_t value initializer +* Eliminate 64-bit compiler warnings in atomic_ops_malloc +* Eliminate arithmetic shifts in double-CAS (gcc/arm, msftc/x86) +* Eliminate warning for fetch_and_add argument in test_atomic_include (tests) +* Enable Makefile.msft for Win64 +* Enable build using toolchain without pthreads +* Enable double_compare_and_swap for non-cpp code (msftc/x86.h) +* Enable generalization of all variants of CAS via fetch_compare_and_swap +* Enable test_stack for pthreads-w32 and Win32 with native threads +* Fix generalized AO_char/short_compare_and_swap args (missing 'unsigned') +* Fix makefile sed rule for list_atomic (tests) +* Fix missing abort() usage in atomic_ops_malloc and tests on WinCE +* Generalize compare_double_and_swap_double using double_compare_and_swap +* Generalize double_load/store for x86_64 (GCC) +* Generate ao_t_is_int, 'loadstore' headers from templates +* Generate generalized AO_t load/store/fetch_and_add primitives from template +* Generate ordered_loads/stores_only headers from templates +* Group all X_acquire_release_volatile.h and X_[aligned_]atomic_load_store.h +* Implement and/or/xor, AO_double_load for ARM +* Implement atomic store using direct write by default on ARMv6+ +* Implement char/short/int-wide primitives using GCC built-in atomic/sync +* Implement char/short/int_fetch_and_add for msftc/x86[_64] (Win32) +* Implement char/short_fetch_and_add, char/short_load for ARMv6+ (GCC) +* Implement char/short_store primitives at aligned addresses for ARM +* Implement compare_double_and_swap_double for SunCC/x86 +* Implement double_load/store based on guaranteed x86 access atomicity +* Implement double_store for ARMv7 using LDREXD/STREXD +* Implement load/store via simple LDR/STR for ARMv6+ (msftc) +* Implement nop_full/write using 'dmb' instruction if available (gcc/arm) +* Improve debug printing in test_stack (tests) +* Log messages to stdout instead of stderr (tests) +* Make AO_ASSUME_VISTA also enables Win98 code in msftc/x86.h (Win32) +* Minimize gcc/generic-arithm template by factoring out barriers +* Move 'unsigned' keyword to XCTYPE in generalize-small template +* Move default compiler options to CFLAGS in Makefile.msft (Win32) +* Move definitions of ordered loads/stores to inner separate headers +* Move gcc-generic AO_t-wide primitives to generic-small/arithm headers +* Move generalized arithmetical primitives to 'generalize-arithm' template +* Optimize AO_spin manually to minimize compiler influence on its duration +* Parameterize list_atomic template with XSIZE (tests) +* Perform only few list reversals in test_malloc if AO based on pthreads +* Put autogen.sh to 'dist' package (Automake) +* Remote duplicate definition of test_and_set_acquire in generalize.h +* Remove X_aligned_atomic_load_store headers and template +* Remove duplicate AO_spin and AO_pause definition in atomic_ops_stack +* Remove gcc/x86_64.h eliminating code duplication of gcc/x86.h +* Remove nested AO_USE_PTHREAD_DEFS macro check in atomic_ops.h (gcc/arm) +* Remove redundant 'cc' clobber for LDREXD instruction (gcc/arm) +* Remove store_full from msftc/arm.h in favor of generalized primitive +* Remove sunc/x86_64.h eliminating code duplication of sunc/x86.h +* Remove unsafe emulation-based implementation of double CAS (SunCC/x86_64) +* Remove useless 'perror' call in run_parallel.h (tests) +* Reorder AO_double_t union elements for AO_DOUBLE_T_INITIALIZER portability +* Replace atomic_load_store.template with atomic_load and atomic_store ones +* Replace some FIXME items with TODO in atomic_ops.c and sysdeps headers +* Specify fetch_and_add/sub1 result as unused in test_atomic (tests) +* Support AArch64 (64-bit ARM) target (GCC) +* Support ARMv8 target (gcc/arm) +* Test double_compare_and_swap in test_atomic (tests) +* Use AO_ prefix for internal functions in arm_v6.h, hppa.h +* Use __atomic GCC built-in to implement generic double-wide CAS +* Use built-in __sync CAS for double-CAS if AO_USE_SYNC_CAS_BUILTIN for x86 +* Workaround GCC 4.4.3 warning reported for 'val' of list_atomic.c (tests) +Also, includes 7.2e changes == [7.3alpha2] 2012-05-11 == -* Add '-no-undefined' to LDFLAGS in src/Makefile.am. -* Add AO_and, AO_xor atomic operations. -* Add AO_fetch_compare_and_swap primitives. -* Add and fill in AUTHORS, TODO files. -* Add autogen.sh file. -* Adjust AO_..._H macros in public headers. -* Code refactoring of gcc/arm.h by introducing AO_ARM_HAVE_x macros. -* Define AO macros for libatomic_ops version identification. -* Do not define NDEBUG if '--enable-assertions' passed to configure. -* Eliminate compiler warnings in various functions and macros. -* Generalize AO_compare_and_swap primitives via AO_fetch_compare_and_swap. +* Add '-no-undefined' to LDFLAGS in src/Makefile.am +* Add AO_and, AO_xor atomic operations +* Add AO_fetch_compare_and_swap primitives +* Add and fill in AUTHORS, TODO files +* Add autogen.sh file +* Adjust AO_..._H macros in public headers +* Code refactoring of gcc/arm.h by introducing AO_ARM_HAVE_x macros +* Define AO macros for libatomic_ops version identification +* Do not define NDEBUG if '--enable-assertions' passed to configure +* Eliminate compiler warnings in various functions and macros +* Generalize AO_compare_and_swap primitives via AO_fetch_compare_and_swap * Generalize acquire/release/full CAS primitives for MIPS -* Implement fetch_and_add, test_and_set primitives for MIPS. -* Improve Makefile for MS VC++; pass '-W3' option to MS compiler. +* Implement fetch_and_add, test_and_set primitives for MIPS +* Improve Makefile for MS VC++; pass '-W3' option to MS compiler * Include ao_t_is_int.h from atomic_ops.h after first generalization pass -* Merge all Makefile.am files in src tree. -* Minor code refactoring of atomic_ops.c, generic_pthread.h. -* Minor configure build improvements (e.g., ensure proper autoconf version). -* Place only major per-release changes description to ChangeLog (this file). -* Recognize AO_PREFER_GENERALIZED macro to favor generalization over assembly. -* Remove all auto-generated files except for generalize-small.h from the repo. -* Remove duplicate doc/COPYING and empty NEWS files. -* Replace atomic_ops_malloc static mmap-related empty functions with macros. -* Replace pointer relational comparisons with non-pointer ones. -* Require autoconf 2.61 instead of v2.64. -* Show extra compiler warnings (GCC only). -* Turn off AO primitives inlining if AO_NO_INLINE defined. -* Use __builtin_expect in CAS failure loop condition checks (GCC only). +* Merge all Makefile.am files in src tree +* Minor code refactoring of atomic_ops.c, generic_pthread.h +* Minor configure build improvements (e.g., ensure proper autoconf version) +* Place only major per-release changes description to ChangeLog (this file) +* Recognize AO_PREFER_GENERALIZED macro to favor generalization over assembly +* Remove all auto-generated files except for generalize-small.h from the repo +* Remove duplicate doc/COPYING and empty NEWS files +* Replace atomic_ops_malloc static mmap-related empty functions with macros +* Replace pointer relational comparisons with non-pointer ones +* Require autoconf 2.61 instead of v2.64 +* Show extra compiler warnings (GCC only) +* Turn off AO primitives inlining if AO_NO_INLINE defined +* Use __builtin_expect in CAS failure loop condition checks (GCC only) +Also, includes 7.2 changes -== [7.2g] (unset) == +== [7.2i] 2017-12-21 == -* Remove inclusion of acquire_release_volatile.h on MIPS. +* Fix 'missing select.h', 'undefined sigprocmask' compiler errors (Hexagon) +* Fix AO_malloc for sizes near CHUNK_SIZE +* Fix typo in AO_REAL_NEXT_PTR comment + + +== [7.2h] 2017-05-17 == + +* Add 'clean' target to Makefile.msft +* Enable Makefile.msft for Win64 +* Exclude 'check' from nmake all (Makefile.msft) +* Fix 'Cannot implement CAS_full on this architecture' build error (cris) +* Fix 'doc' files installation folder +* Fix (improve) AO_REQUIRE_CAS description in README +* Fix AO_SIZE_MAX definition (Linux/musl-gcc) +* Fix assertions style in test_atomic_include +* Fix size value wrap around in AO_malloc_large +* Fix test_atomic failure caused unaligned AO_double_t access (x86) +* Fix type of general AO_TS_INITIALIZER +* Fix typo in comments in gcc/arm.h +* Fix typos in 'error' pragma messages +* Workaround test_stack failure on AIX/ppc + + +== [7.2g] 2016-05-23 == + +* Add disclaimer to README to favor C11/C++14 atomics over libatomic_ops use +* Regenerate configure files using official libtool release (v2.4.2) +* Remove inclusion of acquire_release_volatile.h on MIPS +* Remove obsolete information from README about C++0x standard future +* Update links due to project site transition == [7.2f] 2014-05-02 == -* Fix a typo in doc/README.txt (remove redundant "an" article). -* Regenerate configure files by new automake (v1.14.1), libtool (v2.4.2.418). +* Fix a typo in doc/README.txt (remove redundant "an" article) +* Regenerate configure files by new automake (v1.14.1), libtool (v2.4.2.418) == [7.2e] 2013-11-10 == -* Fix (remove) invalid include of read_ordered.h for ARM. -* Fix AM_CONFIG_HEADER in configure for autoconf-2.69-1. -* Fix AO_pause sleep delay for particular argument values (Win32). -* Fix ARMv7 LDREXD/STREXD double-wide operand specification (GCC/Clang). -* Fix LDREXD/STREXD use for pre-Clang3.3/arm. -* Fix README regarding _acquire_read barrier. -* Fix XSIZE_load/store definition order in generalize-small template. -* Fix asm constraint of CAS memory operand for gcc/alpha, clang-3.1/mips. -* Fix asm constraints of primitives in sunc/x86.h. -* Fix cmpxchg16b-based compare_double_and_swap_double for SunCC/x86_64. -* Fix compare_double_and_swap_double and double_ptr_storage for gcc/x32. -* Fix compare_double_and_swap_double for clang3.0/x86 in PIC mode. -* Fix compare_double_and_swap_double_full definition condition in emul_cas. -* Fix generalize-small template adding missed CAS-based fetch_and_add. -* Fix generalized fetch_and_add function. -* Fix missing compiler barrier in nop_full for uniprocessor ARM. -* Fix ordered_except_wr header inclusion for s390. -* Fix return type of AO_int_X primitives defined in ao_t_is_int header. -* Fix return type of char/short/int_load_read() in read_ordered.h. -* Fix template-based headers regeneration order in src/Makefile. -* Fix typos in ao_t_is_int, atomic_ops.h, generalize.h, msftc/arm.h comments. -* Fix variable type to match printf format specifier in test_stack. -* Fix visibility and initial value of 'dummy' variable in atomic_ops_stack. -* Terminate tests with abort after error reported. +* Fix (remove) invalid include of read_ordered.h for ARM +* Fix AM_CONFIG_HEADER in configure for autoconf-2.69-1 +* Fix AO_pause sleep delay for particular argument values (Win32) +* Fix ARMv7 LDREXD/STREXD double-wide operand specification (GCC/Clang) +* Fix LDREXD/STREXD use for pre-Clang3.3/arm +* Fix README regarding _acquire_read barrier +* Fix XSIZE_load/store definition order in generalize-small template +* Fix asm constraint of CAS memory operand for gcc/alpha, clang-3.1/mips +* Fix asm constraints of primitives in sunc/x86.h +* Fix cmpxchg16b-based compare_double_and_swap_double for SunCC/x86_64 +* Fix compare_double_and_swap_double and double_ptr_storage for gcc/x32 +* Fix compare_double_and_swap_double for clang3.0/x86 in PIC mode +* Fix compare_double_and_swap_double_full definition condition in emul_cas +* Fix generalize-small template adding missed CAS-based fetch_and_add +* Fix generalized fetch_and_add function +* Fix missing compiler barrier in nop_full for uniprocessor ARM +* Fix ordered_except_wr header inclusion for s390 +* Fix return type of AO_int_X primitives defined in ao_t_is_int header +* Fix return type of char/short/int_load_read() in read_ordered.h +* Fix template-based headers regeneration order in src/Makefile +* Fix typos in ao_t_is_int, atomic_ops.h, generalize.h, msftc/arm.h comments +* Fix variable type to match printf format specifier in test_stack +* Fix visibility and initial value of 'dummy' variable in atomic_ops_stack +* Terminate tests with abort after error reported == [7.2d] 2012-08-09 == -* Fix AO_compare_double_and_swap_double_full for gcc-4.2.1/x86 in PIC mode. -* Fix AO_compiler_barrier missing parentheses. -* Fix missing 'unsigned' for generalized AO_char/short_fetch_and_add result. +* Fix AO_compare_double_and_swap_double_full for gcc-4.2.1/x86 in PIC mode +* Fix AO_compiler_barrier missing parentheses +* Fix missing 'unsigned' for generalized AO_char/short_fetch_and_add result == [7.2] 2012-05-11 == -* Add atomic_ops.pc.in and atomic_ops-uninstalled.pc.in to pkgconfig folder. -* Define and use AO_PTRDIFF_T in tests for casts between pointer and integer. -* Fix AO_compare_and_swap return type for s390 and PowerPC. -* Fix AO_compare_double_and_swap_double_full for gcc/x86 (PIC mode). -* Fix AO_stack_push_release to workaround bug in clang-1.1/x86 compiler. -* Fix AO_test_and_setXX in tests/list_atomic.template. -* Fix AO_test_and_set_full (gcc/x86[_64].h) to work-around a bug in LLVM v2.7. -* Fix AO_test_and_set_full on m68k. -* Fix __ARM_ARCH_5__ macro handling for Android NDK (ARMv7). -* Fix configure for Cygwin, mingw-w64/32. -* Fix configure to define __PIC__ macro explicitly if needed (GCC). -* Fix double_ptr_storage definition for GCC pre-v4 (x86_64). -* Fix for x32 by removing 'q' suffix in x86-64 instructions. +* Add atomic_ops.pc.in and atomic_ops-uninstalled.pc.in to pkgconfig folder +* Define and use AO_PTRDIFF_T in tests for casts between pointer and integer +* Fix AO_compare_and_swap return type for s390 and PowerPC +* Fix AO_compare_double_and_swap_double_full for gcc/x86 (PIC mode) +* Fix AO_stack_push_release to workaround bug in clang-1.1/x86 compiler +* Fix AO_test_and_setXX in tests/list_atomic.template +* Fix AO_test_and_set_full (gcc/x86[_64].h) to work-around a bug in LLVM v2.7 +* Fix AO_test_and_set_full on m68k +* Fix __ARM_ARCH_5__ macro handling for Android NDK (ARMv7) +* Fix configure for Cygwin, mingw-w64/32 +* Fix configure to define __PIC__ macro explicitly if needed (GCC) +* Fix double_ptr_storage definition for GCC pre-v4 (x86_64) +* Fix for x32 by removing 'q' suffix in x86-64 instructions * Fix generalization for IA-64 (regarding AO_or, AO_..._read/write primitives) -* Fix generalized AO__fetch_and_add() return type. -* Fix test_atomic_include for the case of missing CAS primitive. -* Fix test_malloc - allocate less memory in case of missing mmap. -* Implement the basic atomic primitives for the hexagon CPU. +* Fix generalized AO__fetch_and_add() return type +* Fix test_atomic_include for the case of missing CAS primitive +* Fix test_malloc - allocate less memory in case of missing mmap +* Implement the basic atomic primitives for the hexagon CPU == [7.2alpha6] 2011-06-14 == -* Add missing AO_HAVE_ macros. -* Add support of avr32 CPU. -* Better support of various models of ARM. -* Disable AO_compare_double_and_swap_double_full for SunCC x86 as not working. -* Enable ARM Thumb-2 mode. -* Fix AO_test_and_set_full for SunCC (x86). -* Fix bugs in tests. -* Fix clobbers in AO_compare_and_swap_full (x86.h). -* Fix typos in identifiers and comments. -* Improve AO_sync for PowerPC. -* Improve make scripts (configure.ac). -* Make get_mmaped() in atomic_ops_malloc.c more portable. -* Support Intel compiler. -* Support NaCl target. -* Suppress compiler warnings in various places. -* Test more predefined macros (ARM, PowerPC). -* Use assembly code only for MS VC if available (x86_64). -* Use built-in __sync_bool_compare_and_swap if available (x86_64). -* Workaround bugs in LLVM GCC and SunCC regarding XCHG (x86, x86_64). +* Add missing AO_HAVE_ macros +* Add support of avr32 CPU +* Better support of various models of ARM +* Disable AO_compare_double_and_swap_double_full for SunCC x86 as not working +* Enable ARM Thumb-2 mode +* Fix AO_test_and_set_full for SunCC (x86) +* Fix bugs in tests +* Fix clobbers in AO_compare_and_swap_full (x86.h) +* Fix typos in identifiers and comments +* Improve AO_sync for PowerPC +* Improve make scripts (configure.ac) +* Make get_mmaped() in atomic_ops_malloc.c more portable +* Support Intel compiler +* Support NaCl target +* Suppress compiler warnings in various places +* Test more predefined macros (ARM, PowerPC) +* Use assembly code only for MS VC if available (x86_64) +* Use built-in __sync_bool_compare_and_swap if available (x86_64) +* Workaround bugs in LLVM GCC and SunCC regarding XCHG (x86, x86_64) == [7.2alpha4] 2009-12-02 == -* Fix typos in comments, identifiers and documentation. -* Implement AO_compare_and_swap_full for SPARC. -* Refine ARM-specific code. -* Refine code and comments for MS VC. -* Regenerate make scripts. -* Share common code for all 32-bit CPUs (MS VC). -* Support DigitalMars and Watcom compilers. -* Support MS VC for ARM (WinCE). -* Support SH CPU. -* Support win32-pthreads. -* Support x86 and x86_64 for SunCC compiler. +* Fix typos in comments, identifiers and documentation +* Implement AO_compare_and_swap_full for SPARC +* Refine ARM-specific code +* Refine code and comments for MS VC +* Regenerate make scripts +* Share common code for all 32-bit CPUs (MS VC) +* Support DigitalMars and Watcom compilers +* Support MS VC for ARM (WinCE) +* Support SH CPU +* Support win32-pthreads +* Support x86 and x86_64 for SunCC compiler == [7.2alpha2] 2009-05-27 == -* Add MIPS support. -* Add better support for m68k. -* Add "const" to first parameter of load calls. -* Add parentheses around address argument for various macros. -* Add some platform-specific documentation to INSTALL. -* Add untested 64-bit support for PowerPC. -* Fix AO_compare_and_swap_double_acquire. -* Fix AO_int_fetch_and_add_full (x86_64). -* Fix comments. -* Fix s390 include paths. -* Fix use of lwz instruction (PowerPC). -* Refine clobbers (PowerPC). -* Remove outdated info about Windows support in README. -* Replace K&R-style function definition with ANSI C one. -* add AO_compare_double_and_swap_double for ARMv6. -* gcc/powerpc.h: Consider __NO_LWSYNC__. +* Add MIPS support +* Add better support for m68k +* Add "const" to first parameter of load calls +* Add parentheses around address argument for various macros +* Add some platform-specific documentation to INSTALL +* Add untested 64-bit support for PowerPC +* Fix AO_compare_and_swap_double_acquire +* Fix AO_int_fetch_and_add_full (x86_64) +* Fix comments +* Fix s390 include paths +* Fix use of lwz instruction (PowerPC) +* Refine clobbers (PowerPC) +* Remove outdated info about Windows support in README +* Replace K&R-style function definition with ANSI C one +* add AO_compare_double_and_swap_double for ARMv6 +* gcc/powerpc.h: Consider __NO_LWSYNC__ == [7.1] 2008-02-11 == -* Add test_and_set, AO_double_compare_and_swap generalizations. -* Conditionally add compare_double_and_swap_double (x86). -* Conditionally add compare_double_and_swap_double (x86). -* Fix AO_compare_double_and_swap_double_full (x86) for PIC mode. -* Fix AO_load_acquire for PowerPC. -* Fix double-width CAS (x86). -* Refine README (add more warnings about data dependencies). -* Refine double_ptr_storage type definition. -* Support ARMv6+ in GCC. -* Support ArmCC compiler. -* Use _InterlockedExchangeAdd for MS VC (x86). +* Add test_and_set, AO_double_compare_and_swap generalizations +* Conditionally add compare_double_and_swap_double (x86) +* Conditionally add compare_double_and_swap_double (x86) +* Fix AO_compare_double_and_swap_double_full (x86) for PIC mode +* Fix AO_load_acquire for PowerPC +* Fix double-width CAS (x86) +* Refine README (add more warnings about data dependencies) +* Refine double_ptr_storage type definition +* Support ARMv6+ in GCC +* Support ArmCC compiler +* Use _InterlockedExchangeAdd for MS VC (x86) == [7.0] 2007-06-28 == -* Add 64-bit version of AO_load_acquire for PowerPC (by Luca Barbato). -* Add support of x86 and x86_64 for MS VC. -* Do not assume that "mfence" is always present (x86.h). -* Fix ARM AO_test_and_set_full. -* Include windows.h (MS VC). -* Update README to reflect C++0x effort. +* Add 64-bit version of AO_load_acquire for PowerPC (by Luca Barbato) +* Add support of x86 and x86_64 for MS VC +* Do not assume that "mfence" is always present (x86.h) +* Fix ARM AO_test_and_set_full +* Include windows.h (MS VC) +* Update README to reflect C++0x effort == [1.2] 2006-07-11 == -* Add prototypes to suppress compiler warnings. -* Add simple VxWorks support. -* Fix InterlockedCompareExchange proto usage. -* Fix typos (ia64). -* Include all_acquire_release_volatile.h and all_atomic_load_store.h (ia64). -* Initial support for 64-bit targets. -* Use "=q" for AO_test_and_set_full (x86). -* Use inline assembler to generate "mfence" and byte sized XCHG. -* Use new intrinsics available in MSVC 2003 and MSVC 2005. +* Add prototypes to suppress compiler warnings +* Add simple VxWorks support +* Fix InterlockedCompareExchange proto usage +* Fix typos (ia64) +* Include all_acquire_release_volatile.h and all_atomic_load_store.h (ia64) +* Initial support for 64-bit targets +* Use "=q" for AO_test_and_set_full (x86) +* Use inline assembler to generate "mfence" and byte sized XCHG +* Use new intrinsics available in MSVC 2003 and MSVC 2005 == [1.1] 2005-09-27 == -* Add and use read_ordered.h. -* Change function naming from "byte" to "char". -* Fix AO_test_and_set for ARM; define AO_CAN_EMUL_CAS. +* Add and use read_ordered.h +* Change function naming from "byte" to "char" +* Fix AO_test_and_set for ARM; define AO_CAN_EMUL_CAS == [1.0] 2005-03-21 == -* Add atomic_ops primitives for different sized data. -* Add compare_double_and_swap_double and compare_and_swap_double. -* Add gcc/cris.h (originally comes from Hans-Peter Nilsson). -* Add gcc/m68k.h (contributed by Tony Mantler). -* Add gcc/powerpc.h (with help of Maged Michael, Doug Lea, Roger Hoover). -* Add initial support for atomic_ops for VC++/Windows/X86 and HP/UX. -* Add minimal support for the Sun SPARC compiler. -* Add support for platforms that require out-of-line assembly code. -* Add support of int-wide operations on platforms with int-sized pointers. -* Added libatomic_ops_gpl library with support for lock-free stack and malloc. -* Change atomic_ops include file structure. -* Change most platforms to use byte-wide test-and-set locations. -* Define AO_CLEAR, __ldcw[_align] macros in gcc/hppa.h (by Carlos O'Donell). -* Fix various bugs. -* Install under "atomic_ops" instead of "ao". -* Remove compiler_barrier workaround for gcc 3.4+. -* Renamed various types to end in _t. -* Replace AO_HAVE_NOP_FULL with AO_HAVE_nop_full (by Ranko Zivojnovic). -* Use autoconf, automake. +* Add atomic_ops primitives for different sized data +* Add compare_double_and_swap_double and compare_and_swap_double +* Add gcc/cris.h (originally comes from Hans-Peter Nilsson) +* Add gcc/m68k.h (contributed by Tony Mantler) +* Add gcc/powerpc.h (with help of Maged Michael, Doug Lea, Roger Hoover) +* Add initial support for atomic_ops for VC++/Windows/X86 and HP/UX +* Add minimal support for the Sun SPARC compiler +* Add support for platforms that require out-of-line assembly code +* Add support of int-wide operations on platforms with int-sized pointers +* Added libatomic_ops_gpl library with support for lock-free stack and malloc +* Change atomic_ops include file structure +* Change most platforms to use byte-wide test-and-set locations +* Define AO_CLEAR, __ldcw[_align] macros in gcc/hppa.h (by Carlos O'Donell) +* Fix various bugs +* Install under "atomic_ops" instead of "ao" +* Remove compiler_barrier workaround for gcc 3.4+ +* Renamed various types to end in _t +* Replace AO_HAVE_NOP_FULL with AO_HAVE_nop_full (by Ranko Zivojnovic) +* Use autoconf, automake diff --git a/src/bdwgc/libatomic_ops/Makefile.am b/src/bdwgc/libatomic_ops/Makefile.am index a339e51c0..f71cf20ab 100644 --- a/src/bdwgc/libatomic_ops/Makefile.am +++ b/src/bdwgc/libatomic_ops/Makefile.am @@ -6,8 +6,19 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = pkgconfig/atomic_ops.pc noinst_DATA = pkgconfig/atomic_ops-uninstalled.pc -dist_pkgdata_DATA = COPYING README.md +if ENABLE_DOCS +dist_doc_DATA = COPYING README.md +endif EXTRA_DIST = autogen.sh +## TODO: After migration to autoconf-1.13+, remove check-nolink definition +## from this Makefile.am and add AM_EXTRA_RECURSIVE_TARGETS([check-nolink]) +## back to configure.ac file. +.PHONY: check-nolink check-nolink-local +check-nolink: check-nolink-local + $(MAKE) --directory tests $(AM_MAKEFLAGS) check-nolink-local + +check-nolink-local: all + #distclean-local: diff --git a/src/bdwgc/libatomic_ops/Makefile.in b/src/bdwgc/libatomic_ops/Makefile.in index 250109eb7..d0d917a59 100644 --- a/src/bdwgc/libatomic_ops/Makefile.in +++ b/src/bdwgc/libatomic_ops/Makefile.in @@ -98,7 +98,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ - $(am__configure_deps) $(dist_pkgdata_DATA) $(am__DIST_COMMON) + $(am__configure_deps) $(am__dist_doc_DATA_DIST) \ + $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d @@ -133,6 +134,7 @@ am__can_run_installinfo = \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac +am__dist_doc_DATA_DIST = COPYING README.md am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -160,9 +162,8 @@ am__uninstall_files_from_dir = { \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } -am__installdirs = "$(DESTDIR)$(pkgdatadir)" \ - "$(DESTDIR)$(pkgconfigdir)" -DATA = $(dist_pkgdata_DATA) $(noinst_DATA) $(pkgconfig_DATA) +am__installdirs = "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)" +DATA = $(dist_doc_DATA) $(noinst_DATA) $(pkgconfig_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ @@ -192,13 +193,11 @@ ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) -am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/../compile \ - $(top_srcdir)/../config.guess $(top_srcdir)/../config.sub \ - $(top_srcdir)/../install-sh $(top_srcdir)/../ltmain.sh \ - $(top_srcdir)/../missing \ +am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/pkgconfig/atomic_ops-uninstalled.pc.in \ $(top_srcdir)/pkgconfig/atomic_ops.pc.in AUTHORS COPYING \ - ChangeLog TODO + ChangeLog compile config.guess config.sub install-sh ltmain.sh \ + missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -234,9 +233,9 @@ am__relativize = \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" -DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 +DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best -DIST_TARGETS = dist-bzip2 dist-gzip +DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' @@ -255,6 +254,7 @@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +CFLAGS_EXTRA = @CFLAGS_EXTRA@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -371,7 +371,7 @@ ACLOCAL_AMFLAGS = -I m4 pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = pkgconfig/atomic_ops.pc noinst_DATA = pkgconfig/atomic_ops-uninstalled.pc -dist_pkgdata_DATA = COPYING README.md +@ENABLE_DOCS_TRUE@dist_doc_DATA = COPYING README.md EXTRA_DIST = autogen.sh all: all-recursive @@ -422,27 +422,27 @@ clean-libtool: distclean-libtool: -rm -f libtool config.lt -install-dist_pkgdataDATA: $(dist_pkgdata_DATA) +install-dist_docDATA: $(dist_doc_DATA) @$(NORMAL_INSTALL) - @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done -uninstall-dist_pkgdataDATA: +uninstall-dist_docDATA: @$(NORMAL_UNINSTALL) - @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ @@ -638,6 +638,7 @@ distdir: $(DISTFILES) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) + dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) @@ -763,7 +764,7 @@ check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: - for dir in "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(pkgconfigdir)"; do \ + for dir in "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive @@ -818,7 +819,7 @@ info: info-recursive info-am: -install-data-am: install-dist_pkgdataDATA install-pkgconfigDATA +install-data-am: install-dist_docDATA install-pkgconfigDATA install-dvi: install-dvi-recursive @@ -864,7 +865,7 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-dist_pkgdataDATA uninstall-pkgconfigDATA +uninstall-am: uninstall-dist_docDATA uninstall-pkgconfigDATA .MAKE: $(am__recursive_targets) install-am install-strip @@ -876,19 +877,25 @@ uninstall-am: uninstall-dist_pkgdataDATA uninstall-pkgconfigDATA distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ - install-dist_pkgdataDATA install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - installdirs-am maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ - ps ps-am tags tags-am uninstall uninstall-am \ - uninstall-dist_pkgdataDATA uninstall-pkgconfigDATA + install-dist_docDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pkgconfigDATA install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-dist_docDATA \ + uninstall-pkgconfigDATA .PRECIOUS: Makefile +.PHONY: check-nolink check-nolink-local +check-nolink: check-nolink-local + $(MAKE) --directory tests $(AM_MAKEFLAGS) check-nolink-local + +check-nolink-local: all + #distclean-local: # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/src/bdwgc/libatomic_ops/README.md b/src/bdwgc/libatomic_ops/README.md index 9d2b53db9..4ffe11b37 100644 --- a/src/bdwgc/libatomic_ops/README.md +++ b/src/bdwgc/libatomic_ops/README.md @@ -1,16 +1,24 @@ -# The atomic_ops library (libatomic_ops) +# The atomic_ops library (`libatomic_ops`) -This is version 7.5.0 of libatomic_ops. +IN NEW CODE, PLEASE USE C11 OR C++14 STANDARD ATOMICS INSTEAD OF THIS PACKAGE. -You might find a more recent version -[here](http://www.hboehm.info/gc/), or -[here](https://github.com/ivmai/libatomic_ops). +This is version 7.6.6 of libatomic_ops. + + +## Download + +You might find a more recent/stable version on the +[Download](https://github.com/ivmai/libatomic_ops/wiki/Download) page, or +[BDWGC site](http://www.hboehm.info/gc/). + +Also, the latest bug fixes and new features are available in the +[development repository](https://github.com/ivmai/libatomic_ops). ## Overview This package provides semi-portable access to hardware-provided -atomic memory update operations on a number architectures. These might +atomic memory update operations on a number of architectures. These might allow you to write code: * That does more interesting things in signal handlers. @@ -26,38 +34,87 @@ allow you to write code: For details and licensing restrictions see the files in the "doc" subdirectory. -Please address bug reports to [mailing list](mailto:bdwgc@lists.opendylan.org). - ## Installation and Usage The configuration and build scripts for this package were generated by -Automake/Autoconf. "./configure; make; sudo make install" in this +Automake/Autoconf. `./configure; make; sudo make install` in this directory should work. For a more customized build, see the output of -"./configure --help". +`./configure --help`. To build it from the development repository, +`./autogen.sh` should be executed first. Note that much of the content of this library is in the header files. However, two small libraries are built and installed: -* libatomic_ops.a is a support library, which is not needed on some platforms. - This is intended to be usable, under some mild restrictions, in free or - proprietary code, as are all the header files. See doc/LICENSING.txt. +* `libatomic_ops.a` is a support library, which is not needed on some + platforms. This is intended to be usable, under some mild restrictions, + in free or proprietary code, as are all the header files. + See doc/LICENSING.txt. -* libatomic_ops_gpl.a contains some higher level facilities. This code is +* `libatomic_ops_gpl.a` contains some higher level facilities. This code is currently covered by the GPL. The contents currently correspond to - the headers atomic_ops_stack.h and atomic_ops_malloc.h. + the headers `atomic_ops_stack.h` and `atomic_ops_malloc.h`. ## Platform Specific Notes Win32/64: src/Makefile.msft contains a very simple Makefile for building -and running tests and building the gpl library. The core atomic_ops +and running tests and building the gpl library. The core `libatomic_ops` implementation is entirely in header files. -HP-UX/PA-RISC: aCC -Ae won't work as a C compiler, since it doesn't support +HP-UX/PA-RISC: `aCC -Ae` won't work as a C compiler, since it doesn't support inline assembly code. Use cc. +## Feedback, Contribution, Questions and Notifications + +Please address bug reports and new feature ideas to +[GitHub issues](https://github.com/ivmai/libatomic_ops/issues). Before the +submission please check that it has not been done yet by someone else. + +If you want to contribute, submit +a [pull request](https://github.com/ivmai/libatomic_ops/pulls) to GitHub. + +If you need help, use +[Stack Overflow](https://stackoverflow.com/questions/tagged/atomic-ops). +Older questions on the site can be found by +[this query](https://stackoverflow.com/search?q=atomic_ops). +Older technical discussions are also available in `bdwgc` mailing list +archive - it can be downloaded as a +[compressed file](https://github.com/ivmai/bdwgc/files/1038163/bdwgc-mailing-list-archive-2017_04.tar.gz) +or browsed at [Narkive](http://bdwgc.opendylan.narkive.com) (please search +for _atomic_ keyword). + +To get new release announcements, subscribe to +[RSS feed](https://github.com/ivmai/libatomic_ops/releases.atom). +(To receive the notifications by email, a 3rd-party free service like +[IFTTT RSS Feed](https://ifttt.com/feed) can be setup.) +To be notified on all issues, please +[watch](https://github.com/ivmai/libatomic_ops/watchers) the project on +GitHub. + + ## Copyright & Warranty -See doc/LICENSING.txt file. + * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. + * Copyright (c) 1999-2011 Hewlett-Packard Development Company, L.P. + * Copyright (c) 2008-2018 Ivan Maidanski + +The file armcc/arm_v6.h is also + + * Copyright (c) 2007 by NEC LE-IT. All rights reserved. + +The file gcc/avr32.h is + + * Copyright (c) 2009 Bradley Smith + +The file gcc/mips.h is + + * Copyright (c) 2005, 2007 Thiemo Seufer + +The file gcc/sh.h is + + * Copyright (c) 2009 by Takashi YOSHII. All rights reserved. + +See doc/LICENSING.txt for the details. diff --git a/src/bdwgc/libatomic_ops/TODO b/src/bdwgc/libatomic_ops/TODO deleted file mode 100644 index 8a95ddb36..000000000 --- a/src/bdwgc/libatomic_ops/TODO +++ /dev/null @@ -1,13 +0,0 @@ -== TODO tasks == - -Add C++0x ATM (atomic memory operations) layer. - - -== FIXME tasks == - -RHELinux6/POWER7 (gcc-4.4.7-3/ppc64), Fedora16/POWER7 (gcc-4.6.2-1/ppc64), -Debian/powerpc (gcc 4.6.3-7): -test_stack failed (Debian Bug #680100). - -Debian/m68k (Linux 3.2.0-2-atari): -test_stack failed (Bus error), regression (Debian Bug #680066). diff --git a/src/bdwgc/libatomic_ops/compile b/src/bdwgc/libatomic_ops/compile new file mode 100755 index 000000000..a85b723c7 --- /dev/null +++ b/src/bdwgc/libatomic_ops/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/src/bdwgc/libatomic_ops/config.guess b/src/bdwgc/libatomic_ops/config.guess new file mode 100755 index 000000000..6c32c8645 --- /dev/null +++ b/src/bdwgc/libatomic_ops/config.guess @@ -0,0 +1,1421 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2014 Free Software Foundation, Inc. + +timestamp='2014-11-04' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2014 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/src/bdwgc/libatomic_ops/config.sub b/src/bdwgc/libatomic_ops/config.sub new file mode 100755 index 000000000..7ffe37378 --- /dev/null +++ b/src/bdwgc/libatomic_ops/config.sub @@ -0,0 +1,1807 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2014 Free Software Foundation, Inc. + +timestamp='2014-12-03' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2014 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/src/bdwgc/libatomic_ops/configure b/src/bdwgc/libatomic_ops/configure index 46c5fbcfd..acc5ea37f 100755 --- a/src/bdwgc/libatomic_ops/configure +++ b/src/bdwgc/libatomic_ops/configure @@ -1,8 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libatomic_ops 7.5.0. +# Generated by GNU Autoconf 2.69 for libatomic_ops 7.6.6. # -# Report bugs to . +# Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -275,10 +275,10 @@ fi $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and -$0: bdwgc@lists.opendylan.org about your system, including -$0: any error possibly output before this message. Then -$0: install a modern shell, or manually run the script -$0: under such a shell if you do have one." +$0: https://github.com/ivmai/libatomic_ops/issues about +$0: your system, including any error possibly output before +$0: this message. Then install a modern shell, or manually +$0: run the script under such a shell if you do have one." fi exit 1 fi @@ -590,9 +590,9 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libatomic_ops' PACKAGE_TARNAME='libatomic_ops' -PACKAGE_VERSION='7.5.0' -PACKAGE_STRING='libatomic_ops 7.5.0' -PACKAGE_BUGREPORT='bdwgc@lists.opendylan.org' +PACKAGE_VERSION='7.6.6' +PACKAGE_STRING='libatomic_ops 7.6.6' +PACKAGE_BUGREPORT='https://github.com/ivmai/libatomic_ops/issues' PACKAGE_URL='' ac_unique_file="src/atomic_ops.c" @@ -642,7 +642,10 @@ NEED_ASM_TRUE HAVE_PTHREAD_H_FALSE HAVE_PTHREAD_H_TRUE THREADDLLIBS +CFLAGS_EXTRA PICFLAG +ENABLE_DOCS_FALSE +ENABLE_DOCS_TRUE CPP LT_SYS_LIBRARY_PATH OTOOL64 @@ -784,6 +787,9 @@ with_sysroot enable_libtool_lock enable_werror enable_assertions +enable_atomic_intrinsics +enable_gcov +enable_docs ' ac_precious_vars='build_alias host_alias @@ -1337,7 +1343,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libatomic_ops 7.5.0 to adapt to many kinds of systems. +\`configure' configures libatomic_ops 7.6.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1408,7 +1414,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libatomic_ops 7.5.0:";; + short | recursive ) echo "Configuration of libatomic_ops 7.6.6:";; esac cat <<\_ACEOF @@ -1432,6 +1438,10 @@ Optional Features: --disable-libtool-lock avoid locking (might break parallel builds) --enable-werror Pass -Werror to the C compiler --enable-assertions Assertion checking + --disable-atomic-intrinsics + Do not use C11 atomic intrinsics + --enable-gcov Turn on code coverage analysis + --disable-docs Do not build and install documentation Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1462,7 +1472,7 @@ Some influential environment variables: Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. -Report bugs to . +Report bugs to . _ACEOF ac_status=$? fi @@ -1525,7 +1535,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libatomic_ops configure 7.5.0 +libatomic_ops configure 7.6.6 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1803,7 +1813,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libatomic_ops $as_me 7.5.0, which was +It was created by libatomic_ops $as_me 7.6.6, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2783,7 +2793,7 @@ fi # Define the identity of the package. PACKAGE='libatomic_ops' - VERSION='7.5.0' + VERSION='7.6.6' cat >>confdefs.h <<_ACEOF @@ -2903,7 +2913,6 @@ fi ac_config_headers="$ac_config_headers src/config.h" -# Checks for programs. DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" @@ -12075,7 +12084,6 @@ CC=$lt_save_CC -# Checks for functions. @@ -12284,18 +12292,23 @@ PICFLAG= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PIC compiler flag" >&5 $as_echo_n "checking for PIC compiler flag... " >&6; } if test "$GCC" = yes; then + old_CC="$CC" + if test -n "$CROSS_CC"; then + CC="$CROSS_CC" + fi + case "$host" in *-*-cygwin* | *-*-mingw*) # Cygwin and Mingw[-w32/64] do not need -fPIC. - { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"\"" >&5 -$as_echo "\"\"" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not needed" >&5 +$as_echo "not needed" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: -fPIC" >&5 $as_echo "-fPIC" >&6; } PICFLAG=-fPIC - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc -fPIC causes __PIC__ definition" >&5 -$as_echo_n "checking whether gcc -fPIC causes __PIC__ definition... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -fPIC compiler option causes __PIC__ definition" >&5 +$as_echo_n "checking whether -fPIC compiler option causes __PIC__ definition... " >&6; } # Workaround: at least GCC 3.4.6 (Solaris) does not define this macro. old_CFLAGS="$CFLAGS" CFLAGS="$PICFLAG $CFLAGS" @@ -12332,8 +12345,8 @@ fi esac # Output all warnings. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc -Wextra" >&5 -$as_echo_n "checking for gcc -Wextra... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wextra" >&5 +$as_echo_n "checking whether compiler supports -Wextra... " >&6; } old_CFLAGS="$CFLAGS" CFLAGS="-Wextra $CFLAGS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -12361,7 +12374,36 @@ $as_echo "$ac_cv_cc_wextra" >&6; } else WEXTRA="-W" fi - CFLAGS="-Wall $WEXTRA $CFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wpedantic" >&5 +$as_echo_n "checking whether compiler supports -Wpedantic... " >&6; } + CFLAGS="-Wpedantic -Wno-long-long $CFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +extern int quiet; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_cc_pedantic=yes +else + ac_cv_cc_pedantic=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$old_CFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_pedantic" >&5 +$as_echo "$ac_cv_cc_pedantic" >&6; } + WPEDANTIC= + if test "$ac_cv_cc_pedantic" = yes; then : + WPEDANTIC="-Wpedantic -Wno-long-long" +fi + CFLAGS="-Wall $WEXTRA $WPEDANTIC $CFLAGS" # Check whether --enable-werror was given. if test "${enable_werror+set}" = set; then : @@ -12371,11 +12413,13 @@ fi if test "$enable_werror" = yes; then CFLAGS="-Werror $CFLAGS" fi + + CC="$old_CC" else case "$host" in *-*-hpux*) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"+Z\"" >&5 -$as_echo "\"+Z\"" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: +Z" >&5 +$as_echo "+Z" >&6; } PICFLAG="+Z" CFLAGS="+O2 -mt $CFLAGS" ;; @@ -12393,8 +12437,8 @@ $as_echo "-fPIC" >&6; } # Any Linux compiler had better be gcc compatible. ;; *) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"\"" >&5 -$as_echo "\"\"" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } ;; esac fi @@ -12410,6 +12454,44 @@ $as_echo "#define NDEBUG 1" >>confdefs.h fi +# Check whether --enable-atomic-intrinsics was given. +if test "${enable_atomic_intrinsics+set}" = set; then : + enableval=$enable_atomic_intrinsics; +fi + +if test "$enable_atomic_intrinsics" = no; then + +$as_echo "#define AO_DISABLE_GCC_ATOMICS 1" >>confdefs.h + +fi + +# Check whether --enable-gcov was given. +if test "${enable_gcov+set}" = set; then : + enableval=$enable_gcov; +fi + +if test "$enable_gcov" = "yes"; then + CFLAGS="$CFLAGS --coverage" + # Turn off code optimization to get accurate line numbers. + CFLAGS=`echo "$CFLAGS" | sed -e 's/-O\(1\|2\|3\|4\|s\|fast\)\?//g'` +fi + +# Check whether --enable-docs was given. +if test "${enable_docs+set}" = set; then : + enableval=$enable_docs; +fi + + if test x$enable_docs != xno; then + ENABLE_DOCS_TRUE= + ENABLE_DOCS_FALSE='#' +else + ENABLE_DOCS_TRUE='#' + ENABLE_DOCS_FALSE= +fi + + + + @@ -12420,7 +12502,6 @@ fi -# These macros are tested in public headers @@ -12678,6 +12759,10 @@ if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${ENABLE_DOCS_TRUE}" && test -z "${ENABLE_DOCS_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_DOCS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${HAVE_PTHREAD_H_TRUE}" && test -z "${HAVE_PTHREAD_H_FALSE}"; then as_fn_error $? "conditional \"HAVE_PTHREAD_H\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -13083,7 +13168,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libatomic_ops $as_me 7.5.0, which was +This file was extended by libatomic_ops $as_me 7.6.6, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -13143,13 +13228,13 @@ $config_headers Configuration commands: $config_commands -Report bugs to ." +Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libatomic_ops config.status 7.5.0 +libatomic_ops config.status 7.6.6 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/src/bdwgc/libatomic_ops/configure.ac b/src/bdwgc/libatomic_ops/configure.ac index e11b9c7ce..6bcfa9b23 100644 --- a/src/bdwgc/libatomic_ops/configure.ac +++ b/src/bdwgc/libatomic_ops/configure.ac @@ -1,21 +1,34 @@ -# Process this file with autoconf to produce a configure script. -AC_INIT([libatomic_ops],[7.5.0],bdwgc@lists.opendylan.org) +# Copyright (c) 2005-2006 Hewlett-Packard Development Company, L.P. +# Copyright (c) 2009-2018 Ivan Maidanski +# +# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED +# OR IMPLIED. ANY USE IS AT YOUR OWN RISK. +# +# Permission is hereby granted to use or copy this program +# for any purpose, provided the above notices are retained on all copies. +# Permission to modify the code and to distribute modified code is granted, +# provided the above notices are retained, and a notice that the code was +# modified is included with the above copyright notice. + +dnl Process this file with autoconf to produce configure. + +AC_INIT([libatomic_ops],[7.6.6],https://github.com/ivmai/libatomic_ops/issues) AC_PREREQ(2.61) AC_CANONICAL_TARGET([]) AC_CONFIG_SRCDIR(src/atomic_ops.c) AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE([foreign dist-bzip2 nostdinc]) +AM_INIT_AUTOMAKE([foreign nostdinc]) AM_MAINTAINER_MODE AC_CONFIG_HEADERS([src/config.h]) -# Checks for programs. +dnl Checks for programs. AM_PROG_CC_C_O AM_PROG_AS LT_INIT([disable-shared]) -# Checks for functions. +dnl Checks for functions. AC_FUNC_MMAP # Determine PIC flag. @@ -23,15 +36,20 @@ need_asm=false PICFLAG= AC_MSG_CHECKING(for PIC compiler flag) if test "$GCC" = yes; then + old_CC="$CC" + if test -n "$CROSS_CC"; then + CC="$CROSS_CC" + fi + case "$host" in *-*-cygwin* | *-*-mingw*) # Cygwin and Mingw[-w32/64] do not need -fPIC. - AC_MSG_RESULT("") + AC_MSG_RESULT([not needed]) ;; *) AC_MSG_RESULT(-fPIC) PICFLAG=-fPIC - AC_MSG_CHECKING(whether gcc -fPIC causes __PIC__ definition) + AC_MSG_CHECKING(whether -fPIC compiler option causes __PIC__ definition) # Workaround: at least GCC 3.4.6 (Solaris) does not define this macro. old_CFLAGS="$CFLAGS" CFLAGS="$PICFLAG $CFLAGS" @@ -48,24 +66,36 @@ if test "$GCC" = yes; then esac # Output all warnings. - AC_MSG_CHECKING(for gcc -Wextra) + AC_MSG_CHECKING([whether compiler supports -Wextra]) old_CFLAGS="$CFLAGS" CFLAGS="-Wextra $CFLAGS" AC_TRY_COMPILE([],[], [ac_cv_cc_wextra=yes], [ac_cv_cc_wextra=no]) CFLAGS="$old_CFLAGS" AC_MSG_RESULT($ac_cv_cc_wextra) AS_IF([test "$ac_cv_cc_wextra" = yes], [WEXTRA="-Wextra"], [WEXTRA="-W"]) - CFLAGS="-Wall $WEXTRA $CFLAGS" + AC_MSG_CHECKING([whether compiler supports -Wpedantic]) + CFLAGS="-Wpedantic -Wno-long-long $CFLAGS" + AC_TRY_COMPILE([],[ +extern int quiet; + ], [ac_cv_cc_pedantic=yes], [ac_cv_cc_pedantic=no]) + CFLAGS="$old_CFLAGS" + AC_MSG_RESULT($ac_cv_cc_pedantic) + WPEDANTIC= + AS_IF([test "$ac_cv_cc_pedantic" = yes], + [WPEDANTIC="-Wpedantic -Wno-long-long"]) + CFLAGS="-Wall $WEXTRA $WPEDANTIC $CFLAGS" AC_ARG_ENABLE(werror, [AC_HELP_STRING([--enable-werror], [Pass -Werror to the C compiler])]) if test "$enable_werror" = yes; then CFLAGS="-Werror $CFLAGS" fi + + CC="$old_CC" else case "$host" in *-*-hpux*) - AC_MSG_RESULT("+Z") + AC_MSG_RESULT([+Z]) PICFLAG="+Z" CFLAGS="+O2 -mt $CFLAGS" ;; @@ -81,7 +111,7 @@ else # Any Linux compiler had better be gcc compatible. ;; *) - AC_MSG_RESULT("") + AC_MSG_RESULT([none]) ;; esac fi @@ -92,9 +122,33 @@ if test "$enable_assertions" != yes; then AC_DEFINE([NDEBUG], 1, [Define to disable assertion checking.]) fi +AC_ARG_ENABLE(atomic-intrinsics, + [AC_HELP_STRING([--disable-atomic-intrinsics], + [Do not use C11 atomic intrinsics])]) +if test "$enable_atomic_intrinsics" = no; then + AC_DEFINE([AO_DISABLE_GCC_ATOMICS], 1, + [Define to avoid C11 atomic intrinsics even if available.]) +fi + +AC_ARG_ENABLE(gcov, AC_HELP_STRING([--enable-gcov], + [Turn on code coverage analysis])) +if test "$enable_gcov" = "yes"; then + CFLAGS="$CFLAGS --coverage" + # Turn off code optimization to get accurate line numbers. + CFLAGS=`echo "$CFLAGS" | sed -e 's/-O\(1\|2\|3\|4\|s\|fast\)\?//g'` +fi + +AC_ARG_ENABLE(docs, + [AC_HELP_STRING([--disable-docs], + [Do not build and install documentation])]) +AM_CONDITIONAL(ENABLE_DOCS, test x$enable_docs != xno) + AC_SUBST(PICFLAG) AC_SUBST(DEFS) +dnl Extra user-defined C flags. +AC_SUBST([CFLAGS_EXTRA]) + AH_TEMPLATE([_PTHREADS], [Indicates the use of pthreads (NetBSD).]) AH_TEMPLATE([AO_USE_NANOSLEEP], @@ -108,7 +162,7 @@ AH_TEMPLATE([AO_USE_WIN32_PTHREADS], are emulated)]) AH_TEMPLATE([AO_TRACE_MALLOC], [Trace AO_malloc/free calls (for debug only)]) -# These macros are tested in public headers +dnl These macros are tested in public headers. AH_TEMPLATE([AO_GENERALIZE_ASM_BOOL_CAS], [Force compare_and_swap definition via fetch_compare_and_swap]) AH_TEMPLATE([AO_PREFER_GENERALIZED], @@ -117,12 +171,9 @@ AH_TEMPLATE([AO_USE_PTHREAD_DEFS], [Emulate atomic operations via slow and async-signal-unsafe \ pthread locking]) AH_TEMPLATE([AO_ASM_X64_AVAILABLE], - [Inline assembly avalable (only VC/x86_64)]) + [Inline assembly available (only VC/x86_64)]) AH_TEMPLATE([AO_ASSUME_VISTA], [Assume Windows Server 2003, Vista or later target (only VC/x86)]) -AH_TEMPLATE([AO_ASSUME_WINDOWS98], - [Assume hardware compare-and-swap functionality available \ - on target (only VC/x86)]) AH_TEMPLATE([AO_CMPXCHG16B_AVAILABLE], [Assume target is not old AMD Opteron chip (only x86_64)]) AH_TEMPLATE([AO_FORCE_USE_SWP], @@ -143,6 +194,10 @@ AH_TEMPLATE([AO_USE_SYNC_CAS_BUILTIN], AH_TEMPLATE([AO_WEAK_DOUBLE_CAS_EMULATION], [Emulate double-width CAS via pthread locking in case of no hardware \ support (only gcc/x86_64, the emulation is unsafe)]) +AH_TEMPLATE([AO_PREFER_BUILTIN_ATOMICS], + [Prefer C11 atomic intrinsics over assembly-based implementation \ + even in case of inefficient implementation (do not use assembly for \ + any atomic_ops primitive if C11/GCC atomic intrinsics available)]) AC_DEFINE(_REENTRANT, 1, [Required define if using POSIX threads.]) diff --git a/src/bdwgc/libatomic_ops/depcomp b/src/bdwgc/libatomic_ops/depcomp new file mode 100755 index 000000000..fc98710e2 --- /dev/null +++ b/src/bdwgc/libatomic_ops/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2013-05-30.07; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/src/bdwgc/libatomic_ops/doc/Makefile.am b/src/bdwgc/libatomic_ops/doc/Makefile.am index c32bb6fef..571b52b67 100644 --- a/src/bdwgc/libatomic_ops/doc/Makefile.am +++ b/src/bdwgc/libatomic_ops/doc/Makefile.am @@ -1,4 +1,7 @@ # installed documentation # -dist_pkgdata_DATA=LICENSING.txt README.txt README_stack.txt \ + +if ENABLE_DOCS +dist_doc_DATA = LICENSING.txt README_details.txt README_stack.txt \ README_malloc.txt README_win32.txt +endif diff --git a/src/bdwgc/libatomic_ops/doc/Makefile.in b/src/bdwgc/libatomic_ops/doc/Makefile.in index b3f3ec568..88d6bfa45 100644 --- a/src/bdwgc/libatomic_ops/doc/Makefile.in +++ b/src/bdwgc/libatomic_ops/doc/Makefile.in @@ -14,6 +14,9 @@ @SET_MAKE@ +# installed documentation +# + VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ @@ -97,7 +100,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) -DIST_COMMON = $(srcdir)/Makefile.am $(dist_pkgdata_DATA) \ +DIST_COMMON = $(srcdir)/Makefile.am $(am__dist_doc_DATA_DIST) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h @@ -122,6 +125,8 @@ am__can_run_installinfo = \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac +am__dist_doc_DATA_DIST = LICENSING.txt README_details.txt \ + README_stack.txt README_malloc.txt README_win32.txt am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -149,8 +154,8 @@ am__uninstall_files_from_dir = { \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } -am__installdirs = "$(DESTDIR)$(pkgdatadir)" -DATA = $(dist_pkgdata_DATA) +am__installdirs = "$(DESTDIR)$(docdir)" +DATA = $(dist_doc_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -168,6 +173,7 @@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ +CFLAGS_EXTRA = @CFLAGS_EXTRA@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -279,11 +285,8 @@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ - -# installed documentation -# -dist_pkgdata_DATA = LICENSING.txt README.txt README_stack.txt \ - README_malloc.txt README_win32.txt +@ENABLE_DOCS_TRUE@dist_doc_DATA = LICENSING.txt README_details.txt README_stack.txt \ +@ENABLE_DOCS_TRUE@ README_malloc.txt README_win32.txt all: all-am @@ -323,27 +326,27 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs -install-dist_pkgdataDATA: $(dist_pkgdata_DATA) +install-dist_docDATA: $(dist_doc_DATA) @$(NORMAL_INSTALL) - @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done -uninstall-dist_pkgdataDATA: +uninstall-dist_docDATA: @$(NORMAL_UNINSTALL) - @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ + @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: @@ -385,7 +388,7 @@ check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: - for dir in "$(DESTDIR)$(pkgdatadir)"; do \ + for dir in "$(DESTDIR)$(docdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -438,7 +441,7 @@ info: info-am info-am: -install-data-am: install-dist_pkgdataDATA +install-data-am: install-dist_docDATA install-dvi: install-dvi-am @@ -482,7 +485,7 @@ ps: ps-am ps-am: -uninstall-am: uninstall-dist_pkgdataDATA +uninstall-am: uninstall-dist_docDATA .MAKE: install-am install-strip @@ -490,14 +493,14 @@ uninstall-am: uninstall-dist_pkgdataDATA cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ - install-dist_pkgdataDATA install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ + install-dist_docDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ - uninstall-am uninstall-dist_pkgdataDATA + uninstall-am uninstall-dist_docDATA .PRECIOUS: Makefile diff --git a/src/bdwgc/libatomic_ops/doc/README.txt b/src/bdwgc/libatomic_ops/doc/README_details.txt similarity index 91% rename from src/bdwgc/libatomic_ops/doc/README.txt rename to src/bdwgc/libatomic_ops/doc/README_details.txt index b06f6a60a..df124ab8b 100644 --- a/src/bdwgc/libatomic_ops/doc/README.txt +++ b/src/bdwgc/libatomic_ops/doc/README_details.txt @@ -25,9 +25,9 @@ by synthesis). This is an attempt to replace various existing files with similar goals, since they usually do not handle differences in memory barrier styles with sufficient generality. -If this is included after defining AO_REQUIRE_CAS, then the package -will make an attempt to emulate compare-and-swap in a way that (at least -on Linux) should still be async-signal-safe. As a result, most other +If this is included after defining AO_REQUIRE_CAS, then the package makes +an attempt to emulate AO_compare_and_swap* (single-width) in a way that (at +least on Linux) should still be async-signal-safe. As a result, most other atomic operations will then be defined using the compare-and-swap emulation. This emulation is slow, since it needs to disable signals. And it needs to block in case of contention. If you care about performance @@ -140,6 +140,16 @@ both of type AO_t. For compare_and_swap_double, we compare against the val1 field. AO_double_t exists only if AO_HAVE_double_t is defined. +Please note that AO_double_t (and AO_stack_t) variables should be properly +aligned (8-byte alignment on 32-bit targets, 16-byte alignment on 64-bit ones) +otherwise the behavior of a double-wide atomic primitive might be undefined +(or an assertion violation might occur) if such a misaligned variable is +passed (as a reference) to the primitive. Global and static variables should +already have proper alignment automatically but automatic variables (i.e. +located on the stack) might be misaligned because the stack might be +word-aligned (e.g. 4-byte stack alignment is the default one for x86). +Luckily, stack-allocated AO variables is a rare case in practice. + ORDERING CONSTRAINTS: Each operation name also includes a suffix that specifies the associated @@ -160,7 +170,9 @@ _read: Subsequent reads must become visible after reads included in the atomic operation or preceding it. Rarely useful for clients? _write: Earlier writes become visible before writes during or after the atomic operation. Rarely useful for clients? -_full: Ordered with respect to both earlier and later memory ops. +_full: The associated operation is ordered with respect to both earlier and + later memory ops. If the associated operation is nop, then this orders + all earlier memory operations with respect to subsequent ones. AO_store_full or AO_nop_full are the normal ways to force a store to be ordered with respect to a later load. _release_write: Ordered with respect to earlier writes. This is @@ -204,13 +216,6 @@ macro expansions of all implemented operations on the platform: make list_atomic.i -Future directions: - -It currently appears that something roughly analogous to this is very likely -to become part of the C++0x standard. That effort has pointed out a number -of issues that we expect to address there. Since some of the solutions -really require compiler support, they may not be completely addressed here. - Known issues include: We should be more precise in defining the semantics of the ordering @@ -235,12 +240,6 @@ Platform notes: All X86: We quietly assume 486 or better. -Microsoft compilers: -Define AO_ASSUME_WINDOWS98 to get access to hardware compare-and-swap -functionality. This relies on the InterlockedCompareExchange() function -which was apparently not supported in Windows95. (There may be a better -way to get access to this.) - Gcc on x86: Define AO_USE_PENTIUM4_INSTRS to use the Pentium 4 mfence instruction. Currently this is appears to be of marginal benefit. diff --git a/src/bdwgc/libatomic_ops/doc/README_win32.txt b/src/bdwgc/libatomic_ops/doc/README_win32.txt index e2b87ad8b..c9e81d9cc 100644 --- a/src/bdwgc/libatomic_ops/doc/README_win32.txt +++ b/src/bdwgc/libatomic_ops/doc/README_win32.txt @@ -22,10 +22,8 @@ pieces from the resulting src directory contents: The atomic_ops.h implementation is entirely in the header files in Win32. -Most clients of atomic_ops.h will need to define AO_ASSUME_WINDOWS98 before -including it. Compare_and_swap is otherwise not available. -Defining AO_ASSUME_VISTA will make compare_double_and_swap_double available -as well. +If the client defines AO_ASSUME_VISTA (before include atomic_ops.h), it should +make double_compare_and_swap_full available. Note that the library is covered by the GNU General Public License, while the top 2 of these pieces allow use in proprietary code. diff --git a/src/bdwgc/libatomic_ops/install-sh b/src/bdwgc/libatomic_ops/install-sh new file mode 100755 index 000000000..0b0fdcbba --- /dev/null +++ b/src/bdwgc/libatomic_ops/install-sh @@ -0,0 +1,501 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2013-12-25.23; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/src/bdwgc/libatomic_ops/ltmain.sh b/src/bdwgc/libatomic_ops/ltmain.sh new file mode 100644 index 000000000..0f0a2da3f --- /dev/null +++ b/src/bdwgc/libatomic_ops/ltmain.sh @@ -0,0 +1,11147 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4.6 +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -stdlib=* select c++ std lib with clang + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/src/bdwgc/libatomic_ops/m4/libtool.m4 b/src/bdwgc/libatomic_ops/m4/libtool.m4 new file mode 100644 index 000000000..a3bc337b7 --- /dev/null +++ b/src/bdwgc/libatomic_ops/m4/libtool.m4 @@ -0,0 +1,8369 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/src/bdwgc/libatomic_ops/m4/ltoptions.m4 b/src/bdwgc/libatomic_ops/m4/ltoptions.m4 new file mode 100644 index 000000000..94b082976 --- /dev/null +++ b/src/bdwgc/libatomic_ops/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/src/bdwgc/libatomic_ops/m4/ltsugar.m4 b/src/bdwgc/libatomic_ops/m4/ltsugar.m4 new file mode 100644 index 000000000..48bc9344a --- /dev/null +++ b/src/bdwgc/libatomic_ops/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/src/bdwgc/libatomic_ops/m4/ltversion.m4 b/src/bdwgc/libatomic_ops/m4/ltversion.m4 new file mode 100644 index 000000000..fa04b52a3 --- /dev/null +++ b/src/bdwgc/libatomic_ops/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/src/bdwgc/libatomic_ops/m4/lt~obsolete.m4 b/src/bdwgc/libatomic_ops/m4/lt~obsolete.m4 new file mode 100644 index 000000000..c6b26f88f --- /dev/null +++ b/src/bdwgc/libatomic_ops/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/src/bdwgc/libatomic_ops/missing b/src/bdwgc/libatomic_ops/missing new file mode 100755 index 000000000..f62bbae30 --- /dev/null +++ b/src/bdwgc/libatomic_ops/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/src/bdwgc/libatomic_ops/src/Makefile.am b/src/bdwgc/libatomic_ops/src/Makefile.am index fc09b27e1..ae5f24fe2 100644 --- a/src/bdwgc/libatomic_ops/src/Makefile.am +++ b/src/bdwgc/libatomic_ops/src/Makefile.am @@ -1,6 +1,15 @@ + +# Info (current:revision:age) for the Libtool versioning system. +# These numbers should be updated at most once just before the release, +# and, optionally, at most once during the development (after the release). +LIBATOMIC_OPS_VER_INFO = 2:1:1 +LIBATOMIC_OPS_GPL_VER_INFO = 2:2:1 + AM_CFLAGS=@PICFLAG@ AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src +CFLAGS += $(CFLAGS_EXTRA) + include_HEADERS = atomic_ops.h atomic_ops_stack.h atomic_ops_malloc.h lib_LTLIBRARIES = libatomic_ops.la libatomic_ops_gpl.la if NEED_ASM @@ -8,10 +17,12 @@ libatomic_ops_la_SOURCES = atomic_ops.c atomic_ops_sysdeps.S else libatomic_ops_la_SOURCES = atomic_ops.c endif -libatomic_ops_la_LDFLAGS = -version-info 1:3:0 -no-undefined +libatomic_ops_la_LDFLAGS = -version-info $(LIBATOMIC_OPS_VER_INFO) \ + -no-undefined libatomic_ops_gpl_la_SOURCES = atomic_ops_stack.c atomic_ops_malloc.c -libatomic_ops_gpl_la_LDFLAGS = -version-info 1:3:0 -no-undefined +libatomic_ops_gpl_la_LDFLAGS = -version-info $(LIBATOMIC_OPS_GPL_VER_INFO) \ + -no-undefined libatomic_ops_gpl_la_LIBADD = libatomic_ops.la EXTRA_DIST = Makefile.msft atomic_ops/sysdeps/README \ @@ -80,9 +91,11 @@ nobase_private_HEADERS = atomic_ops/ao_version.h \ atomic_ops/sysdeps/gcc/m68k.h \ atomic_ops/sysdeps/gcc/mips.h \ atomic_ops/sysdeps/gcc/powerpc.h \ + atomic_ops/sysdeps/gcc/riscv.h \ atomic_ops/sysdeps/gcc/s390.h \ atomic_ops/sysdeps/gcc/sh.h \ atomic_ops/sysdeps/gcc/sparc.h \ + atomic_ops/sysdeps/gcc/tile.h \ atomic_ops/sysdeps/gcc/x86.h \ \ atomic_ops/sysdeps/hpc/hppa.h \ diff --git a/src/bdwgc/libatomic_ops/src/Makefile.in b/src/bdwgc/libatomic_ops/src/Makefile.in index 123844a41..53d1f9bf4 100644 --- a/src/bdwgc/libatomic_ops/src/Makefile.in +++ b/src/bdwgc/libatomic_ops/src/Makefile.in @@ -169,7 +169,7 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -depcomp = $(SHELL) $(top_srcdir)/../depcomp +depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ @@ -230,7 +230,7 @@ am__define_uniq_tagged_files = \ ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ - $(top_srcdir)/../depcomp + $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -245,7 +245,8 @@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ $(CFLAGS_EXTRA) +CFLAGS_EXTRA = @CFLAGS_EXTRA@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -357,15 +358,25 @@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ + +# Info (current:revision:age) for the Libtool versioning system. +# These numbers should be updated at most once just before the release, +# and, optionally, at most once during the development (after the release). +LIBATOMIC_OPS_VER_INFO = 2:1:1 +LIBATOMIC_OPS_GPL_VER_INFO = 2:2:1 AM_CFLAGS = @PICFLAG@ AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src include_HEADERS = atomic_ops.h atomic_ops_stack.h atomic_ops_malloc.h lib_LTLIBRARIES = libatomic_ops.la libatomic_ops_gpl.la @NEED_ASM_FALSE@libatomic_ops_la_SOURCES = atomic_ops.c @NEED_ASM_TRUE@libatomic_ops_la_SOURCES = atomic_ops.c atomic_ops_sysdeps.S -libatomic_ops_la_LDFLAGS = -version-info 1:3:0 -no-undefined +libatomic_ops_la_LDFLAGS = -version-info $(LIBATOMIC_OPS_VER_INFO) \ + -no-undefined + libatomic_ops_gpl_la_SOURCES = atomic_ops_stack.c atomic_ops_malloc.c -libatomic_ops_gpl_la_LDFLAGS = -version-info 1:3:0 -no-undefined +libatomic_ops_gpl_la_LDFLAGS = -version-info $(LIBATOMIC_OPS_GPL_VER_INFO) \ + -no-undefined + libatomic_ops_gpl_la_LIBADD = libatomic_ops.la EXTRA_DIST = Makefile.msft atomic_ops/sysdeps/README \ atomic_ops/generalize-arithm.template \ @@ -434,9 +445,11 @@ nobase_private_HEADERS = atomic_ops/ao_version.h \ atomic_ops/sysdeps/gcc/m68k.h \ atomic_ops/sysdeps/gcc/mips.h \ atomic_ops/sysdeps/gcc/powerpc.h \ + atomic_ops/sysdeps/gcc/riscv.h \ atomic_ops/sysdeps/gcc/s390.h \ atomic_ops/sysdeps/gcc/sh.h \ atomic_ops/sysdeps/gcc/sparc.h \ + atomic_ops/sysdeps/gcc/tile.h \ atomic_ops/sysdeps/gcc/x86.h \ \ atomic_ops/sysdeps/hpc/hppa.h \ diff --git a/src/bdwgc/libatomic_ops/src/Makefile.msft b/src/bdwgc/libatomic_ops/src/Makefile.msft index 56c0bc3c1..f06a03f32 100644 --- a/src/bdwgc/libatomic_ops/src/Makefile.msft +++ b/src/bdwgc/libatomic_ops/src/Makefile.msft @@ -5,18 +5,19 @@ # only AO_pause (used by atomic_ops_stack). # And we rely on a pre-built test_atomic_include.h and generalize-small.h, # since we can't rely on sed. But we don't keep test_atomic_include.h in -# the development repository any longer, so if you want to do "make check" +# the development repository any longer, so if you want to run all tests # for the sources obtained from the repository then -# do "autoreconf -vif; ./configure; make check" in Cygwin first. +# type "./autogen.sh && ./configure && make -j && make clean" in Cygwin first. +# Otherwise type "nmake -f Makefile.msft check-noautogen" to run only the +# tests not requiring the source auto-generation. # Win32 clients only need to include the header files. # To install, copy atomic_ops.h and the atomic_ops/... tree to your favorite # include directory. -#MY_CPU=X86 -#CPU=$(MY_CPU) #!include -CFLAGS=-O2 -W3 -DAO_ASSUME_WINDOWS98 +CFLAGS_EXTRA= +CFLAGS=-O2 -W3 $(CFLAGS_EXTRA) LIB_OBJS=atomic_ops.obj atomic_ops_malloc.obj atomic_ops_stack.obj @@ -37,8 +38,9 @@ libatomic_ops_gpl.lib: $(LIB_OBJS) test_atomic: ..\tests\test_atomic.c ..\tests\test_atomic_include.h cl $(CFLAGS) -I. ..\tests\test_atomic.c /Fo.\test_atomic -test_atomic_w95: ..\tests\test_atomic.c ..\tests\test_atomic_include.h - cl -W3 -O2 -I. ..\tests\test_atomic.c /Fo.\test_atomic_w95 +test_atomic_generalized: ..\tests\test_atomic.c ..\tests\test_atomic_include.h + cl $(CFLAGS) -DAO_PREFER_GENERALIZED -I. ..\tests\test_atomic.c \ + /Fo.\test_atomic_generalized test_malloc: ..\tests\test_malloc.c libatomic_ops_gpl.lib cl $(CFLAGS) -I. ..\tests\test_malloc.c /Fo.\test_malloc \ @@ -48,11 +50,12 @@ test_stack: ..\tests\test_stack.c libatomic_ops_gpl.lib cl $(CFLAGS) -I. ..\tests\test_stack.c /Fo.\test_stack \ libatomic_ops_gpl.lib -check: test_atomic test_atomic_w95 test_malloc test_stack - @echo "The following will print lots of 'Missing ...' messages" - test_atomic_w95 +check: test_atomic test_atomic_generalized check-noautogen @echo "The following will print some 'Missing ...' messages" test_atomic + test_atomic_generalized + +check-noautogen: test_malloc test_stack test_malloc test_stack diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops.c b/src/bdwgc/libatomic_ops/src/atomic_ops.c index 30dd21cac..5f33a9056 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops.c +++ b/src/bdwgc/libatomic_ops/src/atomic_ops.c @@ -32,8 +32,10 @@ # include "config.h" #endif -#if defined(__native_client__) && !defined(AO_USE_NO_SIGNALS) \ - && !defined(AO_USE_NANOSLEEP) +#if (defined(__hexagon__) || defined(__native_client__)) \ + && !defined(AO_USE_NO_SIGNALS) && !defined(AO_USE_NANOSLEEP) + /* Hexagon QuRT does not have sigprocmask (but Hexagon does not need */ + /* emulation, so it is OK not to bother about signals blocking). */ /* Since NaCl is not recognized by configure yet, we do it here. */ # define AO_USE_NO_SIGNALS # define AO_USE_NANOSLEEP @@ -43,6 +45,11 @@ # define AO_USE_NO_SIGNALS #endif +#if (defined(__linux__) || defined(__GLIBC__) || defined(__GNU__)) \ + && !defined(AO_USE_NO_SIGNALS) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE 1 +#endif + #undef AO_REQUIRE_CAS #include "atomic_ops.h" /* Without cas emulation! */ @@ -94,7 +101,7 @@ #define AO_HASH(x) (((unsigned long)(x) >> 12) & (AO_HASH_SIZE-1)) -AO_TS_t AO_locks[AO_HASH_SIZE] = { +static AO_TS_t AO_locks[AO_HASH_SIZE] = { AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, AO_TS_INITIALIZER, @@ -238,16 +245,21 @@ void AO_pause(int n) # ifdef AO_USE_NANOSLEEP struct timespec ts; ts.tv_sec = 0; - ts.tv_nsec = (n > 28 ? 100000 * 1000 : 1 << (n - 2)); + ts.tv_nsec = n > 28 ? 100000L * 1000 : 1L << (n - 2); nanosleep(&ts, 0); # elif defined(AO_USE_WIN32_PTHREADS) - Sleep(n > 28 ? 100 : n < 22 ? 1 : 1 << (n - 22)); /* in millis */ + Sleep(n > 28 ? 100 /* millis */ + : n < 22 ? 1 : (DWORD)1 << (n - 22)); # else struct timeval tv; /* Short async-signal-safe sleep. */ + int usec = n > 28 ? 100000 : 1 << (n - 12); + /* Use an intermediate variable (of int type) to avoid */ + /* "shift followed by widening conversion" warning. */ + tv.tv_sec = 0; - tv.tv_usec = n > 28 ? 100000 : 1 << (n - 12); - select(0, 0, 0, 0, &tv); + tv.tv_usec = usec; + (void)select(0, 0, 0, 0, &tv); # endif } } diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops.h b/src/bdwgc/libatomic_ops/src/atomic_ops.h index 33fe00e08..d7fec6be3 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P. + * Copyright (c) 2008-2018 Ivan Maidanski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -157,7 +158,23 @@ /* The test_and_set primitive returns an AO_TS_VAL_t value. */ /* AO_TS_t is the type of an in-memory test-and-set location. */ -#define AO_TS_INITIALIZER (AO_t)AO_TS_CLEAR +#define AO_TS_INITIALIZER ((AO_TS_t)AO_TS_CLEAR) + +/* Convenient internal macro to test version of GCC. */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define AO_GNUC_PREREQ(major, minor) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((major) << 16) + (minor)) +#else +# define AO_GNUC_PREREQ(major, minor) 0 /* false */ +#endif + +/* Convenient internal macro to test version of Clang. */ +#if defined(__clang__) && defined(__clang_major__) +# define AO_CLANG_PREREQ(major, minor) \ + ((__clang_major__ << 16) + __clang_minor__ >= ((major) << 16) + (minor)) +#else +# define AO_CLANG_PREREQ(major, minor) 0 /* false */ +#endif /* Platform-dependent stuff: */ #if (defined(__GNUC__) || defined(_MSC_VER) || defined(__INTEL_COMPILER) \ @@ -169,13 +186,51 @@ # define AO_INLINE static #endif -#if __GNUC__ >= 3 && !defined(LINT2) +#if AO_GNUC_PREREQ(3, 0) && !defined(LINT2) # define AO_EXPECT_FALSE(expr) __builtin_expect(expr, 0) /* Equivalent to (expr) but predict that usually (expr) == 0. */ #else # define AO_EXPECT_FALSE(expr) (expr) #endif /* !__GNUC__ */ +#if defined(__has_feature) + /* __has_feature() is supported. */ +# if __has_feature(address_sanitizer) +# define AO_ADDRESS_SANITIZER +# endif +# if __has_feature(memory_sanitizer) +# define AO_MEMORY_SANITIZER +# endif +# if __has_feature(thread_sanitizer) +# define AO_THREAD_SANITIZER +# endif +#else +# ifdef __SANITIZE_ADDRESS__ + /* GCC v4.8+ */ +# define AO_ADDRESS_SANITIZER +# endif +#endif /* !__has_feature */ + +#ifndef AO_ATTR_NO_SANITIZE_MEMORY +# ifndef AO_MEMORY_SANITIZER +# define AO_ATTR_NO_SANITIZE_MEMORY /* empty */ +# elif AO_CLANG_PREREQ(3, 8) +# define AO_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) +# else +# define AO_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +# endif +#endif /* !AO_ATTR_NO_SANITIZE_MEMORY */ + +#ifndef AO_ATTR_NO_SANITIZE_THREAD +# ifndef AO_THREAD_SANITIZER +# define AO_ATTR_NO_SANITIZE_THREAD /* empty */ +# elif AO_CLANG_PREREQ(3, 8) +# define AO_ATTR_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread"))) +# else +# define AO_ATTR_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) +# endif +#endif /* !AO_ATTR_NO_SANITIZE_THREAD */ + #if defined(__GNUC__) && !defined(__INTEL_COMPILER) # define AO_compiler_barrier() __asm__ __volatile__("" : : : "memory") #elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \ @@ -203,7 +258,7 @@ # include # define AO_compiler_barrier() _Asm_sched_fence() # else - /* FIXME - We dont know how to do this. This is a guess. */ + /* FIXME - We do not know how to do this. This is a guess. */ /* And probably a bad one. */ static volatile int AO_barrier_dummy; # define AO_compiler_barrier() (void)(AO_barrier_dummy = AO_barrier_dummy) @@ -231,65 +286,56 @@ /* it might require specifying additional options (like -march) */ /* or additional link libraries (if -march is not specified). */ # include "atomic_ops/sysdeps/gcc/x86.h" -# endif /* __i386__ */ -# if defined(__x86_64__) -# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) \ - && !defined(AO_USE_SYNC_CAS_BUILTIN) +# elif defined(__x86_64__) +# if AO_GNUC_PREREQ(4, 2) && !defined(AO_USE_SYNC_CAS_BUILTIN) /* It is safe to use __sync CAS built-in on this architecture. */ # define AO_USE_SYNC_CAS_BUILTIN # endif # include "atomic_ops/sysdeps/gcc/x86.h" -# endif /* __x86_64__ */ -# if defined(__ia64__) +# elif defined(__ia64__) # include "atomic_ops/sysdeps/gcc/ia64.h" # define AO_GENERALIZE_TWICE -# endif /* __ia64__ */ -# if defined(__hppa__) +# elif defined(__hppa__) # include "atomic_ops/sysdeps/gcc/hppa.h" # define AO_CAN_EMUL_CAS -# endif /* __hppa__ */ -# if defined(__alpha__) +# elif defined(__alpha__) # include "atomic_ops/sysdeps/gcc/alpha.h" # define AO_GENERALIZE_TWICE -# endif /* __alpha__ */ -# if defined(__s390__) +# elif defined(__s390__) # include "atomic_ops/sysdeps/gcc/s390.h" -# endif /* __s390__ */ -# if defined(__sparc__) +# elif defined(__sparc__) # include "atomic_ops/sysdeps/gcc/sparc.h" # define AO_CAN_EMUL_CAS -# endif /* __sparc__ */ -# if defined(__m68k__) +# elif defined(__m68k__) # include "atomic_ops/sysdeps/gcc/m68k.h" -# endif /* __m68k__ */ -# if defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) \ - || defined(__powerpc64__) || defined(__ppc64__) +# elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) \ + || defined(__powerpc64__) || defined(__ppc64__) || defined(_ARCH_PPC) # include "atomic_ops/sysdeps/gcc/powerpc.h" -# endif /* __powerpc__ */ -# if defined(__aarch64__) +# elif defined(__aarch64__) # include "atomic_ops/sysdeps/gcc/aarch64.h" # define AO_CAN_EMUL_CAS -# endif /* __aarch64__ */ -# if defined(__arm__) +# elif defined(__arm__) # include "atomic_ops/sysdeps/gcc/arm.h" # define AO_CAN_EMUL_CAS -# endif /* __arm__ */ -# if defined(__cris__) || defined(CRIS) +# elif defined(__cris__) || defined(CRIS) # include "atomic_ops/sysdeps/gcc/cris.h" +# define AO_CAN_EMUL_CAS # define AO_GENERALIZE_TWICE -# endif -# if defined(__mips__) +# elif defined(__mips__) # include "atomic_ops/sysdeps/gcc/mips.h" -# endif /* __mips__ */ -# if defined(__sh__) || defined(SH4) +# elif defined(__sh__) || defined(SH4) # include "atomic_ops/sysdeps/gcc/sh.h" # define AO_CAN_EMUL_CAS -# endif /* __sh__ */ -# if defined(__avr32__) +# elif defined(__avr32__) # include "atomic_ops/sysdeps/gcc/avr32.h" -# endif -# if defined(__hexagon__) +# elif defined(__hexagon__) # include "atomic_ops/sysdeps/gcc/hexagon.h" +# elif defined(__riscv) +# include "atomic_ops/sysdeps/gcc/riscv.h" +# elif defined(__tile__) +# include "atomic_ops/sysdeps/gcc/tile.h" +# else /* __nios2__, etc. */ +# include "atomic_ops/sysdeps/gcc/generic.h" # endif #endif /* __GNUC__ && !AO_USE_PTHREAD_DEFS */ @@ -357,26 +403,28 @@ # define AO_CAN_EMUL_CAS #endif -#if defined(AO_REQUIRE_CAS) && !defined(AO_HAVE_compare_and_swap) \ +#if (defined(AO_REQUIRE_CAS) && !defined(AO_HAVE_compare_and_swap) \ && !defined(AO_HAVE_fetch_compare_and_swap) \ && !defined(AO_HAVE_compare_and_swap_full) \ && !defined(AO_HAVE_fetch_compare_and_swap_full) \ && !defined(AO_HAVE_compare_and_swap_acquire) \ - && !defined(AO_HAVE_fetch_compare_and_swap_acquire) + && !defined(AO_HAVE_fetch_compare_and_swap_acquire)) || defined(CPPCHECK) # if defined(AO_CAN_EMUL_CAS) # include "atomic_ops/sysdeps/emul_cas.h" -# else -# error Cannot implement AO_compare_and_swap_full on this architecture. +# elif !defined(CPPCHECK) +# error Cannot implement AO_compare_and_swap_full on this architecture. # endif #endif /* AO_REQUIRE_CAS && !AO_HAVE_compare_and_swap ... */ /* The most common way to clear a test-and-set location */ /* at the end of a critical section. */ -#if AO_AO_TS_T && !defined(AO_CLEAR) +#if AO_AO_TS_T && !defined(AO_HAVE_CLEAR) # define AO_CLEAR(addr) AO_store_release((AO_TS_t *)(addr), AO_TS_CLEAR) +# define AO_HAVE_CLEAR #endif -#if AO_CHAR_TS_T && !defined(AO_CLEAR) +#if AO_CHAR_TS_T && !defined(AO_HAVE_CLEAR) # define AO_CLEAR(addr) AO_char_store_release((AO_TS_t *)(addr), AO_TS_CLEAR) +# define AO_HAVE_CLEAR #endif /* The generalization section. */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/ao_version.h b/src/bdwgc/libatomic_ops/src/atomic_ops/ao_version.h index 976b6cfa4..97e8ccd02 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/ao_version.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/ao_version.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2003-2004 Hewlett-Packard Development Company, L.P. + * Copyright (c) 2011-2018 Ivan Maidanski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,5 +34,5 @@ /* The version here should match that in configure.ac and README. */ #define AO_VERSION_MAJOR 7 -#define AO_VERSION_MINOR 5 -#define AO_VERSION_MICRO 0 /* 7.5.0 */ +#define AO_VERSION_MINOR 6 +#define AO_VERSION_MICRO 6 /* 7.6.6 */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-arithm.h b/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-arithm.h index e925b10f0..515f52e9e 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-arithm.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-arithm.h @@ -133,6 +133,7 @@ /* corresponding compare_and_swap variants to minimize adding barriers. */ #if defined(AO_HAVE_char_compare_and_swap_full) \ && !defined(AO_HAVE_char_fetch_and_add_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/char AO_char_fetch_and_add_full(volatile unsigned/**/char *addr, unsigned/**/char incr) { @@ -151,6 +152,7 @@ #if defined(AO_HAVE_char_compare_and_swap_acquire) \ && !defined(AO_HAVE_char_fetch_and_add_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/char AO_char_fetch_and_add_acquire(volatile unsigned/**/char *addr, unsigned/**/char incr) { @@ -169,6 +171,7 @@ #if defined(AO_HAVE_char_compare_and_swap_release) \ && !defined(AO_HAVE_char_fetch_and_add_release) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/char AO_char_fetch_and_add_release(volatile unsigned/**/char *addr, unsigned/**/char incr) { @@ -187,6 +190,7 @@ #if defined(AO_HAVE_char_compare_and_swap) \ && !defined(AO_HAVE_char_fetch_and_add) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/char AO_char_fetch_and_add(volatile unsigned/**/char *addr, unsigned/**/char incr) { @@ -600,6 +604,7 @@ /* char_and */ #if defined(AO_HAVE_char_compare_and_swap_full) \ && !defined(AO_HAVE_char_and_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_char_and_full(volatile unsigned/**/char *addr, unsigned/**/char value) { @@ -682,6 +687,7 @@ /* char_or */ #if defined(AO_HAVE_char_compare_and_swap_full) \ && !defined(AO_HAVE_char_or_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_char_or_full(volatile unsigned/**/char *addr, unsigned/**/char value) { @@ -763,6 +769,7 @@ /* char_xor */ #if defined(AO_HAVE_char_compare_and_swap_full) \ && !defined(AO_HAVE_char_xor_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_char_xor_full(volatile unsigned/**/char *addr, unsigned/**/char value) { @@ -978,6 +985,7 @@ /* corresponding compare_and_swap variants to minimize adding barriers. */ #if defined(AO_HAVE_short_compare_and_swap_full) \ && !defined(AO_HAVE_short_fetch_and_add_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/short AO_short_fetch_and_add_full(volatile unsigned/**/short *addr, unsigned/**/short incr) { @@ -996,6 +1004,7 @@ #if defined(AO_HAVE_short_compare_and_swap_acquire) \ && !defined(AO_HAVE_short_fetch_and_add_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/short AO_short_fetch_and_add_acquire(volatile unsigned/**/short *addr, unsigned/**/short incr) { @@ -1014,6 +1023,7 @@ #if defined(AO_HAVE_short_compare_and_swap_release) \ && !defined(AO_HAVE_short_fetch_and_add_release) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/short AO_short_fetch_and_add_release(volatile unsigned/**/short *addr, unsigned/**/short incr) { @@ -1032,6 +1042,7 @@ #if defined(AO_HAVE_short_compare_and_swap) \ && !defined(AO_HAVE_short_fetch_and_add) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/short AO_short_fetch_and_add(volatile unsigned/**/short *addr, unsigned/**/short incr) { @@ -1445,6 +1456,7 @@ /* short_and */ #if defined(AO_HAVE_short_compare_and_swap_full) \ && !defined(AO_HAVE_short_and_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_short_and_full(volatile unsigned/**/short *addr, unsigned/**/short value) { @@ -1527,6 +1539,7 @@ /* short_or */ #if defined(AO_HAVE_short_compare_and_swap_full) \ && !defined(AO_HAVE_short_or_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_short_or_full(volatile unsigned/**/short *addr, unsigned/**/short value) { @@ -1608,6 +1621,7 @@ /* short_xor */ #if defined(AO_HAVE_short_compare_and_swap_full) \ && !defined(AO_HAVE_short_xor_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_short_xor_full(volatile unsigned/**/short *addr, unsigned/**/short value) { @@ -1823,6 +1837,7 @@ /* corresponding compare_and_swap variants to minimize adding barriers. */ #if defined(AO_HAVE_int_compare_and_swap_full) \ && !defined(AO_HAVE_int_fetch_and_add_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned AO_int_fetch_and_add_full(volatile unsigned *addr, unsigned incr) { @@ -1841,6 +1856,7 @@ #if defined(AO_HAVE_int_compare_and_swap_acquire) \ && !defined(AO_HAVE_int_fetch_and_add_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned AO_int_fetch_and_add_acquire(volatile unsigned *addr, unsigned incr) { @@ -1859,6 +1875,7 @@ #if defined(AO_HAVE_int_compare_and_swap_release) \ && !defined(AO_HAVE_int_fetch_and_add_release) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned AO_int_fetch_and_add_release(volatile unsigned *addr, unsigned incr) { @@ -1877,6 +1894,7 @@ #if defined(AO_HAVE_int_compare_and_swap) \ && !defined(AO_HAVE_int_fetch_and_add) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned AO_int_fetch_and_add(volatile unsigned *addr, unsigned incr) { @@ -2290,6 +2308,7 @@ /* int_and */ #if defined(AO_HAVE_int_compare_and_swap_full) \ && !defined(AO_HAVE_int_and_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_int_and_full(volatile unsigned *addr, unsigned value) { @@ -2372,6 +2391,7 @@ /* int_or */ #if defined(AO_HAVE_int_compare_and_swap_full) \ && !defined(AO_HAVE_int_or_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_int_or_full(volatile unsigned *addr, unsigned value) { @@ -2453,6 +2473,7 @@ /* int_xor */ #if defined(AO_HAVE_int_compare_and_swap_full) \ && !defined(AO_HAVE_int_xor_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_int_xor_full(volatile unsigned *addr, unsigned value) { @@ -2668,6 +2689,7 @@ /* corresponding compare_and_swap variants to minimize adding barriers. */ #if defined(AO_HAVE_compare_and_swap_full) \ && !defined(AO_HAVE_fetch_and_add_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_t AO_fetch_and_add_full(volatile AO_t *addr, AO_t incr) { @@ -2686,6 +2708,7 @@ #if defined(AO_HAVE_compare_and_swap_acquire) \ && !defined(AO_HAVE_fetch_and_add_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_t AO_fetch_and_add_acquire(volatile AO_t *addr, AO_t incr) { @@ -2704,6 +2727,7 @@ #if defined(AO_HAVE_compare_and_swap_release) \ && !defined(AO_HAVE_fetch_and_add_release) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_t AO_fetch_and_add_release(volatile AO_t *addr, AO_t incr) { @@ -2722,6 +2746,7 @@ #if defined(AO_HAVE_compare_and_swap) \ && !defined(AO_HAVE_fetch_and_add) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_t AO_fetch_and_add(volatile AO_t *addr, AO_t incr) { @@ -3135,6 +3160,7 @@ /* and */ #if defined(AO_HAVE_compare_and_swap_full) \ && !defined(AO_HAVE_and_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_and_full(volatile AO_t *addr, AO_t value) { @@ -3217,6 +3243,7 @@ /* or */ #if defined(AO_HAVE_compare_and_swap_full) \ && !defined(AO_HAVE_or_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_or_full(volatile AO_t *addr, AO_t value) { @@ -3298,6 +3325,7 @@ /* xor */ #if defined(AO_HAVE_compare_and_swap_full) \ && !defined(AO_HAVE_xor_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_xor_full(volatile AO_t *addr, AO_t value) { diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-arithm.template b/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-arithm.template index 24161a49f..0a21ec234 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-arithm.template +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-arithm.template @@ -133,6 +133,7 @@ /* corresponding compare_and_swap variants to minimize adding barriers. */ #if defined(AO_HAVE_XSIZE_compare_and_swap_full) \ && !defined(AO_HAVE_XSIZE_fetch_and_add_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE XCTYPE AO_XSIZE_fetch_and_add_full(volatile XCTYPE *addr, XCTYPE incr) { @@ -151,6 +152,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap_acquire) \ && !defined(AO_HAVE_XSIZE_fetch_and_add_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE XCTYPE AO_XSIZE_fetch_and_add_acquire(volatile XCTYPE *addr, XCTYPE incr) { @@ -169,6 +171,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap_release) \ && !defined(AO_HAVE_XSIZE_fetch_and_add_release) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE XCTYPE AO_XSIZE_fetch_and_add_release(volatile XCTYPE *addr, XCTYPE incr) { @@ -187,6 +190,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap) \ && !defined(AO_HAVE_XSIZE_fetch_and_add) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE XCTYPE AO_XSIZE_fetch_and_add(volatile XCTYPE *addr, XCTYPE incr) { @@ -600,6 +604,7 @@ /* XSIZE_and */ #if defined(AO_HAVE_XSIZE_compare_and_swap_full) \ && !defined(AO_HAVE_XSIZE_and_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_XSIZE_and_full(volatile XCTYPE *addr, XCTYPE value) { @@ -682,6 +687,7 @@ /* XSIZE_or */ #if defined(AO_HAVE_XSIZE_compare_and_swap_full) \ && !defined(AO_HAVE_XSIZE_or_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_XSIZE_or_full(volatile XCTYPE *addr, XCTYPE value) { @@ -763,6 +769,7 @@ /* XSIZE_xor */ #if defined(AO_HAVE_XSIZE_compare_and_swap_full) \ && !defined(AO_HAVE_XSIZE_xor_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_XSIZE_xor_full(volatile XCTYPE *addr, XCTYPE value) { diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-small.h b/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-small.h index 37d1d219d..d93d0e827 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-small.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-small.h @@ -312,6 +312,7 @@ #if defined(AO_HAVE_char_compare_and_swap_read) \ && !defined(AO_HAVE_char_load_read) # define AO_char_CAS_BASED_LOAD_READ + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/char AO_char_load_read(const volatile unsigned/**/char *addr) { @@ -342,6 +343,7 @@ #if defined(AO_HAVE_char_compare_and_swap_full) \ && !defined(AO_HAVE_char_load_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/char AO_char_load_full(const volatile unsigned/**/char *addr) { @@ -359,6 +361,7 @@ #if defined(AO_HAVE_char_compare_and_swap_acquire) \ && !defined(AO_HAVE_char_load_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/char AO_char_load_acquire(const volatile unsigned/**/char *addr) { @@ -375,6 +378,7 @@ #endif #if defined(AO_HAVE_char_compare_and_swap) && !defined(AO_HAVE_char_load) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/char AO_char_load(const volatile unsigned/**/char *addr) { @@ -447,6 +451,7 @@ #if defined(AO_HAVE_char_compare_and_swap_write) \ && !defined(AO_HAVE_char_store_write) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_char_store_write(volatile unsigned/**/char *addr, unsigned/**/char new_val) { @@ -476,6 +481,7 @@ #endif #if defined(AO_HAVE_char_compare_and_swap) && !defined(AO_HAVE_char_store) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_char_store(volatile unsigned/**/char *addr, unsigned/**/char new_val) { @@ -491,6 +497,7 @@ #if defined(AO_HAVE_char_compare_and_swap_release) \ && !defined(AO_HAVE_char_store_release) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_char_store_release(volatile unsigned/**/char *addr, unsigned/**/char new_val) { @@ -506,6 +513,7 @@ #if defined(AO_HAVE_char_compare_and_swap_full) \ && !defined(AO_HAVE_char_store_full) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_char_store_full(volatile unsigned/**/char *addr, unsigned/**/char new_val) { @@ -832,6 +840,7 @@ #if defined(AO_HAVE_short_compare_and_swap_read) \ && !defined(AO_HAVE_short_load_read) # define AO_short_CAS_BASED_LOAD_READ + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/short AO_short_load_read(const volatile unsigned/**/short *addr) { @@ -862,6 +871,7 @@ #if defined(AO_HAVE_short_compare_and_swap_full) \ && !defined(AO_HAVE_short_load_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/short AO_short_load_full(const volatile unsigned/**/short *addr) { @@ -879,6 +889,7 @@ #if defined(AO_HAVE_short_compare_and_swap_acquire) \ && !defined(AO_HAVE_short_load_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/short AO_short_load_acquire(const volatile unsigned/**/short *addr) { @@ -895,6 +906,7 @@ #endif #if defined(AO_HAVE_short_compare_and_swap) && !defined(AO_HAVE_short_load) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned/**/short AO_short_load(const volatile unsigned/**/short *addr) { @@ -967,6 +979,7 @@ #if defined(AO_HAVE_short_compare_and_swap_write) \ && !defined(AO_HAVE_short_store_write) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_short_store_write(volatile unsigned/**/short *addr, unsigned/**/short new_val) { @@ -996,6 +1009,7 @@ #endif #if defined(AO_HAVE_short_compare_and_swap) && !defined(AO_HAVE_short_store) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_short_store(volatile unsigned/**/short *addr, unsigned/**/short new_val) { @@ -1011,6 +1025,7 @@ #if defined(AO_HAVE_short_compare_and_swap_release) \ && !defined(AO_HAVE_short_store_release) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_short_store_release(volatile unsigned/**/short *addr, unsigned/**/short new_val) { @@ -1026,6 +1041,7 @@ #if defined(AO_HAVE_short_compare_and_swap_full) \ && !defined(AO_HAVE_short_store_full) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_short_store_full(volatile unsigned/**/short *addr, unsigned/**/short new_val) { @@ -1352,6 +1368,7 @@ #if defined(AO_HAVE_int_compare_and_swap_read) \ && !defined(AO_HAVE_int_load_read) # define AO_int_CAS_BASED_LOAD_READ + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned AO_int_load_read(const volatile unsigned *addr) { @@ -1382,6 +1399,7 @@ #if defined(AO_HAVE_int_compare_and_swap_full) \ && !defined(AO_HAVE_int_load_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned AO_int_load_full(const volatile unsigned *addr) { @@ -1399,6 +1417,7 @@ #if defined(AO_HAVE_int_compare_and_swap_acquire) \ && !defined(AO_HAVE_int_load_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned AO_int_load_acquire(const volatile unsigned *addr) { @@ -1415,6 +1434,7 @@ #endif #if defined(AO_HAVE_int_compare_and_swap) && !defined(AO_HAVE_int_load) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE unsigned AO_int_load(const volatile unsigned *addr) { @@ -1487,6 +1507,7 @@ #if defined(AO_HAVE_int_compare_and_swap_write) \ && !defined(AO_HAVE_int_store_write) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_int_store_write(volatile unsigned *addr, unsigned new_val) { @@ -1516,6 +1537,7 @@ #endif #if defined(AO_HAVE_int_compare_and_swap) && !defined(AO_HAVE_int_store) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_int_store(volatile unsigned *addr, unsigned new_val) { @@ -1531,6 +1553,7 @@ #if defined(AO_HAVE_int_compare_and_swap_release) \ && !defined(AO_HAVE_int_store_release) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_int_store_release(volatile unsigned *addr, unsigned new_val) { @@ -1546,6 +1569,7 @@ #if defined(AO_HAVE_int_compare_and_swap_full) \ && !defined(AO_HAVE_int_store_full) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_int_store_full(volatile unsigned *addr, unsigned new_val) { @@ -1872,6 +1896,7 @@ #if defined(AO_HAVE_compare_and_swap_read) \ && !defined(AO_HAVE_load_read) # define AO_CAS_BASED_LOAD_READ + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_t AO_load_read(const volatile AO_t *addr) { @@ -1902,6 +1927,7 @@ #if defined(AO_HAVE_compare_and_swap_full) \ && !defined(AO_HAVE_load_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_t AO_load_full(const volatile AO_t *addr) { @@ -1919,6 +1945,7 @@ #if defined(AO_HAVE_compare_and_swap_acquire) \ && !defined(AO_HAVE_load_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_t AO_load_acquire(const volatile AO_t *addr) { @@ -1935,6 +1962,7 @@ #endif #if defined(AO_HAVE_compare_and_swap) && !defined(AO_HAVE_load) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_t AO_load(const volatile AO_t *addr) { @@ -2007,6 +2035,7 @@ #if defined(AO_HAVE_compare_and_swap_write) \ && !defined(AO_HAVE_store_write) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_store_write(volatile AO_t *addr, AO_t new_val) { @@ -2036,6 +2065,7 @@ #endif #if defined(AO_HAVE_compare_and_swap) && !defined(AO_HAVE_store) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_store(volatile AO_t *addr, AO_t new_val) { @@ -2051,6 +2081,7 @@ #if defined(AO_HAVE_compare_and_swap_release) \ && !defined(AO_HAVE_store_release) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_store_release(volatile AO_t *addr, AO_t new_val) { @@ -2066,6 +2097,7 @@ #if defined(AO_HAVE_compare_and_swap_full) \ && !defined(AO_HAVE_store_full) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_store_full(volatile AO_t *addr, AO_t new_val) { @@ -2392,6 +2424,7 @@ #if defined(AO_HAVE_double_compare_and_swap_read) \ && !defined(AO_HAVE_double_load_read) # define AO_double_CAS_BASED_LOAD_READ + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_double_t AO_double_load_read(const volatile AO_double_t *addr) { @@ -2422,6 +2455,7 @@ #if defined(AO_HAVE_double_compare_and_swap_full) \ && !defined(AO_HAVE_double_load_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_double_t AO_double_load_full(const volatile AO_double_t *addr) { @@ -2439,6 +2473,7 @@ #if defined(AO_HAVE_double_compare_and_swap_acquire) \ && !defined(AO_HAVE_double_load_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_double_t AO_double_load_acquire(const volatile AO_double_t *addr) { @@ -2455,6 +2490,7 @@ #endif #if defined(AO_HAVE_double_compare_and_swap) && !defined(AO_HAVE_double_load) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE AO_double_t AO_double_load(const volatile AO_double_t *addr) { @@ -2527,6 +2563,7 @@ #if defined(AO_HAVE_double_compare_and_swap_write) \ && !defined(AO_HAVE_double_store_write) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_double_store_write(volatile AO_double_t *addr, AO_double_t new_val) { @@ -2556,6 +2593,7 @@ #endif #if defined(AO_HAVE_double_compare_and_swap) && !defined(AO_HAVE_double_store) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_double_store(volatile AO_double_t *addr, AO_double_t new_val) { @@ -2571,6 +2609,7 @@ #if defined(AO_HAVE_double_compare_and_swap_release) \ && !defined(AO_HAVE_double_store_release) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_double_store_release(volatile AO_double_t *addr, AO_double_t new_val) { @@ -2586,6 +2625,7 @@ #if defined(AO_HAVE_double_compare_and_swap_full) \ && !defined(AO_HAVE_double_store_full) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_double_store_full(volatile AO_double_t *addr, AO_double_t new_val) { diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-small.template b/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-small.template index ac916a583..d3490f87b 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-small.template +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/generalize-small.template @@ -312,6 +312,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap_read) \ && !defined(AO_HAVE_XSIZE_load_read) # define AO_XSIZE_CAS_BASED_LOAD_READ + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE XCTYPE AO_XSIZE_load_read(const volatile XCTYPE *addr) { @@ -342,6 +343,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap_full) \ && !defined(AO_HAVE_XSIZE_load_full) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE XCTYPE AO_XSIZE_load_full(const volatile XCTYPE *addr) { @@ -359,6 +361,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap_acquire) \ && !defined(AO_HAVE_XSIZE_load_acquire) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE XCTYPE AO_XSIZE_load_acquire(const volatile XCTYPE *addr) { @@ -375,6 +378,7 @@ #endif #if defined(AO_HAVE_XSIZE_compare_and_swap) && !defined(AO_HAVE_XSIZE_load) + AO_ATTR_NO_SANITIZE_THREAD AO_INLINE XCTYPE AO_XSIZE_load(const volatile XCTYPE *addr) { @@ -447,6 +451,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap_write) \ && !defined(AO_HAVE_XSIZE_store_write) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_XSIZE_store_write(volatile XCTYPE *addr, XCTYPE new_val) { @@ -476,6 +481,7 @@ #endif #if defined(AO_HAVE_XSIZE_compare_and_swap) && !defined(AO_HAVE_XSIZE_store) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_XSIZE_store(volatile XCTYPE *addr, XCTYPE new_val) { @@ -491,6 +497,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap_release) \ && !defined(AO_HAVE_XSIZE_store_release) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_XSIZE_store_release(volatile XCTYPE *addr, XCTYPE new_val) { @@ -506,6 +513,7 @@ #if defined(AO_HAVE_XSIZE_compare_and_swap_full) \ && !defined(AO_HAVE_XSIZE_store_full) + AO_ATTR_NO_SANITIZE_MEMORY AO_ATTR_NO_SANITIZE_THREAD AO_INLINE void AO_XSIZE_store_full(volatile XCTYPE *addr, XCTYPE new_val) { diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/generalize.h b/src/bdwgc/libatomic_ops/src/atomic_ops/generalize.h index 3e6634110..6edeab4a4 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/generalize.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/generalize.h @@ -187,11 +187,12 @@ # define AO_HAVE_nop_full #endif -#if defined(AO_HAVE_nop_acquire) -# error AO_nop_acquire is useless: dont define. +#if defined(AO_HAVE_nop_acquire) && !defined(CPPCHECK) +# error AO_nop_acquire is useless: do not define. #endif -#if defined(AO_HAVE_nop_release) -# error AO_nop_release is useless: dont define. + +#if defined(AO_HAVE_nop_release) && !defined(CPPCHECK) +# error AO_nop_release is useless: do not define. #endif #if defined(AO_HAVE_nop_full) && !defined(AO_HAVE_nop_read) @@ -323,6 +324,40 @@ } # define AO_HAVE_compare_double_and_swap_double # endif +# if defined(AO_HAVE_double_compare_and_swap_acquire) \ + && !defined(AO_HAVE_compare_double_and_swap_double_acquire) + AO_INLINE int + AO_compare_double_and_swap_double_acquire(volatile AO_double_t *addr, + AO_t old_val1, AO_t old_val2, + AO_t new_val1, AO_t new_val2) + { + AO_double_t old_w; + AO_double_t new_w; + old_w.AO_val1 = old_val1; + old_w.AO_val2 = old_val2; + new_w.AO_val1 = new_val1; + new_w.AO_val2 = new_val2; + return AO_double_compare_and_swap_acquire(addr, old_w, new_w); + } +# define AO_HAVE_compare_double_and_swap_double_acquire +# endif +# if defined(AO_HAVE_double_compare_and_swap_release) \ + && !defined(AO_HAVE_compare_double_and_swap_double_release) + AO_INLINE int + AO_compare_double_and_swap_double_release(volatile AO_double_t *addr, + AO_t old_val1, AO_t old_val2, + AO_t new_val1, AO_t new_val2) + { + AO_double_t old_w; + AO_double_t new_w; + old_w.AO_val1 = old_val1; + old_w.AO_val2 = old_val2; + new_w.AO_val1 = new_val1; + new_w.AO_val2 = new_val2; + return AO_double_compare_and_swap_release(addr, old_w, new_w); + } +# define AO_HAVE_compare_double_and_swap_double_release +# endif # if defined(AO_HAVE_double_compare_and_swap_full) \ && !defined(AO_HAVE_compare_double_and_swap_double_full) AO_INLINE int @@ -674,3 +709,19 @@ } # define AO_HAVE_double_compare_and_swap_full #endif + +#ifndef AO_HAVE_double_compare_and_swap_dd_acquire_read + /* Duplicated from generalize-small because double CAS might be */ + /* defined after the include. */ +# ifdef AO_NO_DD_ORDERING +# if defined(AO_HAVE_double_compare_and_swap_acquire_read) +# define AO_double_compare_and_swap_dd_acquire_read(addr, old, new_val) \ + AO_double_compare_and_swap_acquire_read(addr, old, new_val) +# define AO_HAVE_double_compare_and_swap_dd_acquire_read +# endif +# elif defined(AO_HAVE_double_compare_and_swap) +# define AO_double_compare_and_swap_dd_acquire_read(addr, old, new_val) \ + AO_double_compare_and_swap(addr, old, new_val) +# define AO_HAVE_double_compare_and_swap_dd_acquire_read +# endif /* !AO_NO_DD_ORDERING */ +#endif diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/armcc/arm_v6.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/armcc/arm_v6.h index 9376e5bf8..03aa1d607 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/armcc/arm_v6.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/armcc/arm_v6.h @@ -23,7 +23,9 @@ #include "../test_and_set_t_is_ao_t.h" /* Probably suboptimal */ #if __TARGET_ARCH_ARM < 6 -Dont use with ARM instruction sets lower than v6 +# if !defined(CPPCHECK) +# error Do not use with ARM instruction sets lower than v6 +# endif #else #define AO_ACCESS_CHECK_ALIGNED diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/emul_cas.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/emul_cas.h index 2a592bc7d..e52f75ad7 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/emul_cas.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/emul_cas.h @@ -43,6 +43,10 @@ # include "standard_ao_double_t.h" #endif +#ifdef __cplusplus + extern "C" { +#endif + AO_t AO_fetch_compare_and_swap_emulation(volatile AO_t *addr, AO_t old_val, AO_t new_val); @@ -76,3 +80,7 @@ void AO_store_full_emulation(volatile AO_t *addr, AO_t val); #undef AO_HAVE_store_full #define AO_store_full(addr, val) AO_store_full_emulation(addr, val) #define AO_HAVE_store_full + +#ifdef __cplusplus + } /* extern "C" */ +#endif diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/aarch64.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/aarch64.h index b7f2ef057..62b61aa6d 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/aarch64.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/aarch64.h @@ -2,7 +2,7 @@ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. - * + * Copyright (c) 2013-2017 Ivan Maidanski * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -15,94 +15,106 @@ * */ -#include "../test_and_set_t_is_ao_t.h" - -#include "../standard_ao_double_t.h" - -#ifndef AO_UNIPROCESSOR +/* As of clang-5.0 (and gcc-5.4), __atomic_thread_fence is always */ +/* translated to DMB (which is inefficient for AO_nop_write). */ +/* TODO: Update it for newer Clang and GCC releases. */ +#if !defined(AO_PREFER_BUILTIN_ATOMICS) && !defined(AO_THREAD_SANITIZER) \ + && !defined(AO_UNIPROCESSOR) AO_INLINE void AO_nop_write(void) { - /* TODO: Use C++11 primitive. */ __asm__ __volatile__("dmb ishst" : : : "memory"); } # define AO_HAVE_nop_write #endif -/* TODO: Adjust version check on fixing double-wide AO support in GCC. */ -#if __GNUC__ >= 4 +/* There were some bugs in the older clang releases (related to */ +/* optimization of functions dealing with __int128 values, supposedly), */ +/* so even asm-based implementation did not work correctly. */ +#if !defined(__clang__) || AO_CLANG_PREREQ(3, 9) - AO_INLINE AO_double_t - AO_double_load(const volatile AO_double_t *addr) - { - AO_double_t result; - int status; +# include "../standard_ao_double_t.h" - /* Note that STXP cannot be discarded because LD[A]XP is not */ - /* single-copy atomic (unlike LDREXD for 32-bit ARM). */ - do { - __asm__ __volatile__("//AO_double_load\n" - " ldxp %0, %1, %3\n" - " stxp %w2, %0, %1, %3" - : "=&r" (result.AO_val1), "=&r" (result.AO_val2), "=&r" (status) - : "Q" (*addr)); - } while (AO_EXPECT_FALSE(status)); - return result; - } -# define AO_HAVE_double_load +/* As of gcc-5.4, all built-in load/store and CAS atomics for double */ +/* word require -latomic, are not lock-free and cause test_stack */ +/* failure, so the asm-based implementation is used for now. */ +/* TODO: Update it for newer GCC releases. */ +#if !defined(__clang__) || defined(AO_AARCH64_ASM_LOAD_STORE_CAS) - AO_INLINE AO_double_t - AO_double_load_acquire(const volatile AO_double_t *addr) - { - AO_double_t result; - int status; +# ifndef AO_PREFER_GENERALIZED + AO_INLINE AO_double_t + AO_double_load(const volatile AO_double_t *addr) + { + AO_double_t result; + int status; - do { - __asm__ __volatile__("//AO_double_load_acquire\n" - " ldaxp %0, %1, %3\n" - " stxp %w2, %0, %1, %3" - : "=&r" (result.AO_val1), "=&r" (result.AO_val2), "=&r" (status) - : "Q" (*addr)); - } while (AO_EXPECT_FALSE(status)); - return result; - } -# define AO_HAVE_double_load_acquire + /* Note that STXP cannot be discarded because LD[A]XP is not */ + /* single-copy atomic (unlike LDREXD for 32-bit ARM). */ + do { + __asm__ __volatile__("//AO_double_load\n" + " ldxp %0, %1, %3\n" + " stxp %w2, %0, %1, %3" + : "=&r" (result.AO_val1), "=&r" (result.AO_val2), "=&r" (status) + : "Q" (*addr)); + } while (AO_EXPECT_FALSE(status)); + return result; + } +# define AO_HAVE_double_load - AO_INLINE void - AO_double_store(volatile AO_double_t *addr, AO_double_t value) - { - AO_double_t old_val; - int status; + AO_INLINE AO_double_t + AO_double_load_acquire(const volatile AO_double_t *addr) + { + AO_double_t result; + int status; - do { - __asm__ __volatile__("//AO_double_store\n" - " ldxp %0, %1, %3\n" - " stxp %w2, %4, %5, %3" - : "=&r" (old_val.AO_val1), "=&r" (old_val.AO_val2), "=&r" (status), - "=Q" (*addr) - : "r" (value.AO_val1), "r" (value.AO_val2)); - /* Compared to the arm.h implementation, the 'cc' (flags) are not */ - /* clobbered because A64 has no concept of conditional execution. */ - } while (AO_EXPECT_FALSE(status)); - } -# define AO_HAVE_double_store + do { + __asm__ __volatile__("//AO_double_load_acquire\n" + " ldaxp %0, %1, %3\n" + " stxp %w2, %0, %1, %3" + : "=&r" (result.AO_val1), "=&r" (result.AO_val2), "=&r" (status) + : "Q" (*addr)); + } while (AO_EXPECT_FALSE(status)); + return result; + } +# define AO_HAVE_double_load_acquire - AO_INLINE void - AO_double_store_release(volatile AO_double_t *addr, AO_double_t value) - { - AO_double_t old_val; - int status; + AO_INLINE void + AO_double_store(volatile AO_double_t *addr, AO_double_t value) + { + AO_double_t old_val; + int status; - do { - __asm__ __volatile__("//AO_double_store_release\n" - " ldxp %0, %1, %3\n" - " stlxp %w2, %4, %5, %3" - : "=&r" (old_val.AO_val1), "=&r" (old_val.AO_val2), "=&r" (status), - "=Q" (*addr) - : "r" (value.AO_val1), "r" (value.AO_val2)); - } while (AO_EXPECT_FALSE(status)); - } -# define AO_HAVE_double_store_release + do { + __asm__ __volatile__("//AO_double_store\n" + " ldxp %0, %1, %3\n" + " stxp %w2, %4, %5, %3" + : "=&r" (old_val.AO_val1), "=&r" (old_val.AO_val2), "=&r" (status), + "=Q" (*addr) + : "r" (value.AO_val1), "r" (value.AO_val2)); + /* Compared to the arm.h implementation, the 'cc' (flags) are */ + /* not clobbered because A64 has no concept of conditional */ + /* execution. */ + } while (AO_EXPECT_FALSE(status)); + } +# define AO_HAVE_double_store + + AO_INLINE void + AO_double_store_release(volatile AO_double_t *addr, AO_double_t value) + { + AO_double_t old_val; + int status; + + do { + __asm__ __volatile__("//AO_double_store_release\n" + " ldxp %0, %1, %3\n" + " stlxp %w2, %4, %5, %3" + : "=&r" (old_val.AO_val1), "=&r" (old_val.AO_val2), "=&r" (status), + "=Q" (*addr) + : "r" (value.AO_val1), "r" (value.AO_val2)); + } while (AO_EXPECT_FALSE(status)); + } +# define AO_HAVE_double_store_release +# endif /* !AO_PREFER_GENERALIZED */ AO_INLINE int AO_double_compare_and_swap(volatile AO_double_t *addr, @@ -195,6 +207,21 @@ return !result; } # define AO_HAVE_double_compare_and_swap_full -#endif /* __GNUC__ >= 4 */ + +#endif /* !__clang__ || AO_AARCH64_ASM_LOAD_STORE_CAS */ + +/* As of clang-5.0 and gcc-5.4, __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 */ +/* macro is still missing (while the double-word CAS is available). */ +# define AO_GCC_HAVE_double_SYNC_CAS + +#endif /* !__clang__ || AO_CLANG_PREREQ(3, 9) */ + +#if (defined(__clang__) && !AO_CLANG_PREREQ(3, 8)) || defined(__APPLE_CC__) + /* __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros are missing. */ +# define AO_GCC_FORCE_HAVE_CAS +#endif #include "generic.h" + +#undef AO_GCC_FORCE_HAVE_CAS +#undef AO_GCC_HAVE_double_SYNC_CAS diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/arm.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/arm.h index 3d841e96f..b99a1cad5 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/arm.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/arm.h @@ -2,7 +2,7 @@ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. - * + * Copyright (c) 2008-2017 Ivan Maidanski * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -15,7 +15,20 @@ * */ -#include "../test_and_set_t_is_ao_t.h" /* Probably suboptimal */ +#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 5)) \ + && !defined(AO_DISABLE_GCC_ATOMICS) + /* Probably, it could be enabled even for earlier gcc/clang versions. */ +# define AO_GCC_ATOMIC_TEST_AND_SET +#endif + +#ifdef __native_client__ + /* Mask instruction should immediately precede access instruction. */ +# define AO_MASK_PTR(reg) " bical " reg ", " reg ", #0xc0000000\n" +# define AO_BR_ALIGN " .align 4\n" +#else +# define AO_MASK_PTR(reg) /* empty */ +# define AO_BR_ALIGN /* empty */ +#endif #if defined(__thumb__) && !defined(__thumb2__) /* Thumb One mode does not have ARM "mcr", "swp" and some load/store */ @@ -26,11 +39,13 @@ " bx r3\n" \ " .align\n" \ " .arm\n" \ + AO_BR_ALIGN \ "4:\n" # define AO_THUMB_RESTORE_MODE \ " adr r3, 5f + 1\n" \ " bx r3\n" \ " .thumb\n" \ + AO_BR_ALIGN \ "5:\n" # define AO_THUMB_SWITCH_CLOBBERS "r3", #else @@ -58,15 +73,15 @@ # if !defined(__ARM_ARCH_6__) && !defined(__ARM_ARCH_6J__) \ && !defined(__ARM_ARCH_6T2__) && !defined(__ARM_ARCH_6Z__) \ && !defined(__ARM_ARCH_6ZT2__) -# if !defined(__ARM_ARCH_6K__) && !defined(__ARM_ARCH_6ZK__) +# if !defined(__ARM_ARCH_6K__) && !defined(__ARM_ARCH_6KZ__) \ + && !defined(__ARM_ARCH_6ZK__) /* DMB is present in ARMv6M and ARMv7+. */ # define AO_ARM_HAVE_DMB # endif # if (!defined(__thumb__) \ || (defined(__thumb2__) && !defined(__ARM_ARCH_7__) \ && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__))) \ - && (!defined(__clang__) || (__clang_major__ > 3) \ - || (__clang_major__ == 3 && __clang_minor__ >= 3)) + && (!defined(__clang__) || AO_CLANG_PREREQ(3, 3)) /* LDREXD/STREXD present in ARMv6K/M+ (see gas/config/tc-arm.c). */ /* In the Thumb mode, this works only starting from ARMv7 (except */ /* for the base and 'M' models). Clang3.2 (and earlier) does not */ @@ -84,6 +99,29 @@ /* Also, SWP is obsoleted for ARMv8+. */ #endif /* !__thumb2__ */ +#if !defined(AO_UNIPROCESSOR) && defined(AO_ARM_HAVE_DMB) \ + && !defined(AO_PREFER_BUILTIN_ATOMICS) + AO_INLINE void + AO_nop_write(void) + { + /* AO_THUMB_GO_ARM is empty. */ + /* This will target the system domain and thus be overly */ + /* conservative as the CPUs (even in case of big.LITTLE SoC) will */ + /* occupy the inner shareable domain. */ + /* The plain variant (dmb st) is theoretically slower, and should */ + /* not be needed. That said, with limited experimentation, a CPU */ + /* implementation for which it actually matters has not been found */ + /* yet, though they should already exist. */ + /* Anyway, note that the "st" and "ishst" barriers are actually */ + /* quite weak and, as the libatomic_ops documentation states, */ + /* usually not what you really want. */ + __asm__ __volatile__("dmb ishst" : : : "memory"); + } +# define AO_HAVE_nop_write +#endif /* AO_ARM_HAVE_DMB */ + +#ifndef AO_GCC_ATOMIC_TEST_AND_SET + #ifdef AO_UNIPROCESSOR /* If only a single processor (core) is used, AO_UNIPROCESSOR could */ /* be defined by the client to avoid unnecessary memory barrier. */ @@ -107,23 +145,6 @@ } # define AO_HAVE_nop_full - AO_INLINE void - AO_nop_write(void) - { - /* AO_THUMB_GO_ARM is empty. */ - /* This will target the system domain and thus be overly */ - /* conservative as the CPUs will occupy the inner shareable domain. */ - /* The plain variant (dmb st) is theoretically slower, and should */ - /* not be needed. That said, with limited experimentation, a CPU */ - /* implementation for which it actually matters has not been found */ - /* yet, though they should already exist. */ - /* Anyway, note that the "st" and "ishst" barriers are actually */ - /* quite weak and, as the libatomic_ops documentation states, */ - /* usually not what you really want. */ - __asm__ __volatile__("dmb ishst" : : : "memory"); - } -# define AO_HAVE_nop_write - #elif defined(AO_ARM_HAVE_LDREX) /* ARMv6 is the first architecture providing support for a simple */ /* LL/SC. A data memory barrier must be raised via CP15 command. */ @@ -148,14 +169,9 @@ /* AO_nop_full() is emulated using AO_test_and_set_full(). */ #endif /* !AO_UNIPROCESSOR && !AO_ARM_HAVE_LDREX */ -#ifdef AO_ARM_HAVE_LDREX +#endif /* !AO_GCC_ATOMIC_TEST_AND_SET */ - /* AO_t/char/short/int load is simple reading. */ - /* Unaligned accesses are not guaranteed to be atomic. */ -# define AO_ACCESS_CHECK_ALIGNED -# define AO_ACCESS_short_CHECK_ALIGNED -# define AO_ACCESS_int_CHECK_ALIGNED -# include "../all_atomic_only_load.h" +#ifdef AO_ARM_HAVE_LDREX /* "ARM Architecture Reference Manual" (chapter A3.5.3) says that the */ /* single-copy atomic processor accesses are all byte accesses, all */ @@ -173,13 +189,28 @@ /* arch/arm/kernel/entry-header.S of Linux. Nonetheless, there is */ /* a doubt this was properly implemented in some ancient OS releases. */ # ifdef AO_BROKEN_TASKSWITCH_CLREX + +# define AO_SKIPATOMIC_store +# define AO_SKIPATOMIC_store_release +# define AO_SKIPATOMIC_char_store +# define AO_SKIPATOMIC_char_store_release +# define AO_SKIPATOMIC_short_store +# define AO_SKIPATOMIC_short_store_release +# define AO_SKIPATOMIC_int_store +# define AO_SKIPATOMIC_int_store_release + +# ifndef AO_PREFER_BUILTIN_ATOMICS + AO_INLINE void AO_store(volatile AO_t *addr, AO_t value) { int flag; __asm__ __volatile__("@AO_store\n" AO_THUMB_GO_ARM - "1: ldrex %0, [%2]\n" + AO_BR_ALIGN + "1: " AO_MASK_PTR("%2") + " ldrex %0, [%2]\n" + AO_MASK_PTR("%2") " strex %0, %3, [%2]\n" " teq %0, #0\n" " bne 1b\n" @@ -198,7 +229,10 @@ __asm__ __volatile__("@AO_char_store\n" AO_THUMB_GO_ARM - "1: ldrexb %0, [%2]\n" + AO_BR_ALIGN + "1: " AO_MASK_PTR("%2") + " ldrexb %0, [%2]\n" + AO_MASK_PTR("%2") " strexb %0, %3, [%2]\n" " teq %0, #0\n" " bne 1b\n" @@ -216,7 +250,10 @@ __asm__ __volatile__("@AO_short_store\n" AO_THUMB_GO_ARM - "1: ldrexh %0, [%2]\n" + AO_BR_ALIGN + "1: " AO_MASK_PTR("%2") + " ldrexh %0, [%2]\n" + AO_MASK_PTR("%2") " strexh %0, %3, [%2]\n" " teq %0, #0\n" " bne 1b\n" @@ -228,11 +265,28 @@ # define AO_HAVE_short_store # endif /* AO_ARM_HAVE_LDREXBH */ -# else +# endif /* !AO_PREFER_BUILTIN_ATOMICS */ + +# elif !defined(AO_GCC_ATOMIC_TEST_AND_SET) # include "../loadstore/atomic_store.h" /* AO_int_store is defined in ao_t_is_int.h. */ # endif /* !AO_BROKEN_TASKSWITCH_CLREX */ +#endif /* AO_ARM_HAVE_LDREX */ + +#ifndef AO_GCC_ATOMIC_TEST_AND_SET + +# include "../test_and_set_t_is_ao_t.h" /* Probably suboptimal */ + +#ifdef AO_ARM_HAVE_LDREX + + /* AO_t/char/short/int load is simple reading. */ + /* Unaligned accesses are not guaranteed to be atomic. */ +# define AO_ACCESS_CHECK_ALIGNED +# define AO_ACCESS_short_CHECK_ALIGNED +# define AO_ACCESS_int_CHECK_ALIGNED +# include "../all_atomic_only_load.h" + # ifndef AO_HAVE_char_store # include "../loadstore/char_atomic_store.h" # include "../loadstore/short_atomic_store.h" @@ -264,7 +318,10 @@ __asm__ __volatile__("@AO_test_and_set\n" AO_THUMB_GO_ARM - "1: ldrex %0, [%3]\n" + AO_BR_ALIGN + "1: " AO_MASK_PTR("%3") + " ldrex %0, [%3]\n" + AO_MASK_PTR("%3") " strex %1, %4, [%3]\n" " teq %1, #0\n" " bne 1b\n" @@ -285,8 +342,11 @@ AO_fetch_and_add(volatile AO_t *p, AO_t incr) __asm__ __volatile__("@AO_fetch_and_add\n" AO_THUMB_GO_ARM - "1: ldrex %0, [%5]\n" /* get original */ + AO_BR_ALIGN + "1: " AO_MASK_PTR("%5") + " ldrex %0, [%5]\n" /* get original */ " add %2, %0, %4\n" /* sum up in incr */ + AO_MASK_PTR("%5") " strex %1, %2, [%5]\n" /* store them */ " teq %1, #0\n" " bne 1b\n" @@ -306,8 +366,11 @@ AO_fetch_and_add1(volatile AO_t *p) __asm__ __volatile__("@AO_fetch_and_add1\n" AO_THUMB_GO_ARM - "1: ldrex %0, [%4]\n" /* get original */ + AO_BR_ALIGN + "1: " AO_MASK_PTR("%4") + " ldrex %0, [%4]\n" /* get original */ " add %1, %0, #1\n" /* increment */ + AO_MASK_PTR("%4") " strex %2, %1, [%4]\n" /* store them */ " teq %2, #0\n" " bne 1b\n" @@ -327,8 +390,11 @@ AO_fetch_and_sub1(volatile AO_t *p) __asm__ __volatile__("@AO_fetch_and_sub1\n" AO_THUMB_GO_ARM - "1: ldrex %0, [%4]\n" /* get original */ + AO_BR_ALIGN + "1: " AO_MASK_PTR("%4") + " ldrex %0, [%4]\n" /* get original */ " sub %1, %0, #1\n" /* decrement */ + AO_MASK_PTR("%4") " strex %2, %1, [%4]\n" /* store them */ " teq %2, #0\n" " bne 1b\n" @@ -347,8 +413,11 @@ AO_and(volatile AO_t *p, AO_t value) __asm__ __volatile__("@AO_and\n" AO_THUMB_GO_ARM - "1: ldrex %0, [%4]\n" + AO_BR_ALIGN + "1: " AO_MASK_PTR("%4") + " ldrex %0, [%4]\n" " and %1, %0, %3\n" + AO_MASK_PTR("%4") " strex %0, %1, [%4]\n" " teq %0, #0\n" " bne 1b\n" @@ -366,8 +435,11 @@ AO_or(volatile AO_t *p, AO_t value) __asm__ __volatile__("@AO_or\n" AO_THUMB_GO_ARM - "1: ldrex %0, [%4]\n" + AO_BR_ALIGN + "1: " AO_MASK_PTR("%4") + " ldrex %0, [%4]\n" " orr %1, %0, %3\n" + AO_MASK_PTR("%4") " strex %0, %1, [%4]\n" " teq %0, #0\n" " bne 1b\n" @@ -385,8 +457,11 @@ AO_xor(volatile AO_t *p, AO_t value) __asm__ __volatile__("@AO_xor\n" AO_THUMB_GO_ARM - "1: ldrex %0, [%4]\n" + AO_BR_ALIGN + "1: " AO_MASK_PTR("%4") + " ldrex %0, [%4]\n" " eor %1, %0, %3\n" + AO_MASK_PTR("%4") " strex %0, %1, [%4]\n" " teq %0, #0\n" " bne 1b\n" @@ -407,8 +482,11 @@ AO_xor(volatile AO_t *p, AO_t value) __asm__ __volatile__("@AO_char_fetch_and_add\n" AO_THUMB_GO_ARM - "1: ldrexb %0, [%5]\n" + AO_BR_ALIGN + "1: " AO_MASK_PTR("%5") + " ldrexb %0, [%5]\n" " add %2, %0, %4\n" + AO_MASK_PTR("%5") " strexb %1, %2, [%5]\n" " teq %1, #0\n" " bne 1b\n" @@ -428,8 +506,11 @@ AO_xor(volatile AO_t *p, AO_t value) __asm__ __volatile__("@AO_short_fetch_and_add\n" AO_THUMB_GO_ARM - "1: ldrexh %0, [%5]\n" + AO_BR_ALIGN + "1: " AO_MASK_PTR("%5") + " ldrexh %0, [%5]\n" " add %2, %0, %4\n" + AO_MASK_PTR("%5") " strexh %1, %2, [%5]\n" " teq %1, #0\n" " bne 1b\n" @@ -451,9 +532,12 @@ AO_xor(volatile AO_t *p, AO_t value) __asm__ __volatile__("@AO_compare_and_swap\n" AO_THUMB_GO_ARM + AO_BR_ALIGN "1: mov %0, #2\n" /* store a flag */ + AO_MASK_PTR("%3") " ldrex %1, [%3]\n" /* get original */ " teq %1, %4\n" /* see if match */ + AO_MASK_PTR("%3") # ifdef __thumb2__ /* TODO: Eliminate warning: it blocks containing wide Thumb */ /* instructions are deprecated in ARMv8. */ @@ -466,7 +550,7 @@ AO_xor(volatile AO_t *p, AO_t value) : "=&r"(result), "=&r"(tmp), "+m"(*addr) : "r"(addr), "r"(old_val), "r"(new_val) : AO_THUMB_SWITCH_CLOBBERS "cc"); - return !(result&2); /* if succeded, return 1, else 0 */ + return !(result&2); /* if succeeded then return 1 else 0 */ } # define AO_HAVE_compare_and_swap #endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ @@ -479,9 +563,12 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) __asm__ __volatile__("@AO_fetch_compare_and_swap\n" AO_THUMB_GO_ARM + AO_BR_ALIGN "1: mov %0, #2\n" /* store a flag */ + AO_MASK_PTR("%3") " ldrex %1, [%3]\n" /* get original */ " teq %1, %4\n" /* see if match */ + AO_MASK_PTR("%3") # ifdef __thumb2__ " it eq\n" # endif @@ -512,6 +599,7 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) /* AO_THUMB_GO_ARM is empty. */ __asm__ __volatile__("@AO_double_load\n" + AO_MASK_PTR("%1") " ldrexd %0, %H0, [%1]" : "=&r" (result.AO_whole) : "r" (addr) @@ -529,7 +617,9 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) do { /* AO_THUMB_GO_ARM is empty. */ __asm__ __volatile__("@AO_double_store\n" + AO_MASK_PTR("%3") " ldrexd %0, %H0, [%3]\n" + AO_MASK_PTR("%3") " strexd %1, %4, %H4, [%3]" : "=&r" (old_val.AO_whole), "=&r" (status), "+m" (*addr) : "r" (addr), "r" (new_val.AO_whole) @@ -548,6 +638,7 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) do { /* AO_THUMB_GO_ARM is empty. */ __asm__ __volatile__("@AO_double_compare_and_swap\n" + AO_MASK_PTR("%1") " ldrexd %0, %H0, [%1]\n" /* get original to r1 & r2 */ : "=&r"(tmp) : "r"(addr) @@ -555,12 +646,13 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) if (tmp != old_val.AO_whole) break; __asm__ __volatile__( + AO_MASK_PTR("%2") " strexd %0, %3, %H3, [%2]\n" /* store new one if matched */ : "=&r"(result), "+m"(*addr) : "r" (addr), "r" (new_val.AO_whole) : "cc"); } while (AO_EXPECT_FALSE(result)); - return !result; /* if succeded, return 1 else 0 */ + return !result; /* if succeeded then return 1 else 0 */ } # define AO_HAVE_double_compare_and_swap #endif /* AO_ARM_HAVE_LDREXD */ @@ -595,6 +687,7 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) __asm__ __volatile__("@AO_test_and_set_full\n" AO_THUMB_GO_ARM + AO_MASK_PTR("%3") " swp %0, %2, [%3]\n" /* Ignore GCC "SWP is deprecated for this architecture" */ /* warning here (for ARMv6+). */ @@ -608,3 +701,37 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) #endif /* !AO_HAVE_test_and_set[_full] && AO_ARM_HAVE_SWP */ #define AO_T_IS_INT + +#else /* AO_GCC_ATOMIC_TEST_AND_SET */ + +# if defined(__clang__) && !defined(AO_ARM_HAVE_LDREX) + /* As of clang-3.8, it cannot compile __atomic_and/or/xor_fetch */ + /* library calls yet for pre ARMv6. */ +# define AO_SKIPATOMIC_ANY_and_ANY +# define AO_SKIPATOMIC_ANY_or_ANY +# define AO_SKIPATOMIC_ANY_xor_ANY +# endif + +# ifdef AO_ARM_HAVE_LDREXD +# include "../standard_ao_double_t.h" +# endif +# include "generic.h" + +#endif /* AO_GCC_ATOMIC_TEST_AND_SET */ + +#undef AO_BR_ALIGN +#undef AO_MASK_PTR +#undef AO_SKIPATOMIC_ANY_and_ANY +#undef AO_SKIPATOMIC_ANY_or_ANY +#undef AO_SKIPATOMIC_ANY_xor_ANY +#undef AO_SKIPATOMIC_char_store +#undef AO_SKIPATOMIC_char_store_release +#undef AO_SKIPATOMIC_int_store +#undef AO_SKIPATOMIC_int_store_release +#undef AO_SKIPATOMIC_short_store +#undef AO_SKIPATOMIC_short_store_release +#undef AO_SKIPATOMIC_store +#undef AO_SKIPATOMIC_store_release +#undef AO_THUMB_GO_ARM +#undef AO_THUMB_RESTORE_MODE +#undef AO_THUMB_SWITCH_CLOBBERS diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/cris.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/cris.h index be58ddc66..f31c21eb2 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/cris.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/cris.h @@ -38,7 +38,7 @@ * http://developer.axis.com/doc/hardware/etrax100lx/prog_man/ * 1_architectural_description.pdf * - * Presumably many other primitives (notably CAS, including the double- + * TODO: Presumably many other primitives (notably CAS, including the double- * width versions) could be implemented in this manner, if someone got * around to it. */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-arithm.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-arithm.h index 65e7767bd..f7f38785a 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-arithm.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-arithm.h @@ -22,26 +22,32 @@ AO_char_fetch_and_add(volatile unsigned/**/char *addr, unsigned/**/char incr) } #define AO_HAVE_char_fetch_and_add -AO_INLINE void -AO_char_and(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_char_and +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_char_and(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_char_and +#endif -AO_INLINE void -AO_char_or(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_char_or +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_char_or(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_char_or +#endif -AO_INLINE void -AO_char_xor(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_char_xor +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_char_xor(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_char_xor +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -66,26 +72,32 @@ AO_short_fetch_and_add(volatile unsigned/**/short *addr, unsigned/**/short incr) } #define AO_HAVE_short_fetch_and_add -AO_INLINE void -AO_short_and(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_short_and +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_short_and(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_short_and +#endif -AO_INLINE void -AO_short_or(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_short_or +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_short_or(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_short_or +#endif -AO_INLINE void -AO_short_xor(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_short_xor +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_short_xor(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_short_xor +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -110,26 +122,32 @@ AO_int_fetch_and_add(volatile unsigned *addr, unsigned incr) } #define AO_HAVE_int_fetch_and_add -AO_INLINE void -AO_int_and(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_int_and +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_int_and(volatile unsigned *addr, unsigned value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_int_and +#endif -AO_INLINE void -AO_int_or(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_int_or +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_int_or(volatile unsigned *addr, unsigned value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_int_or +#endif -AO_INLINE void -AO_int_xor(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_int_xor +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_int_xor(volatile unsigned *addr, unsigned value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_int_xor +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -154,26 +172,32 @@ AO_fetch_and_add(volatile AO_t *addr, AO_t incr) } #define AO_HAVE_fetch_and_add -AO_INLINE void -AO_and(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_and +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_and(volatile AO_t *addr, AO_t value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_and +#endif -AO_INLINE void -AO_or(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_or +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_or(volatile AO_t *addr, AO_t value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_or +#endif -AO_INLINE void -AO_xor(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_xor +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_xor(volatile AO_t *addr, AO_t value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELAXED); + } +# define AO_HAVE_xor +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -198,26 +222,32 @@ AO_char_fetch_and_add_acquire(volatile unsigned/**/char *addr, unsigned/**/char } #define AO_HAVE_char_fetch_and_add_acquire -AO_INLINE void -AO_char_and_acquire(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_char_and_acquire +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_char_and_acquire(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_char_and_acquire +#endif -AO_INLINE void -AO_char_or_acquire(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_char_or_acquire +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_char_or_acquire(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_char_or_acquire +#endif -AO_INLINE void -AO_char_xor_acquire(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_char_xor_acquire +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_char_xor_acquire(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_char_xor_acquire +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -242,26 +272,32 @@ AO_short_fetch_and_add_acquire(volatile unsigned/**/short *addr, unsigned/**/sho } #define AO_HAVE_short_fetch_and_add_acquire -AO_INLINE void -AO_short_and_acquire(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_short_and_acquire +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_short_and_acquire(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_short_and_acquire +#endif -AO_INLINE void -AO_short_or_acquire(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_short_or_acquire +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_short_or_acquire(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_short_or_acquire +#endif -AO_INLINE void -AO_short_xor_acquire(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_short_xor_acquire +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_short_xor_acquire(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_short_xor_acquire +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -286,26 +322,32 @@ AO_int_fetch_and_add_acquire(volatile unsigned *addr, unsigned incr) } #define AO_HAVE_int_fetch_and_add_acquire -AO_INLINE void -AO_int_and_acquire(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_int_and_acquire +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_int_and_acquire(volatile unsigned *addr, unsigned value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_int_and_acquire +#endif -AO_INLINE void -AO_int_or_acquire(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_int_or_acquire +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_int_or_acquire(volatile unsigned *addr, unsigned value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_int_or_acquire +#endif -AO_INLINE void -AO_int_xor_acquire(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_int_xor_acquire +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_int_xor_acquire(volatile unsigned *addr, unsigned value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_int_xor_acquire +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -330,26 +372,32 @@ AO_fetch_and_add_acquire(volatile AO_t *addr, AO_t incr) } #define AO_HAVE_fetch_and_add_acquire -AO_INLINE void -AO_and_acquire(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_and_acquire +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_and_acquire(volatile AO_t *addr, AO_t value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_and_acquire +#endif -AO_INLINE void -AO_or_acquire(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_or_acquire +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_or_acquire(volatile AO_t *addr, AO_t value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_or_acquire +#endif -AO_INLINE void -AO_xor_acquire(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE); -} -#define AO_HAVE_xor_acquire +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_xor_acquire(volatile AO_t *addr, AO_t value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_xor_acquire +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -374,26 +422,32 @@ AO_char_fetch_and_add_release(volatile unsigned/**/char *addr, unsigned/**/char } #define AO_HAVE_char_fetch_and_add_release -AO_INLINE void -AO_char_and_release(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_char_and_release +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_char_and_release(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_char_and_release +#endif -AO_INLINE void -AO_char_or_release(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_char_or_release +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_char_or_release(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_char_or_release +#endif -AO_INLINE void -AO_char_xor_release(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_char_xor_release +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_char_xor_release(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_char_xor_release +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -418,26 +472,32 @@ AO_short_fetch_and_add_release(volatile unsigned/**/short *addr, unsigned/**/sho } #define AO_HAVE_short_fetch_and_add_release -AO_INLINE void -AO_short_and_release(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_short_and_release +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_short_and_release(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_short_and_release +#endif -AO_INLINE void -AO_short_or_release(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_short_or_release +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_short_or_release(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_short_or_release +#endif -AO_INLINE void -AO_short_xor_release(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_short_xor_release +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_short_xor_release(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_short_xor_release +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -462,26 +522,32 @@ AO_int_fetch_and_add_release(volatile unsigned *addr, unsigned incr) } #define AO_HAVE_int_fetch_and_add_release -AO_INLINE void -AO_int_and_release(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_int_and_release +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_int_and_release(volatile unsigned *addr, unsigned value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_int_and_release +#endif -AO_INLINE void -AO_int_or_release(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_int_or_release +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_int_or_release(volatile unsigned *addr, unsigned value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_int_or_release +#endif -AO_INLINE void -AO_int_xor_release(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_int_xor_release +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_int_xor_release(volatile unsigned *addr, unsigned value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_int_xor_release +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -506,26 +572,32 @@ AO_fetch_and_add_release(volatile AO_t *addr, AO_t incr) } #define AO_HAVE_fetch_and_add_release -AO_INLINE void -AO_and_release(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_and_release +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_and_release(volatile AO_t *addr, AO_t value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_and_release +#endif -AO_INLINE void -AO_or_release(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_or_release +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_or_release(volatile AO_t *addr, AO_t value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_or_release +#endif -AO_INLINE void -AO_xor_release(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_xor_release +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_xor_release(volatile AO_t *addr, AO_t value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_xor_release +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -550,26 +622,32 @@ AO_char_fetch_and_add_full(volatile unsigned/**/char *addr, unsigned/**/char inc } #define AO_HAVE_char_fetch_and_add_full -AO_INLINE void -AO_char_and_full(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_char_and_full +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_char_and_full(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_char_and_full +#endif -AO_INLINE void -AO_char_or_full(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_char_or_full +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_char_or_full(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_char_or_full +#endif -AO_INLINE void -AO_char_xor_full(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_char_xor_full +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_char_xor_full(volatile unsigned/**/char *addr, unsigned/**/char value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_char_xor_full +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -594,26 +672,32 @@ AO_short_fetch_and_add_full(volatile unsigned/**/short *addr, unsigned/**/short } #define AO_HAVE_short_fetch_and_add_full -AO_INLINE void -AO_short_and_full(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_short_and_full +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_short_and_full(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_short_and_full +#endif -AO_INLINE void -AO_short_or_full(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_short_or_full +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_short_or_full(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_short_or_full +#endif -AO_INLINE void -AO_short_xor_full(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_short_xor_full +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_short_xor_full(volatile unsigned/**/short *addr, unsigned/**/short value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_short_xor_full +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -638,26 +722,32 @@ AO_int_fetch_and_add_full(volatile unsigned *addr, unsigned incr) } #define AO_HAVE_int_fetch_and_add_full -AO_INLINE void -AO_int_and_full(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_int_and_full +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_int_and_full(volatile unsigned *addr, unsigned value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_int_and_full +#endif -AO_INLINE void -AO_int_or_full(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_int_or_full +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_int_or_full(volatile unsigned *addr, unsigned value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_int_or_full +#endif -AO_INLINE void -AO_int_xor_full(volatile unsigned *addr, unsigned value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_int_xor_full +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_int_xor_full(volatile unsigned *addr, unsigned value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_int_xor_full +#endif /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -682,23 +772,29 @@ AO_fetch_and_add_full(volatile AO_t *addr, AO_t incr) } #define AO_HAVE_fetch_and_add_full -AO_INLINE void -AO_and_full(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_and_full +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_and_full(volatile AO_t *addr, AO_t value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_and_full +#endif -AO_INLINE void -AO_or_full(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_or_full +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_or_full(volatile AO_t *addr, AO_t value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_or_full +#endif -AO_INLINE void -AO_xor_full(volatile AO_t *addr, AO_t value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST); -} -#define AO_HAVE_xor_full +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_xor_full(volatile AO_t *addr, AO_t value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_SEQ_CST); + } +# define AO_HAVE_xor_full +#endif diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-arithm.template b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-arithm.template index 2067d5540..41e56bfc7 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-arithm.template +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-arithm.template @@ -22,23 +22,29 @@ AO_XSIZE_fetch_and_add_XBAR(volatile XCTYPE *addr, XCTYPE incr) } #define AO_HAVE_XSIZE_fetch_and_add_XBAR -AO_INLINE void -AO_XSIZE_and_XBAR(volatile XCTYPE *addr, XCTYPE value) -{ - (void)__atomic_and_fetch(addr, value, __ATOMIC_XGCCBAR); -} -#define AO_HAVE_XSIZE_and_XBAR +#ifndef AO_SKIPATOMIC_ANY_and_ANY + AO_INLINE void + AO_XSIZE_and_XBAR(volatile XCTYPE *addr, XCTYPE value) + { + (void)__atomic_and_fetch(addr, value, __ATOMIC_XGCCBAR); + } +# define AO_HAVE_XSIZE_and_XBAR +#endif -AO_INLINE void -AO_XSIZE_or_XBAR(volatile XCTYPE *addr, XCTYPE value) -{ - (void)__atomic_or_fetch(addr, value, __ATOMIC_XGCCBAR); -} -#define AO_HAVE_XSIZE_or_XBAR +#ifndef AO_SKIPATOMIC_ANY_or_ANY + AO_INLINE void + AO_XSIZE_or_XBAR(volatile XCTYPE *addr, XCTYPE value) + { + (void)__atomic_or_fetch(addr, value, __ATOMIC_XGCCBAR); + } +# define AO_HAVE_XSIZE_or_XBAR +#endif -AO_INLINE void -AO_XSIZE_xor_XBAR(volatile XCTYPE *addr, XCTYPE value) -{ - (void)__atomic_xor_fetch(addr, value, __ATOMIC_XGCCBAR); -} -#define AO_HAVE_XSIZE_xor_XBAR +#ifndef AO_SKIPATOMIC_ANY_xor_ANY + AO_INLINE void + AO_XSIZE_xor_XBAR(volatile XCTYPE *addr, XCTYPE value) + { + (void)__atomic_xor_fetch(addr, value, __ATOMIC_XGCCBAR); + } +# define AO_HAVE_XSIZE_xor_XBAR +#endif diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-small.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-small.h index 72f4a5bec..fb78a75b8 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-small.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-small.h @@ -15,6 +15,8 @@ * */ +#if !defined(AO_GCC_HAVE_char_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED) + AO_INLINE unsigned/**/char AO_char_load(const volatile unsigned/**/char *addr) { @@ -29,45 +31,131 @@ AO_char_load_acquire(const volatile unsigned/**/char *addr) } #define AO_HAVE_char_load_acquire -/* char_load_full is generalized using load and nop_full, so that */ /* char_load_read is defined using load and nop_read. */ +/* TODO: Map it to ACQUIRE. We should be strengthening the read and */ +/* write stuff to the more general acquire/release versions. It almost */ +/* never makes a difference and is much less error-prone. */ + +/* char_load_full is generalized using load and nop_full. */ +/* TODO: Map it to SEQ_CST and clarify the documentation. */ + +/* TODO: Map load_dd_acquire_read to ACQUIRE. Ideally it should be */ +/* mapped to CONSUME, but the latter is currently broken. */ + /* char_store_full definition is omitted similar to load_full reason. */ -AO_INLINE void -AO_char_store(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - __atomic_store_n(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_char_store +/* TODO: Map store_write to RELEASE. */ -AO_INLINE void -AO_char_store_release(volatile unsigned/**/char *addr, unsigned/**/char value) -{ - __atomic_store_n(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_char_store_release - -AO_INLINE unsigned/**/char -AO_char_fetch_compare_and_swap(volatile unsigned/**/char *addr, - unsigned/**/char old_val, unsigned/**/char new_val) -{ - return __sync_val_compare_and_swap(addr, old_val, new_val - /* empty protection list */); -} -#define AO_HAVE_char_fetch_compare_and_swap - -/* TODO: Add CAS _acquire/release/full primitives. */ - -#ifndef AO_GENERALIZE_ASM_BOOL_CAS - AO_INLINE int - AO_char_compare_and_swap(volatile unsigned/**/char *addr, - unsigned/**/char old_val, unsigned/**/char new_val) +#ifndef AO_SKIPATOMIC_char_store + AO_INLINE void + AO_char_store(volatile unsigned/**/char *addr, unsigned/**/char value) { - return __sync_bool_compare_and_swap(addr, old_val, new_val - /* empty protection list */); + __atomic_store_n(addr, value, __ATOMIC_RELAXED); } -# define AO_HAVE_char_compare_and_swap -#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ +# define AO_HAVE_char_store +#endif + +#ifndef AO_SKIPATOMIC_char_store_release + AO_INLINE void + AO_char_store_release(volatile unsigned/**/char *addr, unsigned/**/char value) + { + __atomic_store_n(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_char_store_release +#endif + +#endif /* !AO_GCC_HAVE_char_SYNC_CAS || !AO_PREFER_GENERALIZED */ + +#ifdef AO_GCC_HAVE_char_SYNC_CAS + + AO_INLINE unsigned/**/char + AO_char_fetch_compare_and_swap(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + (void)__atomic_compare_exchange_n(addr, + &old_val /* p_expected */, + new_val /* desired */, + 0 /* is_weak: false */, + __ATOMIC_RELAXED /* success */, + __ATOMIC_RELAXED /* failure */); + return old_val; + } +# define AO_HAVE_char_fetch_compare_and_swap + + AO_INLINE unsigned/**/char + AO_char_fetch_compare_and_swap_acquire(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + return old_val; + } +# define AO_HAVE_char_fetch_compare_and_swap_acquire + + AO_INLINE unsigned/**/char + AO_char_fetch_compare_and_swap_release(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + return old_val; + } +# define AO_HAVE_char_fetch_compare_and_swap_release + + AO_INLINE unsigned/**/char + AO_char_fetch_compare_and_swap_full(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + return old_val; + } +# define AO_HAVE_char_fetch_compare_and_swap_full + +# ifndef AO_GENERALIZE_ASM_BOOL_CAS + AO_INLINE int + AO_char_compare_and_swap(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); + } +# define AO_HAVE_char_compare_and_swap + + AO_INLINE int + AO_char_compare_and_swap_acquire(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_char_compare_and_swap_acquire + + AO_INLINE int + AO_char_compare_and_swap_release(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + } +# define AO_HAVE_char_compare_and_swap_release + + AO_INLINE int + AO_char_compare_and_swap_full(volatile unsigned/**/char *addr, + unsigned/**/char old_val, unsigned/**/char new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + } +# define AO_HAVE_char_compare_and_swap_full + +# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ + +#endif /* AO_GCC_HAVE_char_SYNC_CAS */ /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -85,6 +173,8 @@ AO_char_fetch_compare_and_swap(volatile unsigned/**/char *addr, * */ +#if !defined(AO_GCC_HAVE_short_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED) + AO_INLINE unsigned/**/short AO_short_load(const volatile unsigned/**/short *addr) { @@ -99,45 +189,131 @@ AO_short_load_acquire(const volatile unsigned/**/short *addr) } #define AO_HAVE_short_load_acquire -/* short_load_full is generalized using load and nop_full, so that */ /* short_load_read is defined using load and nop_read. */ +/* TODO: Map it to ACQUIRE. We should be strengthening the read and */ +/* write stuff to the more general acquire/release versions. It almost */ +/* never makes a difference and is much less error-prone. */ + +/* short_load_full is generalized using load and nop_full. */ +/* TODO: Map it to SEQ_CST and clarify the documentation. */ + +/* TODO: Map load_dd_acquire_read to ACQUIRE. Ideally it should be */ +/* mapped to CONSUME, but the latter is currently broken. */ + /* short_store_full definition is omitted similar to load_full reason. */ -AO_INLINE void -AO_short_store(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - __atomic_store_n(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_short_store +/* TODO: Map store_write to RELEASE. */ -AO_INLINE void -AO_short_store_release(volatile unsigned/**/short *addr, unsigned/**/short value) -{ - __atomic_store_n(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_short_store_release - -AO_INLINE unsigned/**/short -AO_short_fetch_compare_and_swap(volatile unsigned/**/short *addr, - unsigned/**/short old_val, unsigned/**/short new_val) -{ - return __sync_val_compare_and_swap(addr, old_val, new_val - /* empty protection list */); -} -#define AO_HAVE_short_fetch_compare_and_swap - -/* TODO: Add CAS _acquire/release/full primitives. */ - -#ifndef AO_GENERALIZE_ASM_BOOL_CAS - AO_INLINE int - AO_short_compare_and_swap(volatile unsigned/**/short *addr, - unsigned/**/short old_val, unsigned/**/short new_val) +#ifndef AO_SKIPATOMIC_short_store + AO_INLINE void + AO_short_store(volatile unsigned/**/short *addr, unsigned/**/short value) { - return __sync_bool_compare_and_swap(addr, old_val, new_val - /* empty protection list */); + __atomic_store_n(addr, value, __ATOMIC_RELAXED); } -# define AO_HAVE_short_compare_and_swap -#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ +# define AO_HAVE_short_store +#endif + +#ifndef AO_SKIPATOMIC_short_store_release + AO_INLINE void + AO_short_store_release(volatile unsigned/**/short *addr, unsigned/**/short value) + { + __atomic_store_n(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_short_store_release +#endif + +#endif /* !AO_GCC_HAVE_short_SYNC_CAS || !AO_PREFER_GENERALIZED */ + +#ifdef AO_GCC_HAVE_short_SYNC_CAS + + AO_INLINE unsigned/**/short + AO_short_fetch_compare_and_swap(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + (void)__atomic_compare_exchange_n(addr, + &old_val /* p_expected */, + new_val /* desired */, + 0 /* is_weak: false */, + __ATOMIC_RELAXED /* success */, + __ATOMIC_RELAXED /* failure */); + return old_val; + } +# define AO_HAVE_short_fetch_compare_and_swap + + AO_INLINE unsigned/**/short + AO_short_fetch_compare_and_swap_acquire(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + return old_val; + } +# define AO_HAVE_short_fetch_compare_and_swap_acquire + + AO_INLINE unsigned/**/short + AO_short_fetch_compare_and_swap_release(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + return old_val; + } +# define AO_HAVE_short_fetch_compare_and_swap_release + + AO_INLINE unsigned/**/short + AO_short_fetch_compare_and_swap_full(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + return old_val; + } +# define AO_HAVE_short_fetch_compare_and_swap_full + +# ifndef AO_GENERALIZE_ASM_BOOL_CAS + AO_INLINE int + AO_short_compare_and_swap(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); + } +# define AO_HAVE_short_compare_and_swap + + AO_INLINE int + AO_short_compare_and_swap_acquire(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_short_compare_and_swap_acquire + + AO_INLINE int + AO_short_compare_and_swap_release(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + } +# define AO_HAVE_short_compare_and_swap_release + + AO_INLINE int + AO_short_compare_and_swap_full(volatile unsigned/**/short *addr, + unsigned/**/short old_val, unsigned/**/short new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + } +# define AO_HAVE_short_compare_and_swap_full + +# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ + +#endif /* AO_GCC_HAVE_short_SYNC_CAS */ /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -155,6 +331,8 @@ AO_short_fetch_compare_and_swap(volatile unsigned/**/short *addr, * */ +#if !defined(AO_GCC_HAVE_int_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED) + AO_INLINE unsigned AO_int_load(const volatile unsigned *addr) { @@ -169,45 +347,131 @@ AO_int_load_acquire(const volatile unsigned *addr) } #define AO_HAVE_int_load_acquire -/* int_load_full is generalized using load and nop_full, so that */ /* int_load_read is defined using load and nop_read. */ +/* TODO: Map it to ACQUIRE. We should be strengthening the read and */ +/* write stuff to the more general acquire/release versions. It almost */ +/* never makes a difference and is much less error-prone. */ + +/* int_load_full is generalized using load and nop_full. */ +/* TODO: Map it to SEQ_CST and clarify the documentation. */ + +/* TODO: Map load_dd_acquire_read to ACQUIRE. Ideally it should be */ +/* mapped to CONSUME, but the latter is currently broken. */ + /* int_store_full definition is omitted similar to load_full reason. */ -AO_INLINE void -AO_int_store(volatile unsigned *addr, unsigned value) -{ - __atomic_store_n(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_int_store +/* TODO: Map store_write to RELEASE. */ -AO_INLINE void -AO_int_store_release(volatile unsigned *addr, unsigned value) -{ - __atomic_store_n(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_int_store_release - -AO_INLINE unsigned -AO_int_fetch_compare_and_swap(volatile unsigned *addr, - unsigned old_val, unsigned new_val) -{ - return __sync_val_compare_and_swap(addr, old_val, new_val - /* empty protection list */); -} -#define AO_HAVE_int_fetch_compare_and_swap - -/* TODO: Add CAS _acquire/release/full primitives. */ - -#ifndef AO_GENERALIZE_ASM_BOOL_CAS - AO_INLINE int - AO_int_compare_and_swap(volatile unsigned *addr, - unsigned old_val, unsigned new_val) +#ifndef AO_SKIPATOMIC_int_store + AO_INLINE void + AO_int_store(volatile unsigned *addr, unsigned value) { - return __sync_bool_compare_and_swap(addr, old_val, new_val - /* empty protection list */); + __atomic_store_n(addr, value, __ATOMIC_RELAXED); } -# define AO_HAVE_int_compare_and_swap -#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ +# define AO_HAVE_int_store +#endif + +#ifndef AO_SKIPATOMIC_int_store_release + AO_INLINE void + AO_int_store_release(volatile unsigned *addr, unsigned value) + { + __atomic_store_n(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_int_store_release +#endif + +#endif /* !AO_GCC_HAVE_int_SYNC_CAS || !AO_PREFER_GENERALIZED */ + +#ifdef AO_GCC_HAVE_int_SYNC_CAS + + AO_INLINE unsigned + AO_int_fetch_compare_and_swap(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + (void)__atomic_compare_exchange_n(addr, + &old_val /* p_expected */, + new_val /* desired */, + 0 /* is_weak: false */, + __ATOMIC_RELAXED /* success */, + __ATOMIC_RELAXED /* failure */); + return old_val; + } +# define AO_HAVE_int_fetch_compare_and_swap + + AO_INLINE unsigned + AO_int_fetch_compare_and_swap_acquire(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + return old_val; + } +# define AO_HAVE_int_fetch_compare_and_swap_acquire + + AO_INLINE unsigned + AO_int_fetch_compare_and_swap_release(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + return old_val; + } +# define AO_HAVE_int_fetch_compare_and_swap_release + + AO_INLINE unsigned + AO_int_fetch_compare_and_swap_full(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + return old_val; + } +# define AO_HAVE_int_fetch_compare_and_swap_full + +# ifndef AO_GENERALIZE_ASM_BOOL_CAS + AO_INLINE int + AO_int_compare_and_swap(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); + } +# define AO_HAVE_int_compare_and_swap + + AO_INLINE int + AO_int_compare_and_swap_acquire(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_int_compare_and_swap_acquire + + AO_INLINE int + AO_int_compare_and_swap_release(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + } +# define AO_HAVE_int_compare_and_swap_release + + AO_INLINE int + AO_int_compare_and_swap_full(volatile unsigned *addr, + unsigned old_val, unsigned new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + } +# define AO_HAVE_int_compare_and_swap_full + +# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ + +#endif /* AO_GCC_HAVE_int_SYNC_CAS */ /* * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. @@ -225,6 +489,8 @@ AO_int_fetch_compare_and_swap(volatile unsigned *addr, * */ +#if !defined(AO_GCC_HAVE_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED) + AO_INLINE AO_t AO_load(const volatile AO_t *addr) { @@ -239,42 +505,128 @@ AO_load_acquire(const volatile AO_t *addr) } #define AO_HAVE_load_acquire -/* load_full is generalized using load and nop_full, so that */ /* load_read is defined using load and nop_read. */ +/* TODO: Map it to ACQUIRE. We should be strengthening the read and */ +/* write stuff to the more general acquire/release versions. It almost */ +/* never makes a difference and is much less error-prone. */ + +/* load_full is generalized using load and nop_full. */ +/* TODO: Map it to SEQ_CST and clarify the documentation. */ + +/* TODO: Map load_dd_acquire_read to ACQUIRE. Ideally it should be */ +/* mapped to CONSUME, but the latter is currently broken. */ + /* store_full definition is omitted similar to load_full reason. */ -AO_INLINE void -AO_store(volatile AO_t *addr, AO_t value) -{ - __atomic_store_n(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_store +/* TODO: Map store_write to RELEASE. */ -AO_INLINE void -AO_store_release(volatile AO_t *addr, AO_t value) -{ - __atomic_store_n(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_store_release - -AO_INLINE AO_t -AO_fetch_compare_and_swap(volatile AO_t *addr, - AO_t old_val, AO_t new_val) -{ - return __sync_val_compare_and_swap(addr, old_val, new_val - /* empty protection list */); -} -#define AO_HAVE_fetch_compare_and_swap - -/* TODO: Add CAS _acquire/release/full primitives. */ - -#ifndef AO_GENERALIZE_ASM_BOOL_CAS - AO_INLINE int - AO_compare_and_swap(volatile AO_t *addr, - AO_t old_val, AO_t new_val) +#ifndef AO_SKIPATOMIC_store + AO_INLINE void + AO_store(volatile AO_t *addr, AO_t value) { - return __sync_bool_compare_and_swap(addr, old_val, new_val - /* empty protection list */); + __atomic_store_n(addr, value, __ATOMIC_RELAXED); } -# define AO_HAVE_compare_and_swap -#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ +# define AO_HAVE_store +#endif + +#ifndef AO_SKIPATOMIC_store_release + AO_INLINE void + AO_store_release(volatile AO_t *addr, AO_t value) + { + __atomic_store_n(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_store_release +#endif + +#endif /* !AO_GCC_HAVE_SYNC_CAS || !AO_PREFER_GENERALIZED */ + +#ifdef AO_GCC_HAVE_SYNC_CAS + + AO_INLINE AO_t + AO_fetch_compare_and_swap(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + (void)__atomic_compare_exchange_n(addr, + &old_val /* p_expected */, + new_val /* desired */, + 0 /* is_weak: false */, + __ATOMIC_RELAXED /* success */, + __ATOMIC_RELAXED /* failure */); + return old_val; + } +# define AO_HAVE_fetch_compare_and_swap + + AO_INLINE AO_t + AO_fetch_compare_and_swap_acquire(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + return old_val; + } +# define AO_HAVE_fetch_compare_and_swap_acquire + + AO_INLINE AO_t + AO_fetch_compare_and_swap_release(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + return old_val; + } +# define AO_HAVE_fetch_compare_and_swap_release + + AO_INLINE AO_t + AO_fetch_compare_and_swap_full(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + return old_val; + } +# define AO_HAVE_fetch_compare_and_swap_full + +# ifndef AO_GENERALIZE_ASM_BOOL_CAS + AO_INLINE int + AO_compare_and_swap(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); + } +# define AO_HAVE_compare_and_swap + + AO_INLINE int + AO_compare_and_swap_acquire(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_compare_and_swap_acquire + + AO_INLINE int + AO_compare_and_swap_release(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + } +# define AO_HAVE_compare_and_swap_release + + AO_INLINE int + AO_compare_and_swap_full(volatile AO_t *addr, + AO_t old_val, AO_t new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + } +# define AO_HAVE_compare_and_swap_full + +# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ + +#endif /* AO_GCC_HAVE_SYNC_CAS */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-small.template b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-small.template index 9685acf6a..7c2f738f3 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-small.template +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic-small.template @@ -15,6 +15,8 @@ * */ +#if !defined(AO_GCC_HAVE_XSIZE_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED) + AO_INLINE XCTYPE AO_XSIZE_load(const volatile XCTYPE *addr) { @@ -29,42 +31,128 @@ AO_XSIZE_load_acquire(const volatile XCTYPE *addr) } #define AO_HAVE_XSIZE_load_acquire -/* XSIZE_load_full is generalized using load and nop_full, so that */ /* XSIZE_load_read is defined using load and nop_read. */ +/* TODO: Map it to ACQUIRE. We should be strengthening the read and */ +/* write stuff to the more general acquire/release versions. It almost */ +/* never makes a difference and is much less error-prone. */ + +/* XSIZE_load_full is generalized using load and nop_full. */ +/* TODO: Map it to SEQ_CST and clarify the documentation. */ + +/* TODO: Map load_dd_acquire_read to ACQUIRE. Ideally it should be */ +/* mapped to CONSUME, but the latter is currently broken. */ + /* XSIZE_store_full definition is omitted similar to load_full reason. */ -AO_INLINE void -AO_XSIZE_store(volatile XCTYPE *addr, XCTYPE value) -{ - __atomic_store_n(addr, value, __ATOMIC_RELAXED); -} -#define AO_HAVE_XSIZE_store +/* TODO: Map store_write to RELEASE. */ -AO_INLINE void -AO_XSIZE_store_release(volatile XCTYPE *addr, XCTYPE value) -{ - __atomic_store_n(addr, value, __ATOMIC_RELEASE); -} -#define AO_HAVE_XSIZE_store_release - -AO_INLINE XCTYPE -AO_XSIZE_fetch_compare_and_swap(volatile XCTYPE *addr, - XCTYPE old_val, XCTYPE new_val) -{ - return __sync_val_compare_and_swap(addr, old_val, new_val - /* empty protection list */); -} -#define AO_HAVE_XSIZE_fetch_compare_and_swap - -/* TODO: Add CAS _acquire/release/full primitives. */ - -#ifndef AO_GENERALIZE_ASM_BOOL_CAS - AO_INLINE int - AO_XSIZE_compare_and_swap(volatile XCTYPE *addr, - XCTYPE old_val, XCTYPE new_val) +#ifndef AO_SKIPATOMIC_XSIZE_store + AO_INLINE void + AO_XSIZE_store(volatile XCTYPE *addr, XCTYPE value) { - return __sync_bool_compare_and_swap(addr, old_val, new_val - /* empty protection list */); + __atomic_store_n(addr, value, __ATOMIC_RELAXED); } -# define AO_HAVE_XSIZE_compare_and_swap -#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ +# define AO_HAVE_XSIZE_store +#endif + +#ifndef AO_SKIPATOMIC_XSIZE_store_release + AO_INLINE void + AO_XSIZE_store_release(volatile XCTYPE *addr, XCTYPE value) + { + __atomic_store_n(addr, value, __ATOMIC_RELEASE); + } +# define AO_HAVE_XSIZE_store_release +#endif + +#endif /* !AO_GCC_HAVE_XSIZE_SYNC_CAS || !AO_PREFER_GENERALIZED */ + +#ifdef AO_GCC_HAVE_XSIZE_SYNC_CAS + + AO_INLINE XCTYPE + AO_XSIZE_fetch_compare_and_swap(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + (void)__atomic_compare_exchange_n(addr, + &old_val /* p_expected */, + new_val /* desired */, + 0 /* is_weak: false */, + __ATOMIC_RELAXED /* success */, + __ATOMIC_RELAXED /* failure */); + return old_val; + } +# define AO_HAVE_XSIZE_fetch_compare_and_swap + + AO_INLINE XCTYPE + AO_XSIZE_fetch_compare_and_swap_acquire(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + return old_val; + } +# define AO_HAVE_XSIZE_fetch_compare_and_swap_acquire + + AO_INLINE XCTYPE + AO_XSIZE_fetch_compare_and_swap_release(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + return old_val; + } +# define AO_HAVE_XSIZE_fetch_compare_and_swap_release + + AO_INLINE XCTYPE + AO_XSIZE_fetch_compare_and_swap_full(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + (void)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + return old_val; + } +# define AO_HAVE_XSIZE_fetch_compare_and_swap_full + +# ifndef AO_GENERALIZE_ASM_BOOL_CAS + AO_INLINE int + AO_XSIZE_compare_and_swap(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); + } +# define AO_HAVE_XSIZE_compare_and_swap + + AO_INLINE int + AO_XSIZE_compare_and_swap_acquire(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_XSIZE_compare_and_swap_acquire + + AO_INLINE int + AO_XSIZE_compare_and_swap_release(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + } +# define AO_HAVE_XSIZE_compare_and_swap_release + + AO_INLINE int + AO_XSIZE_compare_and_swap_full(volatile XCTYPE *addr, + XCTYPE old_val, XCTYPE new_val) + { + return (int)__atomic_compare_exchange_n(addr, &old_val, new_val, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + } +# define AO_HAVE_XSIZE_compare_and_swap_full + +# endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ + +#endif /* AO_GCC_HAVE_XSIZE_SYNC_CAS */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic.h index de79edb00..00fd3ace0 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/generic.h @@ -2,7 +2,7 @@ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P. - * + * Copyright (c) 2013-2017 Ivan Maidanski * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -19,7 +19,34 @@ /* For the details, see GNU Manual, chapter 6.52 (Built-in functions */ /* for memory model aware atomic operations). */ -/* TODO: Include this file for other targets if gcc 4.7+ */ +#define AO_GCC_ATOMIC_TEST_AND_SET +#include "../test_and_set_t_is_char.h" + +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) \ + || defined(AO_GCC_FORCE_HAVE_CAS) +# define AO_GCC_HAVE_char_SYNC_CAS +#endif + +#if (__SIZEOF_SHORT__ == 2 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)) \ + || defined(AO_GCC_FORCE_HAVE_CAS) +# define AO_GCC_HAVE_short_SYNC_CAS +#endif + +#if (__SIZEOF_INT__ == 4 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) \ + || (__SIZEOF_INT__ == 8 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)) \ + || defined(AO_GCC_FORCE_HAVE_CAS) +# define AO_GCC_HAVE_int_SYNC_CAS +#endif + +#if (__SIZEOF_SIZE_T__ == 4 && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) \ + || (__SIZEOF_SIZE_T__ == 8 \ + && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)) \ + || defined(AO_GCC_FORCE_HAVE_CAS) +# define AO_GCC_HAVE_SYNC_CAS +#endif + +#undef AO_compiler_barrier +#define AO_compiler_barrier() __atomic_signal_fence(__ATOMIC_SEQ_CST) #ifdef AO_UNIPROCESSOR /* If only a single processor (core) is used, AO_UNIPROCESSOR could */ @@ -62,6 +89,9 @@ #ifndef AO_PREFER_GENERALIZED # include "generic-arithm.h" +# define AO_CLEAR(addr) __atomic_clear(addr, __ATOMIC_RELEASE) +# define AO_HAVE_CLEAR + AO_INLINE AO_TS_VAL_t AO_test_and_set(volatile AO_TS_t *addr) { @@ -93,7 +123,17 @@ #ifdef AO_HAVE_DOUBLE_PTR_STORAGE -# ifndef AO_HAVE_double_load +# if ((__SIZEOF_SIZE_T__ == 4 \ + && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)) \ + || (__SIZEOF_SIZE_T__ == 8 /* half of AO_double_t */ \ + && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16))) \ + && !defined(AO_SKIPATOMIC_double_compare_and_swap_ANY) +# define AO_GCC_HAVE_double_SYNC_CAS +# endif + +# if !defined(AO_GCC_HAVE_double_SYNC_CAS) || !defined(AO_PREFER_GENERALIZED) + +# if !defined(AO_HAVE_double_load) && !defined(AO_SKIPATOMIC_double_load) AO_INLINE AO_double_t AO_double_load(const volatile AO_double_t *addr) { @@ -105,7 +145,8 @@ # define AO_HAVE_double_load # endif -# ifndef AO_HAVE_double_load_acquire +# if !defined(AO_HAVE_double_load_acquire) \ + && !defined(AO_SKIPATOMIC_double_load_acquire) AO_INLINE AO_double_t AO_double_load_acquire(const volatile AO_double_t *addr) { @@ -117,7 +158,7 @@ # define AO_HAVE_double_load_acquire # endif -# ifndef AO_HAVE_double_store +# if !defined(AO_HAVE_double_store) && !defined(AO_SKIPATOMIC_double_store) AO_INLINE void AO_double_store(volatile AO_double_t *addr, AO_double_t value) { @@ -126,7 +167,8 @@ # define AO_HAVE_double_store # endif -# ifndef AO_HAVE_double_store_release +# if !defined(AO_HAVE_double_store_release) \ + && !defined(AO_SKIPATOMIC_double_store_release) AO_INLINE void AO_double_store_release(volatile AO_double_t *addr, AO_double_t value) { @@ -135,20 +177,63 @@ # define AO_HAVE_double_store_release # endif +#endif /* !AO_GCC_HAVE_double_SYNC_CAS || !AO_PREFER_GENERALIZED */ + +#endif /* AO_HAVE_DOUBLE_PTR_STORAGE */ + +#ifdef AO_GCC_HAVE_double_SYNC_CAS # ifndef AO_HAVE_double_compare_and_swap AO_INLINE int AO_double_compare_and_swap(volatile AO_double_t *addr, AO_double_t old_val, AO_double_t new_val) { return (int)__atomic_compare_exchange_n(&addr->AO_whole, - &old_val.AO_whole /* p_expected */, - new_val.AO_whole /* desired */, - 0 /* is_weak: false */, - __ATOMIC_RELAXED /* success */, - __ATOMIC_RELAXED /* failure */); + &old_val.AO_whole /* p_expected */, + new_val.AO_whole /* desired */, + 0 /* is_weak: false */, + __ATOMIC_RELAXED /* success */, + __ATOMIC_RELAXED /* failure */); } # define AO_HAVE_double_compare_and_swap # endif - /* TODO: Add double CAS _acquire/release/full primitives. */ -#endif /* AO_HAVE_DOUBLE_PTR_STORAGE */ +# ifndef AO_HAVE_double_compare_and_swap_acquire + AO_INLINE int + AO_double_compare_and_swap_acquire(volatile AO_double_t *addr, + AO_double_t old_val, + AO_double_t new_val) + { + return (int)__atomic_compare_exchange_n(&addr->AO_whole, + &old_val.AO_whole, new_val.AO_whole, 0, + __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE); + } +# define AO_HAVE_double_compare_and_swap_acquire +# endif + +# ifndef AO_HAVE_double_compare_and_swap_release + AO_INLINE int + AO_double_compare_and_swap_release(volatile AO_double_t *addr, + AO_double_t old_val, + AO_double_t new_val) + { + return (int)__atomic_compare_exchange_n(&addr->AO_whole, + &old_val.AO_whole, new_val.AO_whole, 0, + __ATOMIC_RELEASE, + __ATOMIC_RELAXED /* failure */); + } +# define AO_HAVE_double_compare_and_swap_release +# endif + +# ifndef AO_HAVE_double_compare_and_swap_full + AO_INLINE int + AO_double_compare_and_swap_full(volatile AO_double_t *addr, + AO_double_t old_val, AO_double_t new_val) + { + return (int)__atomic_compare_exchange_n(&addr->AO_whole, + &old_val.AO_whole, new_val.AO_whole, 0, + __ATOMIC_ACQ_REL, + __ATOMIC_ACQUIRE /* failure */); + } +# define AO_HAVE_double_compare_and_swap_full +# endif +#endif /* AO_GCC_HAVE_double_SYNC_CAS */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/hexagon.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/hexagon.h index da7eb4e65..ca0d8975c 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/hexagon.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/hexagon.h @@ -9,6 +9,19 @@ * modified is included with the above copyright notice. */ +#if AO_CLANG_PREREQ(3, 9) && !defined(AO_DISABLE_GCC_ATOMICS) + /* Probably, it could be enabled for earlier clang versions as well. */ + + /* As of clang-3.9, __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n are missing. */ +# define AO_GCC_FORCE_HAVE_CAS + +# define AO_GCC_HAVE_double_SYNC_CAS +# include "../standard_ao_double_t.h" + +# include "generic.h" + +#else /* AO_DISABLE_GCC_ATOMICS */ + #include "../all_aligned_atomic_load_store.h" #include "../test_and_set_t_is_ao_t.h" @@ -35,10 +48,10 @@ AO_fetch_and_add(volatile AO_t *addr, AO_t incr) AO_t newval; __asm__ __volatile__( "1:\n" - " %0 = memw_locked(%3);\n" /* load and reserve */ - " %1 = add (%0,%4);\n" /* increment */ - " memw_locked(%3,p1) = %1;\n" /* store conditional */ - " if (!p1) jump 1b;\n" /* retry if lost reservation */ + " %0 = memw_locked(%3);\n" /* load and reserve */ + " %1 = add (%0,%4);\n" /* increment */ + " memw_locked(%3,p1) = %1;\n" /* store conditional */ + " if (!p1) jump 1b;\n" /* retry if lost reservation */ : "=&r"(oldval), "=&r"(newval), "+m"(*addr) : "r"(addr), "r"(incr) : "memory", "p1"); @@ -54,14 +67,14 @@ AO_test_and_set(volatile AO_TS_t *addr) __asm__ __volatile__( "1:\n" - " %0 = memw_locked(%2);\n" /* load and reserve */ + " %0 = memw_locked(%2);\n" /* load and reserve */ " {\n" - " p2 = cmp.eq(%0,#0);\n" /* if load is not zero, */ - " if (!p2.new) jump:nt 2f; \n" /* we are done */ + " p2 = cmp.eq(%0,#0);\n" /* if load is not zero, */ + " if (!p2.new) jump:nt 2f;\n" /* we are done */ " }\n" - " memw_locked(%2,p1) = %3;\n" /* else store conditional */ - " if (!p1) jump 1b;\n" /* retry if lost reservation */ - "2:\n" /* oldval is zero if we set */ + " memw_locked(%2,p1) = %3;\n" /* else store conditional */ + " if (!p1) jump 1b;\n" /* retry if lost reservation */ + "2:\n" /* oldval is zero if we set */ : "=&r"(oldval), "+m"(*addr) : "r"(addr), "r"(locked_value) : "memory", "p1", "p2"); @@ -81,7 +94,7 @@ AO_test_and_set(volatile AO_TS_t *addr) " %0 = memw_locked(%3);\n" /* load and reserve */ " {\n" " p2 = cmp.eq(%0,%4);\n" /* if load is not equal to */ - " if (!p2.new) jump:nt 2f; \n" /* old, fail */ + " if (!p2.new) jump:nt 2f;\n" /* old, fail */ " }\n" " memw_locked(%3,p1) = %5;\n" /* else store conditional */ " if (!p1) jump 1b;\n" /* retry if lost reservation */ @@ -103,13 +116,13 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) __asm__ __volatile__( "1:\n" - " %0 = memw_locked(%2);\n" /* load and reserve */ + " %0 = memw_locked(%2);\n" /* load and reserve */ " {\n" - " p2 = cmp.eq(%0,%3);\n" /* if load is not equal to */ - " if (!p2.new) jump:nt 2f; \n" /* old_val, fail */ + " p2 = cmp.eq(%0,%3);\n" /* if load is not equal to */ + " if (!p2.new) jump:nt 2f;\n" /* old_val, fail */ " }\n" - " memw_locked(%2,p1) = %4;\n" /* else store conditional */ - " if (!p1) jump 1b;\n" /* retry if lost reservation */ + " memw_locked(%2,p1) = %4;\n" /* else store conditional */ + " if (!p1) jump 1b;\n" /* retry if lost reservation */ "2:\n" : "=&r" (__oldval), "+m"(*addr) : "r" (addr), "r" (old_val), "r" (new_val) @@ -120,3 +133,8 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) #define AO_HAVE_fetch_compare_and_swap #define AO_T_IS_INT + +#endif /* AO_DISABLE_GCC_ATOMICS */ + +#undef AO_GCC_FORCE_HAVE_CAS +#undef AO_GCC_HAVE_double_SYNC_CAS diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/hppa.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/hppa.h index d36f5823d..2d0c491c3 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/hppa.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/hppa.h @@ -37,7 +37,7 @@ struct AO_pa_clearable_loc { #undef AO_TS_INITIALIZER #define AO_TS_t struct AO_pa_clearable_loc -#define AO_TS_INITIALIZER {1,1,1,1} +#define AO_TS_INITIALIZER { { 1, 1, 1, 1 } } /* Switch meaning of set and clear, since we only have an atomic clear */ /* instruction. */ typedef enum {AO_PA_TS_set = 0, AO_PA_TS_clear = 1} AO_PA_TS_val; @@ -87,3 +87,8 @@ AO_pa_clear(volatile AO_TS_t * addr) *a = 1; } #define AO_CLEAR(addr) AO_pa_clear(addr) +#define AO_HAVE_CLEAR + +#undef AO_PA_LDCW_ALIGNMENT +#undef AO_ldcw +#undef AO_ldcw_align diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/ia64.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/ia64.h index f5549fe80..98627d53b 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/ia64.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/ia64.h @@ -279,3 +279,9 @@ AO_short_fetch_compare_and_swap_release(volatile unsigned short *addr, /* TODO: Add compare_and_swap_double as soon as there is widely */ /* available hardware that implements it. */ + +#undef AO_IN_ADDR +#undef AO_LEN +#undef AO_MASK +#undef AO_OUT_ADDR +#undef AO_SWIZZLE diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/mips.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/mips.h index 73ca551ad..34cc4fbb3 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/mips.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/mips.h @@ -17,23 +17,47 @@ * consistent. This is really aimed at modern embedded implementations. */ -#include "../all_aligned_atomic_load_store.h" - -#include "../test_and_set_t_is_ao_t.h" - /* Data dependence does not imply read ordering. */ #define AO_NO_DD_ORDERING -#if defined(_ABI64) && (_MIPS_SIM == _ABI64) -# define AO_MIPS_SET_ISA " .set mips3\n" -# define AO_MIPS_LL_1(args) " lld " args "\n" -# define AO_MIPS_SC(args) " scd " args "\n" -#else -# define AO_MIPS_SET_ISA " .set mips2\n" -# define AO_MIPS_LL_1(args) " ll " args "\n" -# define AO_MIPS_SC(args) " sc " args "\n" -# define AO_T_IS_INT -#endif +/* #include "../standard_ao_double_t.h" */ +/* TODO: Implement double-wide operations if available. */ + +#if (AO_GNUC_PREREQ(4, 9) || AO_CLANG_PREREQ(3, 5)) \ + && !defined(AO_DISABLE_GCC_ATOMICS) + /* Probably, it could be enabled even for earlier gcc/clang versions. */ + + /* As of clang-3.6/mips[64], __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n missing. */ +# if defined(__clang__) +# define AO_GCC_FORCE_HAVE_CAS +# endif + +# include "generic.h" + +#else /* AO_DISABLE_GCC_ATOMICS */ + +# include "../test_and_set_t_is_ao_t.h" +# include "../all_aligned_atomic_load_store.h" + +# if !defined(_ABI64) || _MIPS_SIM != _ABI64 +# define AO_T_IS_INT +# if __mips_isa_rev >= 6 + /* Encoding of ll/sc in mips rel6 differs from that of mips2/3. */ +# define AO_MIPS_SET_ISA "" +# else +# define AO_MIPS_SET_ISA " .set mips2\n" +# endif +# define AO_MIPS_LL_1(args) " ll " args "\n" +# define AO_MIPS_SC(args) " sc " args "\n" +# else +# if __mips_isa_rev >= 6 +# define AO_MIPS_SET_ISA "" +# else +# define AO_MIPS_SET_ISA " .set mips3\n" +# endif +# define AO_MIPS_LL_1(args) " lld " args "\n" +# define AO_MIPS_SC(args) " scd " args "\n" +# endif /* _MIPS_SIM == _ABI64 */ #ifdef AO_ICE9A1_LLSC_WAR /* ICE9 rev A1 chip (used in very few systems) is reported to */ @@ -48,12 +72,12 @@ AO_INLINE void AO_nop_full(void) { __asm__ __volatile__( - " .set push \n" + " .set push\n" AO_MIPS_SET_ISA - " .set noreorder \n" - " .set nomacro \n" - " sync \n" - " .set pop " + " .set noreorder\n" + " .set nomacro\n" + " sync\n" + " .set pop" : : : "memory"); } #define AO_HAVE_nop_full @@ -76,7 +100,7 @@ AO_fetch_and_add(volatile AO_t *addr, AO_t incr) AO_MIPS_SC("%1, %2") " beqz %1, 1b\n" " nop\n" - " .set pop " + " .set pop" : "=&r" (result), "=&r" (temp), "+m" (*addr) : "Ir" (incr) : "memory"); @@ -101,7 +125,7 @@ AO_test_and_set(volatile AO_TS_t *addr) AO_MIPS_SC("%1, %2") " beqz %1, 1b\n" " nop\n" - " .set pop " + " .set pop" : "=&r" (oldval), "=&r" (temp), "+m" (*addr) : "r" (1) : "memory"); @@ -120,19 +144,19 @@ AO_test_and_set(volatile AO_TS_t *addr) register int temp; __asm__ __volatile__( - " .set push \n" + " .set push\n" AO_MIPS_SET_ISA - " .set noreorder \n" - " .set nomacro \n" + " .set noreorder\n" + " .set nomacro\n" "1: " AO_MIPS_LL("%0, %1") - " bne %0, %4, 2f \n" - " move %0, %3 \n" + " bne %0, %4, 2f\n" + " move %0, %3\n" AO_MIPS_SC("%0, %1") - " .set pop \n" - " beqz %0, 1b \n" - " li %2, 1 \n" - "2: " + " .set pop\n" + " beqz %0, 1b\n" + " li %2, 1\n" + "2:" : "=&r" (temp), "+m" (*addr), "+r" (was_equal) : "r" (new_val), "r" (old) : "memory"); @@ -168,9 +192,14 @@ AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val) } #define AO_HAVE_fetch_compare_and_swap -/* #include "../standard_ao_double_t.h" */ -/* TODO: Implement double-wide operations if available. */ +#endif /* AO_DISABLE_GCC_ATOMICS */ /* CAS primitives with acquire, release and full semantics are */ /* generated automatically (and AO_int_... primitives are */ /* defined properly after the first generalization pass). */ + +#undef AO_GCC_FORCE_HAVE_CAS +#undef AO_MIPS_LL +#undef AO_MIPS_LL_1 +#undef AO_MIPS_SC +#undef AO_MIPS_SET_ISA diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/powerpc.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/powerpc.h index 94e83e7a1..eb594a006 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/powerpc.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/powerpc.h @@ -20,6 +20,20 @@ /* http://www-106.ibm.com/developerworks/eserver/articles/powerpc.html. */ /* There appears to be no implicit ordering between any kind of */ /* independent memory references. */ + +/* TODO: Implement double-wide operations if available. */ + +#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 8)) \ + && !defined(AO_DISABLE_GCC_ATOMICS) + /* Probably, it could be enabled even for earlier gcc/clang versions. */ + + /* TODO: As of clang-3.8.1, it emits lwsync in AO_load_acquire */ + /* (i.e., the code is less efficient than the one given below). */ + +# include "generic.h" + +#else /* AO_DISABLE_GCC_ATOMICS */ + /* Architecture enforces some ordering based on control dependence. */ /* I don't know if that could help. */ /* Data-dependent loads are always ordered. */ @@ -57,37 +71,53 @@ AO_lwsync(void) #define AO_nop_read() AO_lwsync() #define AO_HAVE_nop_read +#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__) + /* ppc64 uses ld not lwz */ +# define AO_PPC_LD "ld" +# define AO_PPC_LxARX "ldarx" +# define AO_PPC_CMPx "cmpd" +# define AO_PPC_STxCXd "stdcx." +# define AO_PPC_LOAD_CLOBBER "cr0" +#else +# define AO_PPC_LD "lwz" +# define AO_PPC_LxARX "lwarx" +# define AO_PPC_CMPx "cmpw" +# define AO_PPC_STxCXd "stwcx." +# define AO_PPC_LOAD_CLOBBER "cc" + /* FIXME: We should get gcc to allocate one of the condition */ + /* registers. I always got "impossible constraint" when I */ + /* tried the "y" constraint. */ +# define AO_T_IS_INT +#endif + +#ifdef _AIX + /* Labels are not supported on AIX. */ + /* ppc64 has same size of instructions as 32-bit one. */ +# define AO_PPC_L(label) /* empty */ +# define AO_PPC_BR_A(labelBF, addr) addr +#else +# define AO_PPC_L(label) label ": " +# define AO_PPC_BR_A(labelBF, addr) labelBF +#endif + /* We explicitly specify load_acquire, since it is important, and can */ /* be implemented relatively cheaply. It could be implemented */ /* with an ordinary load followed by a lwsync. But the general wisdom */ /* seems to be that a data dependent branch followed by an isync is */ /* cheaper. And the documentation is fairly explicit that this also */ /* has acquire semantics. */ -/* ppc64 uses ld not lwz */ AO_INLINE AO_t AO_load_acquire(const volatile AO_t *addr) { AO_t result; -#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__) - __asm__ __volatile__ ( - "ld%U1%X1 %0,%1\n" - "cmpw %0,%0\n" - "bne- 1f\n" - "1: isync\n" - : "=r" (result) - : "m"(*addr) : "memory", "cr0"); -#else - /* FIXME: We should get gcc to allocate one of the condition */ - /* registers. I always got "impossible constraint" when I */ - /* tried the "y" constraint. */ + __asm__ __volatile__ ( - "lwz%U1%X1 %0,%1\n" + AO_PPC_LD "%U1%X1 %0,%1\n" "cmpw %0,%0\n" - "bne- 1f\n" - "1: isync\n" + "bne- " AO_PPC_BR_A("1f", "$+4") "\n" + AO_PPC_L("1") "isync\n" : "=r" (result) - : "m"(*addr) : "memory", "cc"); -#endif + : "m"(*addr) : "memory", AO_PPC_LOAD_CLOBBER); return result; } #define AO_HAVE_load_acquire @@ -108,36 +138,23 @@ AO_store_release(volatile AO_t *addr, AO_t value) /* only cost us a load immediate instruction. */ AO_INLINE AO_TS_VAL_t AO_test_and_set(volatile AO_TS_t *addr) { -#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__) /* Completely untested. And we should be using smaller objects anyway. */ - unsigned long oldval; - unsigned long temp = 1; /* locked value */ + AO_t oldval; + AO_t temp = 1; /* locked value */ __asm__ __volatile__( - "1:ldarx %0,0,%1\n" /* load and reserve */ - "cmpdi %0, 0\n" /* if load is */ - "bne 2f\n" /* non-zero, return already set */ - "stdcx. %2,0,%1\n" /* else store conditional */ - "bne- 1b\n" /* retry if lost reservation */ - "2:\n" /* oldval is zero if we set */ + AO_PPC_L("1") AO_PPC_LxARX " %0,0,%1\n" + /* load and reserve */ + AO_PPC_CMPx "i %0, 0\n" /* if load is */ + "bne " AO_PPC_BR_A("2f", "$+12") "\n" + /* non-zero, return already set */ + AO_PPC_STxCXd " %2,0,%1\n" /* else store conditional */ + "bne- " AO_PPC_BR_A("1b", "$-16") "\n" + /* retry if lost reservation */ + AO_PPC_L("2") "\n" /* oldval is zero if we set */ : "=&r"(oldval) : "r"(addr), "r"(temp) : "memory", "cr0"); -#else - int oldval; - int temp = 1; /* locked value */ - - __asm__ __volatile__( - "1:lwarx %0,0,%1\n" /* load and reserve */ - "cmpwi %0, 0\n" /* if load is */ - "bne 2f\n" /* non-zero, return already set */ - "stwcx. %2,0,%1\n" /* else store conditional */ - "bne- 1b\n" /* retry if lost reservation */ - "2:\n" /* oldval is zero if we set */ - : "=&r"(oldval) - : "r"(addr), "r"(temp) - : "memory", "cr0"); -#endif return (AO_TS_VAL_t)oldval; } #define AO_HAVE_test_and_set @@ -175,31 +192,19 @@ AO_test_and_set_full(volatile AO_TS_t *addr) { { AO_t oldval; int result = 0; -# if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__) - __asm__ __volatile__( - "1:ldarx %0,0,%2\n" /* load and reserve */ - "cmpd %0, %4\n" /* if load is not equal to */ - "bne 2f\n" /* old, fail */ - "stdcx. %3,0,%2\n" /* else store conditional */ - "bne- 1b\n" /* retry if lost reservation */ + + __asm__ __volatile__( + AO_PPC_L("1") AO_PPC_LxARX " %0,0,%2\n" /* load and reserve */ + AO_PPC_CMPx " %0, %4\n" /* if load is not equal to */ + "bne " AO_PPC_BR_A("2f", "$+16") "\n" /* old, fail */ + AO_PPC_STxCXd " %3,0,%2\n" /* else store conditional */ + "bne- " AO_PPC_BR_A("1b", "$-16") "\n" + /* retry if lost reservation */ "li %1,1\n" /* result = 1; */ - "2:\n" + AO_PPC_L("2") "\n" : "=&r"(oldval), "=&r"(result) : "r"(addr), "r"(new_val), "r"(old), "1"(result) : "memory", "cr0"); -# else - __asm__ __volatile__( - "1:lwarx %0,0,%2\n" /* load and reserve */ - "cmpw %0, %4\n" /* if load is not equal to */ - "bne 2f\n" /* old, fail */ - "stwcx. %3,0,%2\n" /* else store conditional */ - "bne- 1b\n" /* retry if lost reservation */ - "li %1,1\n" /* result = 1; */ - "2:\n" - : "=&r"(oldval), "=&r"(result) - : "r"(addr), "r"(new_val), "r"(old), "1"(result) - : "memory", "cr0"); -# endif return result; } # define AO_HAVE_compare_and_swap @@ -227,7 +232,8 @@ AO_test_and_set_full(volatile AO_TS_t *addr) { int result; AO_lwsync(); result = AO_compare_and_swap(addr, old, new_val); - AO_lwsync(); + if (result) + AO_lwsync(); return result; } # define AO_HAVE_compare_and_swap_full @@ -238,29 +244,18 @@ AO_INLINE AO_t AO_fetch_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val) { AO_t fetched_val; -# if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__) - __asm__ __volatile__( - "1:ldarx %0,0,%1\n" /* load and reserve */ - "cmpd %0, %3\n" /* if load is not equal to */ - "bne 2f\n" /* old_val, fail */ - "stdcx. %2,0,%1\n" /* else store conditional */ - "bne- 1b\n" /* retry if lost reservation */ - "2:\n" + + __asm__ __volatile__( + AO_PPC_L("1") AO_PPC_LxARX " %0,0,%1\n" /* load and reserve */ + AO_PPC_CMPx " %0, %3\n" /* if load is not equal to */ + "bne " AO_PPC_BR_A("2f", "$+12") "\n" /* old_val, fail */ + AO_PPC_STxCXd " %2,0,%1\n" /* else store conditional */ + "bne- " AO_PPC_BR_A("1b", "$-16") "\n" + /* retry if lost reservation */ + AO_PPC_L("2") "\n" : "=&r"(fetched_val) : "r"(addr), "r"(new_val), "r"(old_val) : "memory", "cr0"); -# else - __asm__ __volatile__( - "1:lwarx %0,0,%1\n" /* load and reserve */ - "cmpw %0, %3\n" /* if load is not equal to */ - "bne 2f\n" /* old_val, fail */ - "stwcx. %2,0,%1\n" /* else store conditional */ - "bne- 1b\n" /* retry if lost reservation */ - "2:\n" - : "=&r"(fetched_val) - : "r"(addr), "r"(new_val), "r"(old_val) - : "memory", "cr0"); -# endif return fetched_val; } #define AO_HAVE_fetch_compare_and_swap @@ -291,7 +286,8 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, AO_t result; AO_lwsync(); result = AO_fetch_compare_and_swap(addr, old_val, new_val); - AO_lwsync(); + if (result == old_val) + AO_lwsync(); return result; } #define AO_HAVE_fetch_compare_and_swap_full @@ -301,25 +297,16 @@ AO_INLINE AO_t AO_fetch_and_add(volatile AO_t *addr, AO_t incr) { AO_t oldval; AO_t newval; -#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__) + __asm__ __volatile__( - "1:ldarx %0,0,%2\n" /* load and reserve */ - "add %1,%0,%3\n" /* increment */ - "stdcx. %1,0,%2\n" /* store conditional */ - "bne- 1b\n" /* retry if lost reservation */ + AO_PPC_L("1") AO_PPC_LxARX " %0,0,%2\n" /* load and reserve */ + "add %1,%0,%3\n" /* increment */ + AO_PPC_STxCXd " %1,0,%2\n" /* store conditional */ + "bne- " AO_PPC_BR_A("1b", "$-12") "\n" + /* retry if lost reservation */ : "=&r"(oldval), "=&r"(newval) : "r"(addr), "r"(incr) : "memory", "cr0"); -#else - __asm__ __volatile__( - "1:lwarx %0,0,%2\n" /* load and reserve */ - "add %1,%0,%3\n" /* increment */ - "stwcx. %1,0,%2\n" /* store conditional */ - "bne- 1b\n" /* retry if lost reservation */ - : "=&r"(oldval), "=&r"(newval) - : "r"(addr), "r"(incr) - : "memory", "cr0"); -#endif return oldval; } #define AO_HAVE_fetch_and_add @@ -350,10 +337,12 @@ AO_fetch_and_add_full(volatile AO_t *addr, AO_t incr) { #define AO_HAVE_fetch_and_add_full #endif /* !AO_PREFER_GENERALIZED */ -#if defined(__powerpc64__) || defined(__ppc64__) || defined(__64BIT__) - /* Empty */ -#else -# define AO_T_IS_INT -#endif +#undef AO_PPC_BR_A +#undef AO_PPC_CMPx +#undef AO_PPC_L +#undef AO_PPC_LD +#undef AO_PPC_LOAD_CLOBBER +#undef AO_PPC_LxARX +#undef AO_PPC_STxCXd -/* TODO: Implement double-wide operations if available. */ +#endif /* AO_DISABLE_GCC_ATOMICS */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/riscv.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/riscv.h new file mode 100644 index 000000000..ce7281608 --- /dev/null +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/riscv.h @@ -0,0 +1,22 @@ +/* + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + */ + +/* As of gcc-7.2.0, some __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n are missing. */ +/* The operations are lock-free (even for the types smaller than word). */ +#define AO_GCC_FORCE_HAVE_CAS + +/* While double-word atomic operations are provided by the compiler */ +/* (which requires -latomic currently), they are not lock-free as */ +/* riscv itself does not have the double-word atomic operations. */ + +#include "generic.h" + +#undef AO_GCC_FORCE_HAVE_CAS diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/s390.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/s390.h index 36efbac12..fe41898b2 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/s390.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/s390.h @@ -41,6 +41,7 @@ /* It appears that certain BCR instructions have that effect. */ /* Presumably they're cheaper than CS? */ +#ifndef AO_GENERALIZE_ASM_BOOL_CAS AO_INLINE int AO_compare_and_swap_full(volatile AO_t *addr, AO_t old, AO_t new_val) { @@ -59,7 +60,23 @@ AO_INLINE int AO_compare_and_swap_full(volatile AO_t *addr, return retval == 0; } #define AO_HAVE_compare_and_swap_full +#endif /* !AO_GENERALIZE_ASM_BOOL_CAS */ -/* TODO: implement AO_fetch_compare_and_swap. */ +AO_INLINE AO_t +AO_fetch_compare_and_swap_full(volatile AO_t *addr, + AO_t old, AO_t new_val) +{ + __asm__ __volatile__ ( +# ifndef __s390x__ + " cs %0,%2,%1\n" +# else + " csg %0,%2,%1\n" +# endif + : "+d" (old), "=Q" (*addr) + : "d" (new_val), "m" (*addr) + : "cc", "memory"); + return old; +} +#define AO_HAVE_fetch_compare_and_swap_full /* TODO: Add double-wide operations for 32-bit executables. */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/tile.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/tile.h new file mode 100644 index 000000000..e42be1e64 --- /dev/null +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/tile.h @@ -0,0 +1,48 @@ +/* + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + */ + +/* Minimal support for tile. */ + +#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 4)) \ + && !defined(AO_DISABLE_GCC_ATOMICS) + +# include "generic.h" + +#else /* AO_DISABLE_GCC_ATOMICS */ + +# include "../all_atomic_load_store.h" + +# include "../test_and_set_t_is_ao_t.h" + + AO_INLINE void + AO_nop_full(void) + { + __sync_synchronize(); + } +# define AO_HAVE_nop_full + + AO_INLINE AO_t + AO_fetch_and_add_full(volatile AO_t *p, AO_t incr) + { + return __sync_fetch_and_add(p, incr); + } +# define AO_HAVE_fetch_and_add_full + + AO_INLINE AO_t + AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, + AO_t new_val) + { + return __sync_val_compare_and_swap(addr, old_val, new_val + /* empty protection list */); + } +# define AO_HAVE_fetch_compare_and_swap_full + +#endif /* AO_DISABLE_GCC_ATOMICS */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/x86.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/x86.h index db66dda8d..f68a8b008 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/x86.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/gcc/x86.h @@ -2,7 +2,7 @@ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. - * + * Copyright (c) 2008-2018 Ivan Maidanski * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -16,6 +16,77 @@ * Some of the machine specific code was borrowed from our GC distribution. */ +#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 4)) \ + && !defined(__INTEL_COMPILER) /* TODO: test and enable icc */ \ + && !defined(AO_DISABLE_GCC_ATOMICS) +# define AO_GCC_ATOMIC_TEST_AND_SET + +# if defined(__APPLE_CC__) + /* OS X 10.7 clang-425 lacks __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n */ + /* predefined macro (unlike e.g. OS X 10.11 clang-703). */ +# define AO_GCC_FORCE_HAVE_CAS + +# ifdef __x86_64__ +# if !AO_CLANG_PREREQ(9, 0) /* < Apple clang-900 */ + /* Older Apple clang (e.g., clang-600 based on LLVM 3.5svn) had */ + /* some bug in the double word CAS implementation for x64. */ +# define AO_SKIPATOMIC_double_compare_and_swap_ANY +# endif + +# elif defined(__MACH__) + /* OS X 10.8 lacks __atomic_load/store symbols for arch i386 */ + /* (even with a non-Apple clang). */ +# ifndef MAC_OS_X_VERSION_MIN_REQUIRED + /* Include this header just to import the version macro. */ +# include +# endif +# if MAC_OS_X_VERSION_MIN_REQUIRED < 1090 /* MAC_OS_X_VERSION_10_9 */ +# define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY +# endif +# endif /* __i386__ */ + +# elif defined(__clang__) +# if !defined(__x86_64__) +# if !defined(AO_PREFER_BUILTIN_ATOMICS) && !defined(__CYGWIN__) \ + && !AO_CLANG_PREREQ(5, 0) + /* At least clang-3.8/i686 (from NDK r11c) required to specify */ + /* -latomic in case of a double-word atomic operation use. */ +# define AO_SKIPATOMIC_double_compare_and_swap_ANY +# define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY +# endif /* !AO_PREFER_BUILTIN_ATOMICS */ + +# elif !defined(__ILP32__) +# if (!AO_CLANG_PREREQ(3, 5) && !defined(AO_PREFER_BUILTIN_ATOMICS)) \ + || (!AO_CLANG_PREREQ(4, 0) && defined(AO_ADDRESS_SANITIZER)) \ + || defined(AO_THREAD_SANITIZER) + /* clang-3.4/x64 required -latomic. clang-3.9/x64 seems to */ + /* pass double-wide arguments to atomic operations incorrectly */ + /* in case of ASan/TSan. */ + /* TODO: As of clang-4.0, lock-free test_stack fails if TSan. */ +# define AO_SKIPATOMIC_double_compare_and_swap_ANY +# define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY +# endif +# endif /* __x86_64__ */ + +# elif AO_GNUC_PREREQ(7, 0) && !defined(AO_PREFER_BUILTIN_ATOMICS) \ + && !defined(AO_THREAD_SANITIZER) && !defined(__MINGW32__) + /* gcc-7.x/x64 (gcc-7.2, at least) requires -latomic flag in case */ + /* of double-word atomic operations use (but not in case of TSan). */ + /* TODO: Revise it for the future gcc-7 releases. */ +# define AO_SKIPATOMIC_double_compare_and_swap_ANY +# define AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY +# endif /* __GNUC__ && !__clang__ */ + +# ifdef AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY +# define AO_SKIPATOMIC_double_load +# define AO_SKIPATOMIC_double_load_acquire +# define AO_SKIPATOMIC_double_store +# define AO_SKIPATOMIC_double_store_release +# undef AO_SKIPATOMIC_DOUBLE_LOAD_STORE_ANY +# endif + +#else /* AO_DISABLE_GCC_ATOMICS */ + /* The following really assume we have a 486 or better. Unfortunately */ /* gcc doesn't define a suitable feature test macro based on command */ /* line options. */ @@ -87,7 +158,6 @@ AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr) #define AO_HAVE_short_fetch_and_add_full #ifndef AO_PREFER_GENERALIZED - /* Really only works for 486 and later */ AO_INLINE void AO_and_full (volatile AO_t *p, AO_t value) { @@ -118,6 +188,60 @@ AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr) /* AO_store_full could be implemented directly using "xchg" but it */ /* could be generalized efficiently as an ordinary store accomplished */ /* with AO_nop_full ("mfence" instruction). */ + +AO_INLINE void +AO_char_and_full (volatile unsigned char *p, unsigned char value) +{ + __asm__ __volatile__ ("lock; andb %1, %0" : + "=m" (*p) : "r" (value), "m" (*p) + : "memory"); +} +#define AO_HAVE_char_and_full + +AO_INLINE void +AO_char_or_full (volatile unsigned char *p, unsigned char value) +{ + __asm__ __volatile__ ("lock; orb %1, %0" : + "=m" (*p) : "r" (value), "m" (*p) + : "memory"); +} +#define AO_HAVE_char_or_full + +AO_INLINE void +AO_char_xor_full (volatile unsigned char *p, unsigned char value) +{ + __asm__ __volatile__ ("lock; xorb %1, %0" : + "=m" (*p) : "r" (value), "m" (*p) + : "memory"); +} +#define AO_HAVE_char_xor_full + +AO_INLINE void +AO_short_and_full (volatile unsigned short *p, unsigned short value) +{ + __asm__ __volatile__ ("lock; andw %1, %0" : + "=m" (*p) : "r" (value), "m" (*p) + : "memory"); +} +#define AO_HAVE_short_and_full + +AO_INLINE void +AO_short_or_full (volatile unsigned short *p, unsigned short value) +{ + __asm__ __volatile__ ("lock; orw %1, %0" : + "=m" (*p) : "r" (value), "m" (*p) + : "memory"); +} +#define AO_HAVE_short_or_full + +AO_INLINE void +AO_short_xor_full (volatile unsigned short *p, unsigned short value) +{ + __asm__ __volatile__ ("lock; xorw %1, %0" : + "=m" (*p) : "r" (value), "m" (*p) + : "memory"); +} +#define AO_HAVE_short_xor_full #endif /* !AO_PREFER_GENERALIZED */ AO_INLINE AO_TS_VAL_t @@ -174,14 +298,142 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, } #define AO_HAVE_fetch_compare_and_swap_full -#if !defined(__x86_64__) && !defined(AO_USE_SYNC_CAS_BUILTIN) + AO_INLINE unsigned char + AO_char_fetch_compare_and_swap_full(volatile unsigned char *addr, + unsigned char old_val, + unsigned char new_val) + { +# ifdef AO_USE_SYNC_CAS_BUILTIN + return __sync_val_compare_and_swap(addr, old_val, new_val + /* empty protection list */); +# else + unsigned char fetched_val; + + __asm__ __volatile__ ("lock; cmpxchgb %3, %4" + : "=a" (fetched_val), "=m" (*addr) + : "a" (old_val), "q" (new_val), "m" (*addr) + : "memory"); + return fetched_val; +# endif + } +# define AO_HAVE_char_fetch_compare_and_swap_full + + AO_INLINE unsigned short + AO_short_fetch_compare_and_swap_full(volatile unsigned short *addr, + unsigned short old_val, + unsigned short new_val) + { +# ifdef AO_USE_SYNC_CAS_BUILTIN + return __sync_val_compare_and_swap(addr, old_val, new_val + /* empty protection list */); +# else + unsigned short fetched_val; + + __asm__ __volatile__ ("lock; cmpxchgw %3, %4" + : "=a" (fetched_val), "=m" (*addr) + : "a" (old_val), "r" (new_val), "m" (*addr) + : "memory"); + return fetched_val; +# endif + } +# define AO_HAVE_short_fetch_compare_and_swap_full + +# if defined(__x86_64__) && !defined(__ILP32__) + AO_INLINE unsigned int + AO_int_fetch_compare_and_swap_full(volatile unsigned int *addr, + unsigned int old_val, + unsigned int new_val) + { +# ifdef AO_USE_SYNC_CAS_BUILTIN + return __sync_val_compare_and_swap(addr, old_val, new_val + /* empty protection list */); +# else + unsigned int fetched_val; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %4" + : "=a" (fetched_val), "=m" (*addr) + : "a" (old_val), "r" (new_val), "m" (*addr) + : "memory"); + return fetched_val; +# endif + } +# define AO_HAVE_int_fetch_compare_and_swap_full + +# ifndef AO_PREFER_GENERALIZED + AO_INLINE unsigned int + AO_int_fetch_and_add_full (volatile unsigned int *p, unsigned int incr) + { + unsigned int result; + + __asm__ __volatile__ ("lock; xaddl %0, %1" + : "=r" (result), "=m" (*p) + : "0" (incr), "m" (*p) + : "memory"); + return result; + } +# define AO_HAVE_int_fetch_and_add_full + + AO_INLINE void + AO_int_and_full (volatile unsigned int *p, unsigned int value) + { + __asm__ __volatile__ ("lock; andl %1, %0" + : "=m" (*p) : "r" (value), "m" (*p) + : "memory"); + } +# define AO_HAVE_int_and_full + + AO_INLINE void + AO_int_or_full (volatile unsigned int *p, unsigned int value) + { + __asm__ __volatile__ ("lock; orl %1, %0" + : "=m" (*p) : "r" (value), "m" (*p) + : "memory"); + } +# define AO_HAVE_int_or_full + + AO_INLINE void + AO_int_xor_full (volatile unsigned int *p, unsigned int value) + { + __asm__ __volatile__ ("lock; xorl %1, %0" + : "=m" (*p) : "r" (value), "m" (*p) + : "memory"); + } +# define AO_HAVE_int_xor_full +# endif /* !AO_PREFER_GENERALIZED */ + +# else +# define AO_T_IS_INT +# endif /* !x86_64 || ILP32 */ + + /* Real X86 implementations, except for some old 32-bit WinChips, */ + /* appear to enforce ordering between memory operations, EXCEPT that */ + /* a later read can pass earlier writes, presumably due to the */ + /* visible presence of store buffers. */ + /* We ignore both the WinChips and the fact that the official specs */ + /* seem to be much weaker (and arguably too weak to be usable). */ +# include "../ordered_except_wr.h" + +#endif /* AO_DISABLE_GCC_ATOMICS */ + +#if defined(AO_GCC_ATOMIC_TEST_AND_SET) \ + && !defined(AO_SKIPATOMIC_double_compare_and_swap_ANY) + +# if defined(__ILP32__) || !defined(__x86_64__) /* 32-bit AO_t */ \ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) /* 64-bit AO_t */ +# include "../standard_ao_double_t.h" +# endif + +#elif !defined(__x86_64__) && (!defined(AO_USE_SYNC_CAS_BUILTIN) \ + || defined(AO_GCC_ATOMIC_TEST_AND_SET)) # include "../standard_ao_double_t.h" /* Reading or writing a quadword aligned on a 64-bit boundary is */ /* always carried out atomically on at least a Pentium according to */ /* Chapter 8.1.1 of Volume 3A Part 1 of Intel processor manuals. */ -# define AO_ACCESS_double_CHECK_ALIGNED -# include "../loadstore/double_atomic_load_store.h" +# ifndef AO_PREFER_GENERALIZED +# define AO_ACCESS_double_CHECK_ALIGNED +# include "../loadstore/double_atomic_load_store.h" +# endif /* Returns nonzero if the comparison succeeded. */ /* Really requires at least a Pentium. */ @@ -245,15 +497,15 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, } # define AO_HAVE_compare_double_and_swap_double_full -# define AO_T_IS_INT - #elif defined(__ILP32__) || !defined(__x86_64__) # include "../standard_ao_double_t.h" /* Reading or writing a quadword aligned on a 64-bit boundary is */ /* always carried out atomically (requires at least a Pentium). */ -# define AO_ACCESS_double_CHECK_ALIGNED -# include "../loadstore/double_atomic_load_store.h" +# ifndef AO_PREFER_GENERALIZED +# define AO_ACCESS_double_CHECK_ALIGNED +# include "../loadstore/double_atomic_load_store.h" +# endif /* X32 has native support for 64-bit integer operations (AO_double_t */ /* is a 64-bit integer and we could use 64-bit cmpxchg). */ @@ -269,22 +521,10 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, } # define AO_HAVE_double_compare_and_swap_full -# define AO_T_IS_INT - -#else /* 64-bit */ - - AO_INLINE unsigned int - AO_int_fetch_and_add_full (volatile unsigned int *p, unsigned int incr) - { - unsigned int result; - - __asm__ __volatile__ ("lock; xaddl %0, %1" - : "=r" (result), "=m" (*p) - : "0" (incr), "m" (*p) - : "memory"); - return result; - } -# define AO_HAVE_int_fetch_and_add_full +#elif defined(AO_CMPXCHG16B_AVAILABLE) \ + || (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) \ + && !defined(AO_THREAD_SANITIZER)) +# include "../standard_ao_double_t.h" /* The Intel and AMD Architecture Programmer Manuals state roughly */ /* the following: */ @@ -298,63 +538,68 @@ AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, /* Thus, currently, the only way to implement lock-free double_load */ /* and double_store on x86_64 is to use CMPXCHG16B (if available). */ -/* TODO: Test some gcc macro to detect presence of cmpxchg16b. */ + /* NEC LE-IT: older AMD Opterons are missing this instruction. */ + /* On these machines SIGILL will be thrown. */ + /* Define AO_WEAK_DOUBLE_CAS_EMULATION to have an emulated (lock */ + /* based) version available. */ + /* HB: Changed this to not define either by default. There are */ + /* enough machines and tool chains around on which cmpxchg16b */ + /* doesn't work. And the emulation is unsafe by our usual rules. */ + /* However both are clearly useful in certain cases. */ -# ifdef AO_CMPXCHG16B_AVAILABLE -# include "../standard_ao_double_t.h" - - /* NEC LE-IT: older AMD Opterons are missing this instruction. */ - /* On these machines SIGILL will be thrown. */ - /* Define AO_WEAK_DOUBLE_CAS_EMULATION to have an emulated (lock */ - /* based) version available. */ - /* HB: Changed this to not define either by default. There are */ - /* enough machines and tool chains around on which cmpxchg16b */ - /* doesn't work. And the emulation is unsafe by our usual rules. */ - /* However both are clearly useful in certain cases. */ - AO_INLINE int - AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, - AO_t old_val1, AO_t old_val2, - AO_t new_val1, AO_t new_val2) - { - char result; - __asm__ __volatile__("lock; cmpxchg16b %0; setz %1" + AO_INLINE int + AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, + AO_t old_val1, AO_t old_val2, + AO_t new_val1, AO_t new_val2) + { + char result; + __asm__ __volatile__("lock; cmpxchg16b %0; setz %1" : "=m"(*addr), "=a"(result) : "m"(*addr), "d" (old_val2), "a" (old_val1), "c" (new_val2), "b" (new_val1) : "memory"); - return (int) result; - } -# define AO_HAVE_compare_double_and_swap_double_full + return (int) result; + } +# define AO_HAVE_compare_double_and_swap_double_full -# elif defined(AO_WEAK_DOUBLE_CAS_EMULATION) -# include "../standard_ao_double_t.h" +#elif defined(AO_WEAK_DOUBLE_CAS_EMULATION) +# include "../standard_ao_double_t.h" - /* This one provides spinlock based emulation of CAS implemented in */ - /* atomic_ops.c. We probably do not want to do this here, since it */ - /* is not atomic with respect to other kinds of updates of *addr. */ - /* On the other hand, this may be a useful facility on occasion. */ - int AO_compare_double_and_swap_double_emulation( - volatile AO_double_t *addr, - AO_t old_val1, AO_t old_val2, - AO_t new_val1, AO_t new_val2); +# ifdef __cplusplus + extern "C" { +# endif - AO_INLINE int - AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, - AO_t old_val1, AO_t old_val2, - AO_t new_val1, AO_t new_val2) - { - return AO_compare_double_and_swap_double_emulation(addr, + /* This one provides spinlock based emulation of CAS implemented in */ + /* atomic_ops.c. We probably do not want to do this here, since it */ + /* is not atomic with respect to other kinds of updates of *addr. */ + /* On the other hand, this may be a useful facility on occasion. */ + int AO_compare_double_and_swap_double_emulation( + volatile AO_double_t *addr, + AO_t old_val1, AO_t old_val2, + AO_t new_val1, AO_t new_val2); + +# ifdef __cplusplus + } /* extern "C" */ +# endif + + AO_INLINE int + AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, + AO_t old_val1, AO_t old_val2, + AO_t new_val1, AO_t new_val2) + { + return AO_compare_double_and_swap_double_emulation(addr, old_val1, old_val2, new_val1, new_val2); - } -# define AO_HAVE_compare_double_and_swap_double_full -# endif /* AO_WEAK_DOUBLE_CAS_EMULATION && !AO_CMPXCHG16B_AVAILABLE */ + } +# define AO_HAVE_compare_double_and_swap_double_full +#endif /* x86_64 && !ILP32 && CAS_EMULATION && !AO_CMPXCHG16B_AVAILABLE */ -#endif /* x86_64 && !ILP32 */ +#ifdef AO_GCC_ATOMIC_TEST_AND_SET +# include "generic.h" +#endif -/* Real X86 implementations, except for some old 32-bit WinChips, */ -/* appear to enforce ordering between memory operations, EXCEPT that */ -/* a later read can pass earlier writes, presumably due to the visible */ -/* presence of store buffers. */ -/* We ignore both the WinChips and the fact that the official specs */ -/* seem to be much weaker (and arguably too weak to be usable). */ -#include "../ordered_except_wr.h" +#undef AO_GCC_FORCE_HAVE_CAS +#undef AO_SKIPATOMIC_double_compare_and_swap_ANY +#undef AO_SKIPATOMIC_double_load +#undef AO_SKIPATOMIC_double_load_acquire +#undef AO_SKIPATOMIC_double_store +#undef AO_SKIPATOMIC_double_store_release diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/generic_pthread.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/generic_pthread.h index 3c65624f0..854cb7753 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/generic_pthread.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/generic_pthread.h @@ -33,10 +33,18 @@ /* This is not necessarily compatible with the native */ /* implementation. But those can't be safely mixed anyway. */ +#ifdef __cplusplus + extern "C" { +#endif + /* We define only the full barrier variants, and count on the */ /* generalization section below to fill in the rest. */ extern pthread_mutex_t AO_pt_lock; +#ifdef __cplusplus + } /* extern "C" */ +#endif + AO_INLINE void AO_nop_full(void) { diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/hpc/hppa.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/hpc/hppa.h index 4e27eb2ef..f0da9480d 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/hpc/hppa.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/hpc/hppa.h @@ -80,6 +80,9 @@ AO_test_and_set_full(volatile AO_TS_t * addr) register unsigned int ret; register unsigned long a = (unsigned long)AO_ldcw_align(addr); +# if defined(CPPCHECK) + ret = 0; /* to void 'uninitialized variable' warning */ +# endif AO_ldcw(a, ret); return (AO_TS_VAL_t)ret; } @@ -94,3 +97,8 @@ AO_pa_clear(volatile AO_TS_t * addr) *a = 1; } #define AO_CLEAR(addr) AO_pa_clear(addr) +#define AO_HAVE_CLEAR + +#undef AO_PA_LDCW_ALIGNMENT +#undef AO_ldcw +#undef AO_ldcw_align diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/hpc/ia64.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/hpc/ia64.h index 6391eda3c..e71f5e807 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/hpc/ia64.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/hpc/ia64.h @@ -153,3 +153,6 @@ AO_short_fetch_compare_and_swap_release(volatile unsigned short *addr, #ifndef __LP64__ # define AO_T_IS_INT #endif + +#undef AO_T_FASIZE +#undef AO_T_SIZE diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/ibmc/powerpc.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/ibmc/powerpc.h index cb79c8903..a930b1679 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/ibmc/powerpc.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/ibmc/powerpc.h @@ -1,5 +1,4 @@ -/* FIXME. This is only a placeholder for the AIX compiler. */ -/* It doesn't work. Please send a patch. */ + /* Memory model documented at http://www-106.ibm.com/developerworks/ */ /* eserver/articles/archguide.html and (clearer) */ /* http://www-106.ibm.com/developerworks/eserver/articles/powerpc.html. */ @@ -93,7 +92,6 @@ AO_test_and_set(volatile AO_TS_t *addr) { } #define AO_HAVE_test_and_set - AO_INLINE AO_TS_VAL_t AO_test_and_set_acquire(volatile AO_TS_t *addr) { AO_TS_VAL_t result = AO_test_and_set(addr); diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/icc/ia64.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/icc/ia64.h index b43a50148..6654209dd 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/icc/ia64.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/icc/ia64.h @@ -203,3 +203,5 @@ AO_int_fetch_compare_and_swap_release(volatile unsigned int *addr, return _InterlockedCompareExchange_rel(addr, new_val, old_val); } #define AO_HAVE_int_fetch_compare_and_swap_release + +#undef AO_INTEL_PTR_t diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/loadstore/double_atomic_load_store.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/loadstore/double_atomic_load_store.h index 66ce628f0..145a14c23 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/loadstore/double_atomic_load_store.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/loadstore/double_atomic_load_store.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2004 Hewlett-Packard Development Company, L.P. + * Copyright (c) 2013 Ivan Maidanski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/arm.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/arm.h index 647373b7e..8ea238c04 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/arm.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/arm.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2003 Hewlett-Packard Development Company, L.P. + * Copyright (c) 2009-2017 Ivan Maidanski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,8 +26,6 @@ # define AO_ASSUME_WINDOWS98 #endif #include "common32_defs.h" -/* FIXME: Do _InterlockedOps really have a full memory barrier? */ -/* (MSDN WinCE docs say nothing about it.) */ #include "../test_and_set_t_is_ao_t.h" /* AO_test_and_set_full() is emulated using CAS. */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/common32_defs.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/common32_defs.h index 989974eaa..fa7ee9530 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/common32_defs.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/common32_defs.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P. + * Copyright (c) 2009-2018 Ivan Maidanski * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,9 +30,12 @@ /* (otherwise "Interlocked" functions family is used instead). */ /* Define AO_ASSUME_WINDOWS98 if CAS is available. */ -#include +#if _MSC_VER <= 1400 || !defined(AO_USE_INTERLOCKED_INTRINSICS) \ + || defined(_WIN32_WCE) +# include /* Seems like over-kill, but that's what MSDN recommends. */ /* And apparently winbase.h is not always self-contained. */ +#endif #if _MSC_VER < 1310 || !defined(AO_USE_INTERLOCKED_INTRINSICS) @@ -59,7 +63,7 @@ LONG __cdecl _InterlockedCompareExchange(LONG volatile *, LONG /* Exchange */, LONG /* Comp */); # ifdef __cplusplus - } + } /* extern "C" */ # endif # endif /* _MSC_VER < 1400 */ @@ -78,22 +82,21 @@ AO_INLINE AO_t AO_fetch_and_add_full(volatile AO_t *p, AO_t incr) { - return _InterlockedExchangeAdd((LONG AO_INTERLOCKED_VOLATILE *)p, - (LONG)incr); + return _InterlockedExchangeAdd((long AO_INTERLOCKED_VOLATILE *)p, incr); } #define AO_HAVE_fetch_and_add_full AO_INLINE AO_t AO_fetch_and_add1_full(volatile AO_t *p) { - return _InterlockedIncrement((LONG AO_INTERLOCKED_VOLATILE *)p) - 1; + return _InterlockedIncrement((long AO_INTERLOCKED_VOLATILE *)p) - 1; } #define AO_HAVE_fetch_and_add1_full AO_INLINE AO_t AO_fetch_and_sub1_full(volatile AO_t *p) { - return _InterlockedDecrement((LONG AO_INTERLOCKED_VOLATILE *)p) + 1; + return _InterlockedDecrement((long AO_INTERLOCKED_VOLATILE *)p) + 1; } #define AO_HAVE_fetch_and_sub1_full #endif /* !AO_PREFER_GENERALIZED */ @@ -105,13 +108,105 @@ AO_fetch_and_sub1_full(volatile AO_t *p) { # ifdef AO_OLD_STYLE_INTERLOCKED_COMPARE_EXCHANGE return (AO_t)_InterlockedCompareExchange( - (PVOID AO_INTERLOCKED_VOLATILE *)addr, - (PVOID)new_val, (PVOID)old_val); + (void *AO_INTERLOCKED_VOLATILE *)addr, + (void *)new_val, (void *)old_val); # else - return (AO_t)_InterlockedCompareExchange( - (LONG AO_INTERLOCKED_VOLATILE *)addr, - (LONG)new_val, (LONG)old_val); + return _InterlockedCompareExchange((long AO_INTERLOCKED_VOLATILE *)addr, + new_val, old_val); # endif } # define AO_HAVE_fetch_compare_and_swap_full #endif /* AO_ASSUME_WINDOWS98 */ + +#if (_MSC_VER > 1400) && (!defined(_M_ARM) || _MSC_VER >= 1800) + +# pragma intrinsic (_InterlockedAnd8) +# pragma intrinsic (_InterlockedCompareExchange16) +# pragma intrinsic (_InterlockedOr8) +# pragma intrinsic (_InterlockedXor8) + + AO_INLINE void + AO_char_and_full(volatile unsigned char *p, unsigned char value) + { + _InterlockedAnd8((char volatile *)p, value); + } +# define AO_HAVE_char_and_full + + AO_INLINE void + AO_char_or_full(volatile unsigned char *p, unsigned char value) + { + _InterlockedOr8((char volatile *)p, value); + } +# define AO_HAVE_char_or_full + + AO_INLINE void + AO_char_xor_full(volatile unsigned char *p, unsigned char value) + { + _InterlockedXor8((char volatile *)p, value); + } +# define AO_HAVE_char_xor_full + + AO_INLINE unsigned short + AO_short_fetch_compare_and_swap_full(volatile unsigned short *addr, + unsigned short old_val, + unsigned short new_val) + { + return _InterlockedCompareExchange16((short volatile *)addr, + new_val, old_val); + } +# define AO_HAVE_short_fetch_compare_and_swap_full + +# ifndef AO_PREFER_GENERALIZED +# pragma intrinsic (_InterlockedIncrement16) +# pragma intrinsic (_InterlockedDecrement16) + + AO_INLINE unsigned short + AO_short_fetch_and_add1_full(volatile unsigned short *p) + { + return _InterlockedIncrement16((short volatile *)p) - 1; + } +# define AO_HAVE_short_fetch_and_add1_full + + AO_INLINE unsigned short + AO_short_fetch_and_sub1_full(volatile unsigned short *p) + { + return _InterlockedDecrement16((short volatile *)p) + 1; + } +# define AO_HAVE_short_fetch_and_sub1_full +# endif /* !AO_PREFER_GENERALIZED */ +#endif /* _MSC_VER > 1400 */ + +#if _MSC_VER >= 1800 /* Visual Studio 2013+ */ + +# pragma intrinsic (_InterlockedCompareExchange8) + + AO_INLINE unsigned char + AO_char_fetch_compare_and_swap_full(volatile unsigned char *addr, + unsigned char old_val, + unsigned char new_val) + { + return _InterlockedCompareExchange8((char volatile *)addr, + new_val, old_val); + } +# define AO_HAVE_char_fetch_compare_and_swap_full + +# if !defined(AO_PREFER_GENERALIZED) && !defined(_M_ARM) +# pragma intrinsic (_InterlockedExchangeAdd16) +# pragma intrinsic (_InterlockedExchangeAdd8) + + AO_INLINE unsigned char + AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr) + { + return _InterlockedExchangeAdd8((char volatile *)p, incr); + } +# define AO_HAVE_char_fetch_and_add_full + + AO_INLINE unsigned short + AO_short_fetch_and_add_full(volatile unsigned short *p, + unsigned short incr) + { + return _InterlockedExchangeAdd16((short volatile *)p, incr); + } +# define AO_HAVE_short_fetch_and_add_full +# endif /* !AO_PREFER_GENERALIZED && !_M_ARM */ +#endif /* _MSC_VER >= 1800 */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/x86.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/x86.h index 7c2995a4e..3de961699 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/x86.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/x86.h @@ -20,7 +20,6 @@ * SOFTWARE. */ -/* If AO_ASSUME_WINDOWS98 is defined, we assume Windows 98 or newer. */ /* If AO_ASSUME_VISTA is defined, we assume Windows Server 2003, Vista */ /* or later. */ @@ -28,7 +27,9 @@ #include "../test_and_set_t_is_char.h" -#if defined(AO_ASSUME_VISTA) && !defined(AO_ASSUME_WINDOWS98) +#if !defined(AO_ASSUME_WINDOWS98) \ + && (defined(AO_ASSUME_VISTA) || _MSC_VER >= 1400) + /* Visual Studio 2005 (MS VC++ 8.0) discontinued support of Windows 95. */ # define AO_ASSUME_WINDOWS98 #endif @@ -62,7 +63,7 @@ AO_nop_full(void) #endif -#ifndef AO_NO_ASM_XADD +#if !defined(AO_NO_ASM_XADD) && !defined(AO_HAVE_char_fetch_and_add_full) AO_INLINE unsigned char AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr) { @@ -103,8 +104,8 @@ AO_test_and_set_full(volatile AO_TS_t *addr) } #define AO_HAVE_test_and_set_full -#ifdef _WIN64 -# error wrong architecture +#if defined(_WIN64) && !defined(CPPCHECK) +# error wrong architecture #endif #ifdef AO_ASSUME_VISTA @@ -124,6 +125,7 @@ AO_test_and_set_full(volatile AO_TS_t *addr) AO_double_compare_and_swap_full(volatile AO_double_t *addr, AO_double_t old_val, AO_double_t new_val) { + assert(((size_t)addr & (sizeof(AO_double_t) - 1)) == 0); return (double_ptr_storage)_InterlockedCompareExchange64( (__int64 volatile *)addr, new_val.AO_whole /* exchange */, diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/x86_64.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/x86_64.h index b4b0a3c1a..fead27342 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/x86_64.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/msftc/x86_64.h @@ -37,40 +37,39 @@ # include "../test_and_set_t_is_ao_t.h" #endif -#include - /* Seems like over-kill, but that's what MSDN recommends. */ - /* And apparently winbase.h is not always self-contained. */ - /* Assume _MSC_VER >= 1400 */ #include -#pragma intrinsic (_InterlockedExchangeAdd) +#pragma intrinsic (_InterlockedCompareExchange) #pragma intrinsic (_InterlockedCompareExchange64) #ifndef AO_PREFER_GENERALIZED +# pragma intrinsic (_InterlockedIncrement) # pragma intrinsic (_InterlockedIncrement64) +# pragma intrinsic (_InterlockedDecrement) # pragma intrinsic (_InterlockedDecrement64) +# pragma intrinsic (_InterlockedExchangeAdd) # pragma intrinsic (_InterlockedExchangeAdd64) AO_INLINE AO_t AO_fetch_and_add_full (volatile AO_t *p, AO_t incr) { - return _InterlockedExchangeAdd64((LONGLONG volatile *)p, (LONGLONG)incr); + return _InterlockedExchangeAdd64((__int64 volatile *)p, incr); } #define AO_HAVE_fetch_and_add_full AO_INLINE AO_t AO_fetch_and_add1_full (volatile AO_t *p) { - return _InterlockedIncrement64((LONGLONG volatile *)p) - 1; + return _InterlockedIncrement64((__int64 volatile *)p) - 1; } #define AO_HAVE_fetch_and_add1_full AO_INLINE AO_t AO_fetch_and_sub1_full (volatile AO_t *p) { - return _InterlockedDecrement64((LONGLONG volatile *)p) + 1; + return _InterlockedDecrement64((__int64 volatile *)p) + 1; } #define AO_HAVE_fetch_and_sub1_full #endif /* !AO_PREFER_GENERALIZED */ @@ -79,19 +78,134 @@ AO_INLINE AO_t AO_fetch_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, AO_t new_val) { - return (AO_t)_InterlockedCompareExchange64((LONGLONG volatile *)addr, - (LONGLONG)new_val, (LONGLONG)old_val); + return (AO_t)_InterlockedCompareExchange64((__int64 volatile *)addr, + new_val, old_val); } #define AO_HAVE_fetch_compare_and_swap_full +AO_INLINE unsigned int +AO_int_fetch_compare_and_swap_full(volatile unsigned int *addr, + unsigned int old_val, unsigned int new_val) +{ + return _InterlockedCompareExchange((long volatile *)addr, new_val, old_val); +} +#define AO_HAVE_int_fetch_compare_and_swap_full + +#ifndef AO_PREFER_GENERALIZED AO_INLINE unsigned int AO_int_fetch_and_add_full(volatile unsigned int *p, unsigned int incr) { - return _InterlockedExchangeAdd((LONG volatile *)p, incr); + return _InterlockedExchangeAdd((long volatile *)p, incr); } #define AO_HAVE_int_fetch_and_add_full -#ifdef AO_ASM_X64_AVAILABLE + AO_INLINE unsigned int + AO_int_fetch_and_add1_full(volatile unsigned int *p) + { + return _InterlockedIncrement((long volatile *)p) - 1; + } +# define AO_HAVE_int_fetch_and_add1_full + + AO_INLINE unsigned int + AO_int_fetch_and_sub1_full(volatile unsigned int *p) + { + return _InterlockedDecrement((long volatile *)p) + 1; + } +# define AO_HAVE_int_fetch_and_sub1_full +#endif /* !AO_PREFER_GENERALIZED */ + +#if _MSC_VER > 1400 +# pragma intrinsic (_InterlockedAnd8) +# pragma intrinsic (_InterlockedCompareExchange16) +# pragma intrinsic (_InterlockedOr8) +# pragma intrinsic (_InterlockedXor8) + + AO_INLINE void + AO_char_and_full(volatile unsigned char *p, unsigned char value) + { + _InterlockedAnd8((char volatile *)p, value); + } +# define AO_HAVE_char_and_full + + AO_INLINE void + AO_char_or_full(volatile unsigned char *p, unsigned char value) + { + _InterlockedOr8((char volatile *)p, value); + } +# define AO_HAVE_char_or_full + + AO_INLINE void + AO_char_xor_full(volatile unsigned char *p, unsigned char value) + { + _InterlockedXor8((char volatile *)p, value); + } +# define AO_HAVE_char_xor_full + + AO_INLINE unsigned short + AO_short_fetch_compare_and_swap_full(volatile unsigned short *addr, + unsigned short old_val, + unsigned short new_val) + { + return _InterlockedCompareExchange16((short volatile *)addr, + new_val, old_val); + } +# define AO_HAVE_short_fetch_compare_and_swap_full + +# ifndef AO_PREFER_GENERALIZED +# pragma intrinsic (_InterlockedIncrement16) +# pragma intrinsic (_InterlockedDecrement16) + + AO_INLINE unsigned short + AO_short_fetch_and_add1_full(volatile unsigned short *p) + { + return _InterlockedIncrement16((short volatile *)p) - 1; + } +# define AO_HAVE_short_fetch_and_add1_full + + AO_INLINE unsigned short + AO_short_fetch_and_sub1_full(volatile unsigned short *p) + { + return _InterlockedDecrement16((short volatile *)p) + 1; + } +# define AO_HAVE_short_fetch_and_sub1_full +# endif /* !AO_PREFER_GENERALIZED */ +#endif /* _MSC_VER > 1400 */ + +#if _MSC_VER >= 1800 /* Visual Studio 2013+ */ + +# pragma intrinsic (_InterlockedCompareExchange8) + + AO_INLINE unsigned char + AO_char_fetch_compare_and_swap_full(volatile unsigned char *addr, + unsigned char old_val, + unsigned char new_val) + { + return _InterlockedCompareExchange8((char volatile *)addr, + new_val, old_val); + } +# define AO_HAVE_char_fetch_compare_and_swap_full + +# ifndef AO_PREFER_GENERALIZED +# pragma intrinsic (_InterlockedExchangeAdd16) +# pragma intrinsic (_InterlockedExchangeAdd8) + + AO_INLINE unsigned char + AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr) + { + return _InterlockedExchangeAdd8((char volatile *)p, incr); + } +# define AO_HAVE_char_fetch_and_add_full + + AO_INLINE unsigned short + AO_short_fetch_and_add_full(volatile unsigned short *p, + unsigned short incr) + { + return _InterlockedExchangeAdd16((short volatile *)p, incr); + } +# define AO_HAVE_short_fetch_and_add_full +# endif /* !AO_PREFER_GENERALIZED */ + +#elif defined(AO_ASM_X64_AVAILABLE) AO_INLINE unsigned char AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr) @@ -117,6 +231,10 @@ AO_int_fetch_and_add_full(volatile unsigned int *p, unsigned int incr) } # define AO_HAVE_short_fetch_and_add_full +#endif /* _MSC_VER < 1800 && AO_ASM_X64_AVAILABLE */ + +#ifdef AO_ASM_X64_AVAILABLE + /* As far as we can tell, the lfence and sfence instructions are not */ /* currently needed or useful for cached memory accesses. */ @@ -159,6 +277,8 @@ AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, AO_t new_val1, AO_t new_val2) { __int64 comparandResult[2]; + + assert(((size_t)addr & (sizeof(AO_double_t) - 1)) == 0); comparandResult[0] = old_val1; /* low */ comparandResult[1] = old_val2; /* high */ return _InterlockedCompareExchange128((volatile __int64 *)addr, diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/standard_ao_double_t.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/standard_ao_double_t.h index bf76979a1..630c3762b 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/standard_ao_double_t.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/standard_ao_double_t.h @@ -20,20 +20,38 @@ * SOFTWARE. */ -/* For 64-bit systems, we extend the double type to hold two int64's. */ -/* x86-64 (except for x32): __m128 serves as a placeholder which also */ -/* requires the compiler to align it on 16-byte boundary (as required */ -/* by cmpxchg16). */ -/* Similar things could be done for PPC 64-bit using a VMX data type. */ +/* For 64-bit systems, we expect the double type to hold two int64's. */ -#if ((defined(__x86_64__) && __GNUC__ >= 4) || defined(_WIN64)) \ - && !defined(__ILP32__) +#if ((defined(__x86_64__) && defined(AO_GCC_ATOMIC_TEST_AND_SET)) \ + || defined(__aarch64__)) && !defined(__ILP32__) + /* x86-64: __m128 is not applicable to atomic intrinsics. */ +# if AO_GNUC_PREREQ(4, 7) || AO_CLANG_PREREQ(3, 6) +# pragma GCC diagnostic push + /* Suppress warning about __int128 type. */ +# if defined(__clang__) || AO_GNUC_PREREQ(6, 4) +# pragma GCC diagnostic ignored "-Wpedantic" +# else + /* GCC before ~4.8 does not accept "-Wpedantic" quietly. */ +# pragma GCC diagnostic ignored "-pedantic" +# endif + typedef unsigned __int128 double_ptr_storage; +# pragma GCC diagnostic pop +# else /* pragma diagnostic is not supported */ + typedef unsigned __int128 double_ptr_storage; +# endif +#elif ((defined(__x86_64__) && AO_GNUC_PREREQ(4, 0)) || defined(_WIN64)) \ + && !defined(__ILP32__) + /* x86-64 (except for x32): __m128 serves as a placeholder which also */ + /* requires the compiler to align it on 16-byte boundary (as required */ + /* by cmpxchg16b). */ + /* Similar things could be done for PPC 64-bit using a VMX data type. */ # include typedef __m128 double_ptr_storage; #elif defined(_WIN32) && !defined(__GNUC__) typedef unsigned __int64 double_ptr_storage; -#elif defined(__aarch64__) - typedef unsigned __int128 double_ptr_storage; +#elif defined(__i386__) && defined(__GNUC__) + typedef unsigned long long double_ptr_storage + __attribute__((__aligned__(8))); #else typedef unsigned long long double_ptr_storage; #endif @@ -51,6 +69,11 @@ typedef union { } AO_double_t; #define AO_HAVE_double_t +/* Note: AO_double_t volatile variables are not intended to be local */ +/* ones (at least those which are passed to AO double-wide primitives */ +/* as the first argument), otherwise it is the client responsibility to */ +/* ensure they have double-word alignment. */ + /* Dummy declaration as a compile-time assertion for AO_double_t size. */ struct AO_double_t_size_static_assert { char dummy[sizeof(AO_double_t) == 2 * sizeof(AO_t) ? 1 : -1]; diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/sunc/sparc.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/sunc/sparc.h index 298881f53..5530fd0ee 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/sunc/sparc.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/sunc/sparc.h @@ -28,9 +28,17 @@ /* Test_and_set location is just a byte. */ #include "../test_and_set_t_is_char.h" +#ifdef __cplusplus + extern "C" { +#endif + extern AO_TS_VAL_t AO_test_and_set_full(volatile AO_TS_t *addr); /* Implemented in separate .S file, for now. */ #define AO_HAVE_test_and_set_full /* TODO: Like the gcc version, extend this for V8 and V9. */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/sunc/x86.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/sunc/x86.h index a3cb922fe..88c6a7844 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/sunc/x86.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/sunc/x86.h @@ -2,7 +2,7 @@ * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved. - * + * Copyright (c) 2009-2016 Ivan Maidanski * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. @@ -87,7 +87,6 @@ AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr) #define AO_HAVE_short_fetch_and_add_full #ifndef AO_PREFER_GENERALIZED - /* Really only works for 486 and later */ AO_INLINE void AO_and_full (volatile AO_t *p, AO_t value) { diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/test_and_set_t_is_char.h b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/test_and_set_t_is_char.h index 8e265aa9c..9eb250ccd 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/test_and_set_t_is_char.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops/sysdeps/test_and_set_t_is_char.h @@ -23,13 +23,29 @@ /* * These are common definitions for architectures on which test_and_set * operates on byte sized quantities, the "clear" value contains - * all zeroes, and the "set" value contains all ones. + * all zeroes, and the "set" value contains all ones typically. */ -#define AO_TS_t unsigned char -typedef enum {AO_BYTE_TS_clear = 0, AO_BYTE_TS_set = 0xff} AO_BYTE_TS_val; +#ifndef AO_GCC_ATOMIC_TEST_AND_SET +# define AO_TS_SET_TRUEVAL 0xff +#elif defined(__GCC_ATOMIC_TEST_AND_SET_TRUEVAL) \ + && !defined(AO_PREFER_GENERALIZED) +# define AO_TS_SET_TRUEVAL __GCC_ATOMIC_TEST_AND_SET_TRUEVAL +#else +# define AO_TS_SET_TRUEVAL 1 /* true */ +#endif + +typedef enum { + AO_BYTE_TS_clear = 0, + AO_BYTE_TS_set = AO_TS_SET_TRUEVAL +} AO_BYTE_TS_val; + #define AO_TS_VAL_t AO_BYTE_TS_val #define AO_TS_CLEAR AO_BYTE_TS_clear #define AO_TS_SET AO_BYTE_TS_set +#define AO_TS_t unsigned char + #define AO_CHAR_TS_T 1 + +#undef AO_TS_SET_TRUEVAL diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops_malloc.c b/src/bdwgc/libatomic_ops/src/atomic_ops_malloc.c index 60757cfe9..7e4bbb3f0 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops_malloc.c +++ b/src/bdwgc/libatomic_ops/src/atomic_ops_malloc.c @@ -15,6 +15,10 @@ # include "config.h" #endif +#ifdef DONT_USE_MMAP /* for testing */ +# undef HAVE_MMAP +#endif + #define AO_REQUIRE_CAS #include "atomic_ops_malloc.h" @@ -27,7 +31,20 @@ # include #endif -#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(abort) +#if defined(AO_ADDRESS_SANITIZER) && !defined(AO_NO_MALLOC_POISON) + /* #include "sanitizer/asan_interface.h" */ + void __asan_poison_memory_region(void *, size_t); + void __asan_unpoison_memory_region(void *, size_t); +# define ASAN_POISON_MEMORY_REGION(addr, size) \ + __asan_poison_memory_region(addr, size) +# define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ + __asan_unpoison_memory_region(addr, size) +#else +# define ASAN_POISON_MEMORY_REGION(addr, size) (void)0 +# define ASAN_UNPOISON_MEMORY_REGION(addr, size) (void)0 +#endif /* !AO_ADDRESS_SANITIZER */ + +#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(AO_HAVE_abort) # define abort() _exit(-1) /* there is no abort() in WinCE */ #endif @@ -85,12 +102,15 @@ static volatile AO_t initial_heap_ptr = (AO_t)AO_initial_heap; #endif #ifdef USE_MMAP_ANON -# ifdef MAP_ANONYMOUS +# if defined(CPPCHECK) +# define OPT_MAP_ANON 0x20 /* taken from linux */ +# elif defined(MAP_ANONYMOUS) # define OPT_MAP_ANON MAP_ANONYMOUS # else # define OPT_MAP_ANON MAP_ANON # endif #else +# include /* for close() */ # define OPT_MAP_ANON 0 #endif @@ -125,31 +145,48 @@ static char *get_mmaped(size_t sz) if (zero_fd == -1) return 0; # endif - result = mmap(0, sz, PROT_READ | PROT_WRITE, - GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0/* offset */); + result = (char *)mmap(0, sz, PROT_READ | PROT_WRITE, + GC_MMAP_FLAGS | OPT_MAP_ANON, + zero_fd, 0 /* offset */); # ifndef USE_MMAP_ANON close(zero_fd); # endif - if (result == MAP_FAILED) - result = 0; + if (AO_EXPECT_FALSE(result == MAP_FAILED)) + result = NULL; return result; } +#ifndef SIZE_MAX +# include +#endif +#if defined(SIZE_MAX) && !defined(CPPCHECK) +# define AO_SIZE_MAX ((size_t)SIZE_MAX) + /* Extra cast to workaround some buggy SIZE_MAX definitions. */ +#else +# define AO_SIZE_MAX (~(size_t)0) +#endif + +/* Saturated addition of size_t values. Used to avoid value wrap */ +/* around on overflow. The arguments should have no side effects. */ +#define SIZET_SAT_ADD(a, b) \ + (AO_EXPECT_FALSE((a) >= AO_SIZE_MAX - (b)) ? AO_SIZE_MAX : (a) + (b)) + /* Allocate an object of size (incl. header) of size > CHUNK_SIZE. */ /* sz includes space for an AO_t-sized header. */ static char * AO_malloc_large(size_t sz) { - char * result; - /* The header will force us to waste ALIGNMENT bytes, incl. header. */ - sz += ALIGNMENT; - /* Round to multiple of CHUNK_SIZE. */ - sz = (sz + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); - result = get_mmaped(sz); - if (result == 0) return 0; - result += ALIGNMENT; - ((AO_t *)result)[-1] = (AO_t)sz; - return result; + char *result; + /* The header will force us to waste ALIGNMENT bytes, incl. header. */ + /* Round to multiple of CHUNK_SIZE. */ + sz = SIZET_SAT_ADD(sz, ALIGNMENT + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1); + assert(sz > LOG_MAX_SIZE); + result = get_mmaped(sz); + if (AO_EXPECT_FALSE(NULL == result)) + return NULL; + result += ALIGNMENT; + ((AO_t *)result)[-1] = (AO_t)sz; + return result; } static void @@ -192,7 +229,8 @@ get_chunk(void) (AO_t)initial_ptr, (AO_t)my_chunk_ptr); } - if (my_chunk_ptr - AO_initial_heap > AO_INITIAL_HEAP_SIZE - CHUNK_SIZE) + if (AO_EXPECT_FALSE(my_chunk_ptr - AO_initial_heap + > AO_INITIAL_HEAP_SIZE - CHUNK_SIZE)) break; if (AO_compare_and_swap(&initial_heap_ptr, (AO_t)my_chunk_ptr, (AO_t)(my_chunk_ptr + CHUNK_SIZE))) { @@ -220,29 +258,46 @@ static void add_chunk_as(void * chunk, unsigned log_sz) assert (CHUNK_SIZE >= sz); limit = (size_t)CHUNK_SIZE - sz; for (ofs = ALIGNMENT - sizeof(AO_t); ofs <= limit; ofs += sz) { + ASAN_POISON_MEMORY_REGION((char *)chunk + ofs + sizeof(AO_t), + sz - sizeof(AO_t)); AO_stack_push(&AO_free_list[log_sz], (AO_t *)((char *)chunk + ofs)); } } -static const int msbs[16] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4}; +static const unsigned char msbs[16] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 +}; /* Return the position of the most significant set bit in the */ /* argument. */ /* We follow the conventions of ffs(), i.e. the least */ /* significant bit is number one. */ -static int msb(size_t s) +static unsigned msb(size_t s) { - int result = 0; - int v; + unsigned result = 0; if ((s & 0xff) != s) { - /* The following is a tricky code ought to be equivalent to */ - /* "(v = s >> 32) != 0" but suppresses warnings on 32-bit arch's. */ - if (sizeof(size_t) > 4 && (v = s >> (sizeof(size_t) > 4 ? 32 : 0)) != 0) - { - s = v; - result += 32; - } - if ((s >> 16) != 0) +# if (__SIZEOF_SIZE_T__ == 8) && !defined(CPPCHECK) + unsigned v = (unsigned)(s >> 32); + if (AO_EXPECT_FALSE(v != 0)) + { + s = v; + result += 32; + } +# elif __SIZEOF_SIZE_T__ == 4 + /* No op. */ +# else + unsigned v; + /* The following is a tricky code ought to be equivalent to */ + /* "(v = s >> 32) != 0" but suppresses warnings on 32-bit arch's. */ +# define SIZEOF_SIZE_T_GT_4 (sizeof(size_t) > 4) + if (SIZEOF_SIZE_T_GT_4 + && (v = (unsigned)(s >> (SIZEOF_SIZE_T_GT_4 ? 32 : 0))) != 0) + { + s = v; + result += 32; + } +# endif /* !defined(__SIZEOF_SIZE_T__) */ + if (AO_EXPECT_FALSE((s >> 16) != 0)) { s >>= 16; result += 16; @@ -266,40 +321,50 @@ void * AO_malloc(size_t sz) { AO_t *result; - int log_sz; + unsigned log_sz; - if (sz > CHUNK_SIZE) + if (AO_EXPECT_FALSE(sz > CHUNK_SIZE - sizeof(AO_t))) return AO_malloc_large(sz); log_sz = msb(sz + (sizeof(AO_t) - 1)); + assert(log_sz <= LOG_MAX_SIZE); + assert(((size_t)1 << log_sz) >= sz + sizeof(AO_t)); result = AO_stack_pop(AO_free_list+log_sz); - while (0 == result) { + while (AO_EXPECT_FALSE(NULL == result)) { void * chunk = get_chunk(); - if (0 == chunk) return 0; + + if (AO_EXPECT_FALSE(NULL == chunk)) + return NULL; add_chunk_as(chunk, log_sz); result = AO_stack_pop(AO_free_list+log_sz); } *result = log_sz; # ifdef AO_TRACE_MALLOC - fprintf(stderr, "%x: AO_malloc(%lu) = %p\n", - (int)pthread_self(), (unsigned long)sz, result+1); + fprintf(stderr, "%p: AO_malloc(%lu) = %p\n", + (void *)pthread_self(), (unsigned long)sz, (void *)(result + 1)); # endif + ASAN_UNPOISON_MEMORY_REGION(result + 1, sz); return result + 1; } void AO_free(void *p) { - char *base = (char *)p - sizeof(AO_t); + AO_t *base; int log_sz; - if (0 == p) return; - log_sz = (int)(*(AO_t *)base); + if (AO_EXPECT_FALSE(NULL == p)) + return; + + base = (AO_t *)p - 1; + log_sz = (int)(*base); # ifdef AO_TRACE_MALLOC - fprintf(stderr, "%x: AO_free(%p sz:%lu)\n", (int)pthread_self(), p, - (unsigned long)(log_sz > LOG_MAX_SIZE? log_sz : (1 << log_sz))); + fprintf(stderr, "%p: AO_free(%p sz:%lu)\n", (void *)pthread_self(), p, + log_sz > LOG_MAX_SIZE ? (unsigned)log_sz : 1UL << log_sz); # endif - if (log_sz > LOG_MAX_SIZE) - AO_free_large(p); - else - AO_stack_push(AO_free_list+log_sz, (AO_t *)base); + if (AO_EXPECT_FALSE(log_sz > LOG_MAX_SIZE)) { + AO_free_large((char *)p); + } else { + ASAN_POISON_MEMORY_REGION(base + 1, ((size_t)1 << log_sz) - sizeof(AO_t)); + AO_stack_push(AO_free_list + log_sz, base); + } } diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops_malloc.h b/src/bdwgc/libatomic_ops/src/atomic_ops_malloc.h index e324d5b37..f9ed90011 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops_malloc.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops_malloc.h @@ -30,15 +30,52 @@ #include /* for size_t */ +#ifdef __cplusplus + extern "C" { +#endif + #ifdef AO_STACK_IS_LOCK_FREE # define AO_MALLOC_IS_LOCK_FREE #endif +#ifndef AO_ATTR_MALLOC +# if AO_GNUC_PREREQ(3, 1) +# define AO_ATTR_MALLOC __attribute__((__malloc__)) +# elif defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(__EDG__) +# define AO_ATTR_MALLOC \ + __declspec(allocator) __declspec(noalias) __declspec(restrict) +# elif defined(_MSC_VER) && _MSC_VER >= 1400 +# define AO_ATTR_MALLOC __declspec(noalias) __declspec(restrict) +# else +# define AO_ATTR_MALLOC /* empty */ +# endif +#endif + +#ifndef AO_ATTR_ALLOC_SIZE +# ifdef __clang__ +# if __has_attribute(__alloc_size__) +# define AO_ATTR_ALLOC_SIZE(argnum) \ + __attribute__((__alloc_size__(argnum))) +# else +# define AO_ATTR_ALLOC_SIZE(argnum) /* empty */ +# endif +# elif AO_GNUC_PREREQ(4, 3) && !defined(__ICC) +# define AO_ATTR_ALLOC_SIZE(argnum) __attribute__((__alloc_size__(argnum))) +# else +# define AO_ATTR_ALLOC_SIZE(argnum) /* empty */ +# endif +#endif + void AO_free(void *); +AO_ATTR_MALLOC AO_ATTR_ALLOC_SIZE(1) void * AO_malloc(size_t); /* Allow use of mmap to grow the heap. No-op on some platforms. */ void AO_malloc_enable_mmap(void); +#ifdef __cplusplus + } /* extern "C" */ +#endif + #endif /* !AO_MALLOC_H */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops_stack.c b/src/bdwgc/libatomic_ops/src/atomic_ops_stack.c index 642bac0eb..6008b8912 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops_stack.c +++ b/src/bdwgc/libatomic_ops/src/atomic_ops_stack.c @@ -22,6 +22,18 @@ #define AO_REQUIRE_CAS #include "atomic_ops_stack.h" +/* This function call must be a part of a do-while loop with a CAS */ +/* designating the condition of the loop (see the use cases below). */ +#ifdef AO_THREAD_SANITIZER + AO_ATTR_NO_SANITIZE_THREAD + static void store_before_cas(AO_t *addr, AO_t value) + { + *addr = value; + } +#else +# define store_before_cas(addr, value) (void)(*(addr) = (value)) +#endif + #ifdef AO_USE_ALMOST_LOCK_FREE void AO_pause(int); /* defined in atomic_ops.c */ @@ -46,9 +58,8 @@ /* to be inserted. */ /* Both list headers and link fields contain "perturbed" pointers, i.e. */ /* pointers with extra bits "or"ed into the low order bits. */ -void -AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x, - AO_stack_aux *a) +void AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x, + AO_stack_aux *a) { AO_t x_bits = (AO_t)x; AO_t next; @@ -59,8 +70,8 @@ AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x, # if AO_BL_SIZE == 2 { /* Start all loads as close to concurrently as possible. */ - AO_t entry1 = AO_load(a -> AO_stack_bl); - AO_t entry2 = AO_load(a -> AO_stack_bl + 1); + AO_t entry1 = AO_load(&a->AO_stack_bl[0]); + AO_t entry2 = AO_load(&a->AO_stack_bl[1]); if (entry1 == x_bits || entry2 == x_bits) { /* Entry is currently being removed. Change it a little. */ @@ -77,7 +88,7 @@ AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x, int i; for (i = 0; i < AO_BL_SIZE; ++i) { - if (AO_load(a -> AO_stack_bl + i) == x_bits) + if (AO_load(&a->AO_stack_bl[i]) == x_bits) { /* Entry is currently being removed. Change it a little. */ ++x_bits; @@ -94,7 +105,7 @@ AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x, do { next = AO_load(list); - *x = next; + store_before_cas(x, next); } while (AO_EXPECT_FALSE(!AO_compare_and_swap_release(list, next, x_bits))); } @@ -115,6 +126,21 @@ AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x, # define PRECHECK(a) #endif +/* This function is used before CAS in the below AO_stack_pop() and the */ +/* data race (reported by TSan) is OK because it results in a retry. */ +#ifdef AO_THREAD_SANITIZER + AO_ATTR_NO_SANITIZE_THREAD + static AO_t AO_load_next(volatile AO_t *first_ptr) + { + /* Assuming an architecture on which loads of word type are atomic. */ + /* AO_load cannot be used here because it cannot be instructed to */ + /* suppress the warning about the race. */ + return *first_ptr; + } +#else +# define AO_load_next AO_load +#endif + AO_t * AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux * a) { @@ -143,7 +169,10 @@ AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux * a) } } assert(i < AO_BL_SIZE); - assert(a -> AO_stack_bl[i] == first); +# ifndef AO_THREAD_SANITIZER + assert(a -> AO_stack_bl[i] == first); + /* No actual race with the above CAS. */ +# endif /* First is on the auxiliary black list. It may be removed by */ /* another thread before we get to it, but a new insertion of x */ /* cannot be started here. */ @@ -152,18 +181,21 @@ AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux * a) /* list. Otherwise it's possible that a reinsertion of it was */ /* already started before we added the black list entry. */ # if defined(__alpha__) && (__GNUC__ == 4) - if (first != AO_load(list)) + if (first != AO_load_acquire(list)) /* Workaround __builtin_expect bug found in */ /* gcc-4.6.3/alpha causing test_stack failure. */ # else - if (AO_EXPECT_FALSE(first != AO_load(list))) + if (AO_EXPECT_FALSE(first != AO_load_acquire(list))) + /* Workaround test failure on AIX, at least, by */ + /* using acquire ordering semantics for this */ + /* load. Probably, it is not the right fix. */ # endif { AO_store_release(a->AO_stack_bl+i, 0); goto retry; } first_ptr = AO_REAL_NEXT_PTR(first); - next = AO_load(first_ptr); + next = AO_load_next(first_ptr); # if defined(__alpha__) && (__GNUC__ == 4) if (!AO_compare_and_swap_release(list, first, next)) # else @@ -173,7 +205,9 @@ AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux * a) AO_store_release(a->AO_stack_bl+i, 0); goto retry; } - assert(*list != first); +# ifndef AO_THREAD_SANITIZER + assert(*list != first); /* No actual race with the above CAS. */ +# endif /* Since we never insert an entry on the black list, this cannot have */ /* succeeded unless first remained on the list while we were running. */ /* Thus its next link cannot have changed out from under us, and we */ @@ -189,11 +223,38 @@ AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux * a) #else /* ! USE_ALMOST_LOCK_FREE */ +/* The functionality is the same as of AO_load_next but the atomicity */ +/* is not needed. The usage is similar to that of store_before_cas. */ +#if defined(AO_THREAD_SANITIZER) \ + && (defined(AO_HAVE_compare_and_swap_double) \ + || defined(AO_HAVE_compare_double_and_swap_double)) + /* TODO: If compiled by Clang (as of clang-4.0) with -O3 flag, */ + /* no_sanitize attribute is ignored unless the argument is volatile. */ +# if defined(__clang__) +# define LOAD_BEFORE_CAS_VOLATILE volatile +# else +# define LOAD_BEFORE_CAS_VOLATILE /* empty */ +# endif + AO_ATTR_NO_SANITIZE_THREAD + static AO_t load_before_cas(const LOAD_BEFORE_CAS_VOLATILE AO_t *addr) + { + return *addr; + } +#else +# define load_before_cas(addr) (*(addr)) +#endif + /* Better names for fields in AO_stack_t */ #define ptr AO_val2 #define version AO_val1 -#if defined(AO_HAVE_compare_double_and_swap_double) +#if defined(AO_HAVE_compare_double_and_swap_double) \ + && !(defined(AO_STACK_PREFER_CAS_DOUBLE) \ + && defined(AO_HAVE_compare_and_swap_double)) + +#ifdef LINT2 + volatile /* non-static */ AO_t AO_noop_sink; +#endif void AO_stack_push_release(AO_stack_t *list, AO_t *element) { @@ -201,18 +262,22 @@ void AO_stack_push_release(AO_stack_t *list, AO_t *element) do { next = AO_load(&(list -> ptr)); - *element = next; + store_before_cas(element, next); } while (AO_EXPECT_FALSE(!AO_compare_and_swap_release(&(list -> ptr), next, (AO_t)element))); /* This uses a narrow CAS here, an old optimization suggested */ /* by Treiber. Pop is still safe, since we run into the ABA */ /* problem only if there were both intervening "pop"s and "push"es. */ /* In that case we still see a change in the version number. */ +# ifdef LINT2 + /* Instruct static analyzer that element is not lost. */ + AO_noop_sink = (AO_t)element; +# endif } AO_t *AO_stack_pop_acquire(AO_stack_t *list) { -# ifdef __clang__ +# if defined(__clang__) && !AO_CLANG_PREREQ(3, 5) AO_t *volatile cptr; /* Use volatile to workaround a bug in */ /* clang-1.1/x86 causing test_stack failure. */ @@ -226,8 +291,9 @@ AO_t *AO_stack_pop_acquire(AO_stack_t *list) /* Version must be loaded first. */ cversion = AO_load_acquire(&(list -> version)); cptr = (AO_t *)AO_load(&(list -> ptr)); - if (cptr == 0) return 0; - next = *cptr; + if (NULL == cptr) + return NULL; + next = load_before_cas((AO_t *)cptr); } while (AO_EXPECT_FALSE(!AO_compare_double_and_swap_double_release(list, cversion, (AO_t)cptr, cversion+1, (AO_t)next))); @@ -238,8 +304,7 @@ AO_t *AO_stack_pop_acquire(AO_stack_t *list) #elif defined(AO_HAVE_compare_and_swap_double) /* Needed for future IA64 processors. No current clients? */ - -#error Untested! Probably doesnt work. +/* TODO: Not tested thoroughly. */ /* We have a wide CAS, but only does an AO_t-wide comparison. */ /* We can't use the Treiber optimization, since we only check */ @@ -247,13 +312,14 @@ AO_t *AO_stack_pop_acquire(AO_stack_t *list) void AO_stack_push_release(AO_stack_t *list, AO_t *element) { AO_t version; - AO_t next_ptr; do { + AO_t next_ptr; + /* Again version must be loaded first, for different reason. */ version = AO_load_acquire(&(list -> version)); next_ptr = AO_load(&(list -> ptr)); - *element = next_ptr; + store_before_cas(element, next_ptr); } while (!AO_compare_and_swap_double_release( list, version, version+1, (AO_t) element)); @@ -268,14 +334,15 @@ AO_t *AO_stack_pop_acquire(AO_stack_t *list) do { cversion = AO_load_acquire(&(list -> version)); cptr = (AO_t *)AO_load(&(list -> ptr)); - if (cptr == 0) return 0; - next = *cptr; - } while (!AO_compare_double_and_swap_double_release - (list, cversion, (AO_t) cptr, cversion+1, next)); + if (NULL == cptr) + return NULL; + next = load_before_cas(cptr); + } while (!AO_compare_double_and_swap_double_release(list, + cversion, (AO_t)cptr, + cversion+1, next)); return cptr; } - #endif /* AO_HAVE_compare_and_swap_double */ #endif /* ! USE_ALMOST_LOCK_FREE */ diff --git a/src/bdwgc/libatomic_ops/src/atomic_ops_stack.h b/src/bdwgc/libatomic_ops/src/atomic_ops_stack.h index 1ca5f406e..345ae21c0 100644 --- a/src/bdwgc/libatomic_ops/src/atomic_ops_stack.h +++ b/src/bdwgc/libatomic_ops/src/atomic_ops_stack.h @@ -31,9 +31,16 @@ #include "atomic_ops.h" -#if !defined(AO_HAVE_compare_double_and_swap_double) \ - && !defined(AO_HAVE_compare_double_and_swap) \ - && defined(AO_HAVE_compare_and_swap) +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef AO_USE_ALMOST_LOCK_FREE + /* Use the almost-non-blocking implementation regardless of the */ + /* double-word CAS availability. */ +#elif !defined(AO_HAVE_compare_double_and_swap_double) \ + && !defined(AO_HAVE_compare_double_and_swap) \ + && defined(AO_HAVE_compare_and_swap) # define AO_USE_ALMOST_LOCK_FREE #else /* If we have no compare-and-swap operation defined, we assume */ @@ -98,7 +105,7 @@ typedef struct AO__stack_aux { /* link fields in nodes, and nothing about the rest of the */ /* stack elements. Link fields hold an AO_t, which is not */ /* necessarily a real pointer. This converts the AO_t to a */ -/* real (AO_t *) which is either o, or points at the link */ +/* real (AO_t *) which is either NULL, or points at the link */ /* field in the next node. */ #define AO_REAL_NEXT_PTR(x) (AO_t *)((x) & ~AO_BIT_MASK) @@ -151,11 +158,20 @@ AO_INLINE void AO_stack_init(AO_stack_t *list) #ifndef AO_HAVE_double_t /* Can happen if we're using CAS emulation, since we don't want to */ /* force that here, in case other atomic_ops clients don't want it. */ +# ifdef __cplusplus + } /* extern "C" */ +# endif # include "atomic_ops/sysdeps/standard_ao_double_t.h" +# ifdef __cplusplus + extern "C" { +# endif #endif typedef volatile AO_double_t AO_stack_t; /* AO_val1 is version, AO_val2 is pointer. */ +/* Note: AO_stack_t variables are not intended to be local ones, */ +/* otherwise it is the client responsibility to ensure they have */ +/* double-word alignment. */ #define AO_STACK_INITIALIZER AO_DOUBLE_T_INITIALIZER @@ -185,4 +201,8 @@ AO_t * AO_stack_pop_acquire(AO_stack_t *list); # define AO_HAVE_stack_pop #endif +#ifdef __cplusplus + } /* extern "C" */ +#endif + #endif /* !AO_STACK_H */ diff --git a/src/bdwgc/libatomic_ops/src/config.h.in b/src/bdwgc/libatomic_ops/src/config.h.in index aa784def5..f3c684f47 100644 --- a/src/bdwgc/libatomic_ops/src/config.h.in +++ b/src/bdwgc/libatomic_ops/src/config.h.in @@ -1,18 +1,17 @@ /* src/config.h.in. Generated from configure.ac by autoheader. */ -/* Inline assembly avalable (only VC/x86_64) */ +/* Inline assembly available (only VC/x86_64) */ #undef AO_ASM_X64_AVAILABLE /* Assume Windows Server 2003, Vista or later target (only VC/x86) */ #undef AO_ASSUME_VISTA -/* Assume hardware compare-and-swap functionality available on target (only - VC/x86) */ -#undef AO_ASSUME_WINDOWS98 - /* Assume target is not old AMD Opteron chip (only x86_64) */ #undef AO_CMPXCHG16B_AVAILABLE +/* Define to avoid C11 atomic intrinsics even if available. */ +#undef AO_DISABLE_GCC_ATOMICS + /* Force test_and_set to use SWP instruction instead of LDREX/STREX (only arm v6+) */ #undef AO_FORCE_USE_SWP @@ -29,6 +28,11 @@ /* Assume ancient MS VS Win32 headers (only VC/arm v6+, VC/x86) */ #undef AO_OLD_STYLE_INTERLOCKED_COMPARE_EXCHANGE +/* Prefer C11 atomic intrinsics over assembly-based implementation even in + case of inefficient implementation (do not use assembly for any atomic_ops + primitive if C11/GCC atomic intrinsics available) */ +#undef AO_PREFER_BUILTIN_ATOMICS + /* Prefer generalized definitions to direct assembly-based ones */ #undef AO_PREFER_GENERALIZED diff --git a/src/bdwgc/libatomic_ops/test-driver b/src/bdwgc/libatomic_ops/test-driver new file mode 100755 index 000000000..8e575b017 --- /dev/null +++ b/src/bdwgc/libatomic_ops/test-driver @@ -0,0 +1,148 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2013-07-13.22; # UTC + +# Copyright (C) 2011-2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/src/bdwgc/libatomic_ops/tests/Makefile.am b/src/bdwgc/libatomic_ops/tests/Makefile.am index c8812bba5..ced8fa756 100644 --- a/src/bdwgc/libatomic_ops/tests/Makefile.am +++ b/src/bdwgc/libatomic_ops/tests/Makefile.am @@ -10,20 +10,32 @@ AM_CPPFLAGS = \ -I$(top_builddir)/src -I$(top_srcdir)/src \ -I$(top_builddir)/tests -I$(top_srcdir)/tests +CFLAGS += $(CFLAGS_EXTRA) + +TESTS = test_atomic$(EXEEXT) test_atomic_generalized$(EXEEXT) \ + test_stack$(EXEEXT) test_malloc$(EXEEXT) +TEST_OBJS = test_atomic.o test_atomic_generalized-test_atomic.o \ + test_stack.o test_malloc.o +check_PROGRAMS = test_atomic test_atomic_generalized \ + test_stack test_malloc + if HAVE_PTHREAD_H -TESTS=test_atomic test_atomic_pthreads test_stack test_malloc +TESTS += test_atomic_pthreads$(EXEEXT) +TEST_OBJS += test_atomic_pthreads-test_atomic.o +check_PROGRAMS += test_atomic_pthreads test_atomic_pthreads_SOURCES=$(test_atomic_SOURCES) test_atomic_pthreads_CPPFLAGS=-DAO_USE_PTHREAD_DEFS $(AM_CPPFLAGS) test_atomic_pthreads_LDADD=$(test_atomic_LDADD) -else -TESTS=test_atomic test_stack test_malloc endif -check_PROGRAMS=$(TESTS) - test_atomic_SOURCES=test_atomic.c test_atomic_LDADD = $(THREADDLLIBS) $(top_builddir)/src/libatomic_ops.la +test_atomic_generalized_SOURCES=$(test_atomic_SOURCES) +test_atomic_generalized_CPPFLAGS= \ + -DAO_PREFER_GENERALIZED -DAO_TEST_EMULATION $(AM_CPPFLAGS) +test_atomic_generalized_LDADD=$(test_atomic_LDADD) + test_stack_SOURCES=test_stack.c test_stack_LDADD = $(THREADDLLIBS) \ $(top_builddir)/src/libatomic_ops_gpl.la \ @@ -34,6 +46,16 @@ test_malloc_LDADD = $(THREADDLLIBS) \ $(top_builddir)/src/libatomic_ops_gpl.la \ $(top_builddir)/src/libatomic_ops.la +# Run the tests directly (without test-driver): +.PHONY: check-without-test-driver +check-without-test-driver: $(TESTS) + @echo "The following will print some 'Missing ...' messages" + ./test_atomic$(EXEEXT) + ./test_atomic_generalized$(EXEEXT) + ./test_stack$(EXEEXT) + ./test_malloc$(EXEEXT) + test ! -f test_atomic_pthreads$(EXEEXT) || ./test_atomic_pthreads$(EXEEXT) + test_atomic_include.h: test_atomic_include.template mkdir -p `dirname $@` sed -e s:XX::g $? > $@ @@ -44,6 +66,7 @@ test_atomic_include.h: test_atomic_include.template sed -e s:XX:_full:g $? >> $@ sed -e s:XX:_release_write:g $? >> $@ sed -e s:XX:_acquire_read:g $? >> $@ + sed -e s:XX:_dd_acquire_read:g $? >> $@ list_atomic.c: list_atomic.template mkdir -p `dirname $@` @@ -101,3 +124,6 @@ list_atomic.i: list_atomic.c # Verify list_atomic.c syntax: list_atomic.o: list_atomic.c $(COMPILE) -c -o $@ $? + +# Just compile all tests (without linking and execution): +check-nolink-local: $(TEST_OBJS) diff --git a/src/bdwgc/libatomic_ops/tests/Makefile.in b/src/bdwgc/libatomic_ops/tests/Makefile.in index 5efc67c9d..52828d0b9 100644 --- a/src/bdwgc/libatomic_ops/tests/Makefile.in +++ b/src/bdwgc/libatomic_ops/tests/Makefile.in @@ -88,12 +88,11 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -@HAVE_PTHREAD_H_FALSE@TESTS = test_atomic$(EXEEXT) test_stack$(EXEEXT) \ -@HAVE_PTHREAD_H_FALSE@ test_malloc$(EXEEXT) -@HAVE_PTHREAD_H_TRUE@TESTS = test_atomic$(EXEEXT) \ -@HAVE_PTHREAD_H_TRUE@ test_atomic_pthreads$(EXEEXT) \ -@HAVE_PTHREAD_H_TRUE@ test_stack$(EXEEXT) test_malloc$(EXEEXT) -check_PROGRAMS = $(am__EXEEXT_1) +check_PROGRAMS = test_atomic$(EXEEXT) test_atomic_generalized$(EXEEXT) \ + test_stack$(EXEEXT) test_malloc$(EXEEXT) $(am__EXEEXT_1) +@HAVE_PTHREAD_H_TRUE@am__append_1 = test_atomic_pthreads$(EXEEXT) +@HAVE_PTHREAD_H_TRUE@am__append_2 = test_atomic_pthreads-test_atomic.o +@HAVE_PTHREAD_H_TRUE@am__append_3 = test_atomic_pthreads subdir = tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ @@ -107,11 +106,7 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -@HAVE_PTHREAD_H_FALSE@am__EXEEXT_1 = test_atomic$(EXEEXT) \ -@HAVE_PTHREAD_H_FALSE@ test_stack$(EXEEXT) test_malloc$(EXEEXT) -@HAVE_PTHREAD_H_TRUE@am__EXEEXT_1 = test_atomic$(EXEEXT) \ -@HAVE_PTHREAD_H_TRUE@ test_atomic_pthreads$(EXEEXT) \ -@HAVE_PTHREAD_H_TRUE@ test_stack$(EXEEXT) test_malloc$(EXEEXT) +@HAVE_PTHREAD_H_TRUE@am__EXEEXT_1 = test_atomic_pthreads$(EXEEXT) am_test_atomic_OBJECTS = test_atomic.$(OBJEXT) test_atomic_OBJECTS = $(am_test_atomic_OBJECTS) am__DEPENDENCIES_1 = @@ -121,13 +116,18 @@ AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -am__test_atomic_pthreads_SOURCES_DIST = test_atomic.c -am__objects_1 = test_atomic_pthreads-test_atomic.$(OBJEXT) -@HAVE_PTHREAD_H_TRUE@am_test_atomic_pthreads_OBJECTS = \ -@HAVE_PTHREAD_H_TRUE@ $(am__objects_1) -test_atomic_pthreads_OBJECTS = $(am_test_atomic_pthreads_OBJECTS) +am__objects_1 = test_atomic_generalized-test_atomic.$(OBJEXT) +am_test_atomic_generalized_OBJECTS = $(am__objects_1) +test_atomic_generalized_OBJECTS = \ + $(am_test_atomic_generalized_OBJECTS) am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ $(top_builddir)/src/libatomic_ops.la +test_atomic_generalized_DEPENDENCIES = $(am__DEPENDENCIES_2) +am__test_atomic_pthreads_SOURCES_DIST = test_atomic.c +am__objects_2 = test_atomic_pthreads-test_atomic.$(OBJEXT) +@HAVE_PTHREAD_H_TRUE@am_test_atomic_pthreads_OBJECTS = \ +@HAVE_PTHREAD_H_TRUE@ $(am__objects_2) +test_atomic_pthreads_OBJECTS = $(am_test_atomic_pthreads_OBJECTS) @HAVE_PTHREAD_H_TRUE@test_atomic_pthreads_DEPENDENCIES = \ @HAVE_PTHREAD_H_TRUE@ $(am__DEPENDENCIES_2) am_test_malloc_OBJECTS = test_malloc.$(OBJEXT) @@ -153,7 +153,7 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -depcomp = $(SHELL) $(top_srcdir)/../depcomp +depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ @@ -174,9 +174,11 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(test_atomic_SOURCES) $(test_atomic_pthreads_SOURCES) \ - $(test_malloc_SOURCES) $(test_stack_SOURCES) +SOURCES = $(test_atomic_SOURCES) $(test_atomic_generalized_SOURCES) \ + $(test_atomic_pthreads_SOURCES) $(test_malloc_SOURCES) \ + $(test_stack_SOURCES) DIST_SOURCES = $(test_atomic_SOURCES) \ + $(test_atomic_generalized_SOURCES) \ $(am__test_atomic_pthreads_SOURCES_DIST) \ $(test_malloc_SOURCES) $(test_stack_SOURCES) am__can_run_installinfo = \ @@ -389,7 +391,7 @@ RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test -LOG_DRIVER = $(SHELL) $(top_srcdir)/../test-driver +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ @@ -404,11 +406,11 @@ am__set_b = \ am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) -TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/../test-driver +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) -am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/../depcomp \ - $(top_srcdir)/../test-driver +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -423,7 +425,8 @@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ $(CFLAGS_EXTRA) +CFLAGS_EXTRA = @CFLAGS_EXTRA@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -546,11 +549,20 @@ AM_CPPFLAGS = \ -I$(top_builddir)/src -I$(top_srcdir)/src \ -I$(top_builddir)/tests -I$(top_srcdir)/tests +TESTS = test_atomic$(EXEEXT) test_atomic_generalized$(EXEEXT) \ + test_stack$(EXEEXT) test_malloc$(EXEEXT) $(am__append_1) +TEST_OBJS = test_atomic.o test_atomic_generalized-test_atomic.o \ + test_stack.o test_malloc.o $(am__append_2) @HAVE_PTHREAD_H_TRUE@test_atomic_pthreads_SOURCES = $(test_atomic_SOURCES) @HAVE_PTHREAD_H_TRUE@test_atomic_pthreads_CPPFLAGS = -DAO_USE_PTHREAD_DEFS $(AM_CPPFLAGS) @HAVE_PTHREAD_H_TRUE@test_atomic_pthreads_LDADD = $(test_atomic_LDADD) test_atomic_SOURCES = test_atomic.c test_atomic_LDADD = $(THREADDLLIBS) $(top_builddir)/src/libatomic_ops.la +test_atomic_generalized_SOURCES = $(test_atomic_SOURCES) +test_atomic_generalized_CPPFLAGS = \ + -DAO_PREFER_GENERALIZED -DAO_TEST_EMULATION $(AM_CPPFLAGS) + +test_atomic_generalized_LDADD = $(test_atomic_LDADD) test_stack_SOURCES = test_stack.c test_stack_LDADD = $(THREADDLLIBS) \ $(top_builddir)/src/libatomic_ops_gpl.la \ @@ -609,6 +621,10 @@ test_atomic$(EXEEXT): $(test_atomic_OBJECTS) $(test_atomic_DEPENDENCIES) $(EXTRA @rm -f test_atomic$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_atomic_OBJECTS) $(test_atomic_LDADD) $(LIBS) +test_atomic_generalized$(EXEEXT): $(test_atomic_generalized_OBJECTS) $(test_atomic_generalized_DEPENDENCIES) $(EXTRA_test_atomic_generalized_DEPENDENCIES) + @rm -f test_atomic_generalized$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_atomic_generalized_OBJECTS) $(test_atomic_generalized_LDADD) $(LIBS) + test_atomic_pthreads$(EXEEXT): $(test_atomic_pthreads_OBJECTS) $(test_atomic_pthreads_DEPENDENCIES) $(EXTRA_test_atomic_pthreads_DEPENDENCIES) @rm -f test_atomic_pthreads$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_atomic_pthreads_OBJECTS) $(test_atomic_pthreads_LDADD) $(LIBS) @@ -628,6 +644,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_atomic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_atomic_generalized-test_atomic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_atomic_pthreads-test_atomic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_malloc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_stack.Po@am__quote@ @@ -653,6 +670,20 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< +test_atomic_generalized-test_atomic.o: test_atomic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_atomic_generalized_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_atomic_generalized-test_atomic.o -MD -MP -MF $(DEPDIR)/test_atomic_generalized-test_atomic.Tpo -c -o test_atomic_generalized-test_atomic.o `test -f 'test_atomic.c' || echo '$(srcdir)/'`test_atomic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_atomic_generalized-test_atomic.Tpo $(DEPDIR)/test_atomic_generalized-test_atomic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_atomic.c' object='test_atomic_generalized-test_atomic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_atomic_generalized_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_atomic_generalized-test_atomic.o `test -f 'test_atomic.c' || echo '$(srcdir)/'`test_atomic.c + +test_atomic_generalized-test_atomic.obj: test_atomic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_atomic_generalized_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_atomic_generalized-test_atomic.obj -MD -MP -MF $(DEPDIR)/test_atomic_generalized-test_atomic.Tpo -c -o test_atomic_generalized-test_atomic.obj `if test -f 'test_atomic.c'; then $(CYGPATH_W) 'test_atomic.c'; else $(CYGPATH_W) '$(srcdir)/test_atomic.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_atomic_generalized-test_atomic.Tpo $(DEPDIR)/test_atomic_generalized-test_atomic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_atomic.c' object='test_atomic_generalized-test_atomic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_atomic_generalized_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_atomic_generalized-test_atomic.obj `if test -f 'test_atomic.c'; then $(CYGPATH_W) 'test_atomic.c'; else $(CYGPATH_W) '$(srcdir)/test_atomic.c'; fi` + test_atomic_pthreads-test_atomic.o: test_atomic.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_atomic_pthreads_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_atomic_pthreads-test_atomic.o -MD -MP -MF $(DEPDIR)/test_atomic_pthreads-test_atomic.Tpo -c -o test_atomic_pthreads-test_atomic.o `test -f 'test_atomic.c' || echo '$(srcdir)/'`test_atomic.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_atomic_pthreads-test_atomic.Tpo $(DEPDIR)/test_atomic_pthreads-test_atomic.Po @@ -873,6 +904,13 @@ test_atomic.log: test_atomic$(EXEEXT) --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +test_atomic_generalized.log: test_atomic_generalized$(EXEEXT) + @p='test_atomic_generalized$(EXEEXT)'; \ + b='test_atomic_generalized'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) test_stack.log: test_stack$(EXEEXT) @p='test_stack$(EXEEXT)'; \ b='test_stack'; \ @@ -1072,6 +1110,16 @@ uninstall-am: .PRECIOUS: Makefile +# Run the tests directly (without test-driver): +.PHONY: check-without-test-driver +check-without-test-driver: $(TESTS) + @echo "The following will print some 'Missing ...' messages" + ./test_atomic$(EXEEXT) + ./test_atomic_generalized$(EXEEXT) + ./test_stack$(EXEEXT) + ./test_malloc$(EXEEXT) + test ! -f test_atomic_pthreads$(EXEEXT) || ./test_atomic_pthreads$(EXEEXT) + test_atomic_include.h: test_atomic_include.template mkdir -p `dirname $@` sed -e s:XX::g $? > $@ @@ -1082,6 +1130,7 @@ test_atomic_include.h: test_atomic_include.template sed -e s:XX:_full:g $? >> $@ sed -e s:XX:_release_write:g $? >> $@ sed -e s:XX:_acquire_read:g $? >> $@ + sed -e s:XX:_dd_acquire_read:g $? >> $@ list_atomic.c: list_atomic.template mkdir -p `dirname $@` @@ -1140,6 +1189,9 @@ list_atomic.i: list_atomic.c list_atomic.o: list_atomic.c $(COMPILE) -c -o $@ $? +# Just compile all tests (without linking and execution): +check-nolink-local: $(TEST_OBJS) + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/src/bdwgc/libatomic_ops/tests/list_atomic.c b/src/bdwgc/libatomic_ops/tests/list_atomic.c new file mode 100644 index 000000000..cb3eafc6e --- /dev/null +++ b/src/bdwgc/libatomic_ops/tests/list_atomic.c @@ -0,0 +1,5446 @@ +#include "atomic_ops.h" +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void list_atomic(void) +{ +# if defined(AO_HAVE_load) || defined(AO_HAVE_store) \ + || defined(AO_HAVE_fetch_and_add) \ + || defined(AO_HAVE_fetch_and_add1) \ + || defined(AO_HAVE_and) \ + || defined(AO_HAVE_compare_and_swap) \ + || defined(AO_HAVE_fetch_compare_and_swap) + static volatile AO_t val /* = 0 */; +# endif +# if defined(AO_HAVE_compare_and_swap) \ + || defined(AO_HAVE_fetch_compare_and_swap) + static AO_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_store) \ + || defined(AO_HAVE_compare_and_swap) \ + || defined(AO_HAVE_fetch_compare_and_swap) + static AO_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_fetch_and_add) || defined(AO_HAVE_and) \ + || defined(AO_HAVE_or) || defined(AO_HAVE_xor) + static AO_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop) + (void)"AO_nop(): "; + AO_nop(); +# else + (void)"No AO_nop"; +# endif + +# ifdef AO_HAVE_load + (void)"AO_load(&val):"; + (void)AO_load(&val); +# else + (void)"No AO_load"; +# endif +# ifdef AO_HAVE_store + (void)"AO_store(&val, newval):"; + AO_store(&val, newval); +# else + (void)"No AO_store"; +# endif +# ifdef AO_HAVE_fetch_and_add + (void)"AO_fetch_and_add(&val, incr):"; + (void)AO_fetch_and_add(&val, incr); +# else + (void)"No AO_fetch_and_add"; +# endif +# ifdef AO_HAVE_fetch_and_add1 + (void)"AO_fetch_and_add1(&val):"; + (void)AO_fetch_and_add1(&val); +# else + (void)"No AO_fetch_and_add1"; +# endif +# ifdef AO_HAVE_fetch_and_sub1 + (void)"AO_fetch_and_sub1(&val):"; + (void)AO_fetch_and_sub1(&val); +# else + (void)"No AO_fetch_and_sub1"; +# endif +# ifdef AO_HAVE_and + (void)"AO_and(&val, incr):"; + AO_and(&val, incr); +# else + (void)"No AO_and"; +# endif +# ifdef AO_HAVE_or + (void)"AO_or(&val, incr):"; + AO_or(&val, incr); +# else + (void)"No AO_or"; +# endif +# ifdef AO_HAVE_xor + (void)"AO_xor(&val, incr):"; + AO_xor(&val, incr); +# else + (void)"No AO_xor"; +# endif +# ifdef AO_HAVE_compare_and_swap + (void)"AO_compare_and_swap(&val, oldval, newval):"; + if (!AO_compare_and_swap(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_compare_and_swap"; +# endif + /* TODO: Add AO_compare_double_and_swap_double */ + /* TODO: Add AO_compare_and_swap_double */ +# ifdef AO_HAVE_fetch_compare_and_swap + (void)"AO_fetch_compare_and_swap(&val, oldval, newval):"; + if (AO_fetch_compare_and_swap(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_fetch_compare_and_swap"; +# endif + +# if defined(AO_HAVE_test_and_set) + (void)"AO_test_and_set(&ts):"; + (void)AO_test_and_set(&ts); +# else + (void)"No AO_test_and_set"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void list_atomic_release(void) +{ +# if defined(AO_HAVE_load_release) || defined(AO_HAVE_store_release) \ + || defined(AO_HAVE_fetch_and_add_release) \ + || defined(AO_HAVE_fetch_and_add1_release) \ + || defined(AO_HAVE_and_release) \ + || defined(AO_HAVE_compare_and_swap_release) \ + || defined(AO_HAVE_fetch_compare_and_swap_release) + static volatile AO_t val /* = 0 */; +# endif +# if defined(AO_HAVE_compare_and_swap_release) \ + || defined(AO_HAVE_fetch_compare_and_swap_release) + static AO_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_store_release) \ + || defined(AO_HAVE_compare_and_swap_release) \ + || defined(AO_HAVE_fetch_compare_and_swap_release) + static AO_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_release) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_fetch_and_add_release) || defined(AO_HAVE_and_release) \ + || defined(AO_HAVE_or_release) || defined(AO_HAVE_xor_release) + static AO_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_release) + (void)"AO_nop_release(): "; + AO_nop_release(); +# else + (void)"No AO_nop_release"; +# endif + +# ifdef AO_HAVE_load_release + (void)"AO_load_release(&val):"; + (void)AO_load_release(&val); +# else + (void)"No AO_load_release"; +# endif +# ifdef AO_HAVE_store_release + (void)"AO_store_release(&val, newval):"; + AO_store_release(&val, newval); +# else + (void)"No AO_store_release"; +# endif +# ifdef AO_HAVE_fetch_and_add_release + (void)"AO_fetch_and_add_release(&val, incr):"; + (void)AO_fetch_and_add_release(&val, incr); +# else + (void)"No AO_fetch_and_add_release"; +# endif +# ifdef AO_HAVE_fetch_and_add1_release + (void)"AO_fetch_and_add1_release(&val):"; + (void)AO_fetch_and_add1_release(&val); +# else + (void)"No AO_fetch_and_add1_release"; +# endif +# ifdef AO_HAVE_fetch_and_sub1_release + (void)"AO_fetch_and_sub1_release(&val):"; + (void)AO_fetch_and_sub1_release(&val); +# else + (void)"No AO_fetch_and_sub1_release"; +# endif +# ifdef AO_HAVE_and_release + (void)"AO_and_release(&val, incr):"; + AO_and_release(&val, incr); +# else + (void)"No AO_and_release"; +# endif +# ifdef AO_HAVE_or_release + (void)"AO_or_release(&val, incr):"; + AO_or_release(&val, incr); +# else + (void)"No AO_or_release"; +# endif +# ifdef AO_HAVE_xor_release + (void)"AO_xor_release(&val, incr):"; + AO_xor_release(&val, incr); +# else + (void)"No AO_xor_release"; +# endif +# ifdef AO_HAVE_compare_and_swap_release + (void)"AO_compare_and_swap_release(&val, oldval, newval):"; + if (!AO_compare_and_swap_release(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_compare_and_swap_release"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_release */ + /* TODO: Add AO_compare_and_swap_double_release */ +# ifdef AO_HAVE_fetch_compare_and_swap_release + (void)"AO_fetch_compare_and_swap_release(&val, oldval, newval):"; + if (AO_fetch_compare_and_swap_release(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_fetch_compare_and_swap_release"; +# endif + +# if defined(AO_HAVE_test_and_set_release) + (void)"AO_test_and_set_release(&ts):"; + (void)AO_test_and_set_release(&ts); +# else + (void)"No AO_test_and_set_release"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void list_atomic_acquire(void) +{ +# if defined(AO_HAVE_load_acquire) || defined(AO_HAVE_store_acquire) \ + || defined(AO_HAVE_fetch_and_add_acquire) \ + || defined(AO_HAVE_fetch_and_add1_acquire) \ + || defined(AO_HAVE_and_acquire) \ + || defined(AO_HAVE_compare_and_swap_acquire) \ + || defined(AO_HAVE_fetch_compare_and_swap_acquire) + static volatile AO_t val /* = 0 */; +# endif +# if defined(AO_HAVE_compare_and_swap_acquire) \ + || defined(AO_HAVE_fetch_compare_and_swap_acquire) + static AO_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_store_acquire) \ + || defined(AO_HAVE_compare_and_swap_acquire) \ + || defined(AO_HAVE_fetch_compare_and_swap_acquire) + static AO_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_acquire) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_fetch_and_add_acquire) || defined(AO_HAVE_and_acquire) \ + || defined(AO_HAVE_or_acquire) || defined(AO_HAVE_xor_acquire) + static AO_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_acquire) + (void)"AO_nop_acquire(): "; + AO_nop_acquire(); +# else + (void)"No AO_nop_acquire"; +# endif + +# ifdef AO_HAVE_load_acquire + (void)"AO_load_acquire(&val):"; + (void)AO_load_acquire(&val); +# else + (void)"No AO_load_acquire"; +# endif +# ifdef AO_HAVE_store_acquire + (void)"AO_store_acquire(&val, newval):"; + AO_store_acquire(&val, newval); +# else + (void)"No AO_store_acquire"; +# endif +# ifdef AO_HAVE_fetch_and_add_acquire + (void)"AO_fetch_and_add_acquire(&val, incr):"; + (void)AO_fetch_and_add_acquire(&val, incr); +# else + (void)"No AO_fetch_and_add_acquire"; +# endif +# ifdef AO_HAVE_fetch_and_add1_acquire + (void)"AO_fetch_and_add1_acquire(&val):"; + (void)AO_fetch_and_add1_acquire(&val); +# else + (void)"No AO_fetch_and_add1_acquire"; +# endif +# ifdef AO_HAVE_fetch_and_sub1_acquire + (void)"AO_fetch_and_sub1_acquire(&val):"; + (void)AO_fetch_and_sub1_acquire(&val); +# else + (void)"No AO_fetch_and_sub1_acquire"; +# endif +# ifdef AO_HAVE_and_acquire + (void)"AO_and_acquire(&val, incr):"; + AO_and_acquire(&val, incr); +# else + (void)"No AO_and_acquire"; +# endif +# ifdef AO_HAVE_or_acquire + (void)"AO_or_acquire(&val, incr):"; + AO_or_acquire(&val, incr); +# else + (void)"No AO_or_acquire"; +# endif +# ifdef AO_HAVE_xor_acquire + (void)"AO_xor_acquire(&val, incr):"; + AO_xor_acquire(&val, incr); +# else + (void)"No AO_xor_acquire"; +# endif +# ifdef AO_HAVE_compare_and_swap_acquire + (void)"AO_compare_and_swap_acquire(&val, oldval, newval):"; + if (!AO_compare_and_swap_acquire(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_compare_and_swap_acquire"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_acquire */ + /* TODO: Add AO_compare_and_swap_double_acquire */ +# ifdef AO_HAVE_fetch_compare_and_swap_acquire + (void)"AO_fetch_compare_and_swap_acquire(&val, oldval, newval):"; + if (AO_fetch_compare_and_swap_acquire(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_fetch_compare_and_swap_acquire"; +# endif + +# if defined(AO_HAVE_test_and_set_acquire) + (void)"AO_test_and_set_acquire(&ts):"; + (void)AO_test_and_set_acquire(&ts); +# else + (void)"No AO_test_and_set_acquire"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void list_atomic_read(void) +{ +# if defined(AO_HAVE_load_read) || defined(AO_HAVE_store_read) \ + || defined(AO_HAVE_fetch_and_add_read) \ + || defined(AO_HAVE_fetch_and_add1_read) \ + || defined(AO_HAVE_and_read) \ + || defined(AO_HAVE_compare_and_swap_read) \ + || defined(AO_HAVE_fetch_compare_and_swap_read) + static volatile AO_t val /* = 0 */; +# endif +# if defined(AO_HAVE_compare_and_swap_read) \ + || defined(AO_HAVE_fetch_compare_and_swap_read) + static AO_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_store_read) \ + || defined(AO_HAVE_compare_and_swap_read) \ + || defined(AO_HAVE_fetch_compare_and_swap_read) + static AO_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_fetch_and_add_read) || defined(AO_HAVE_and_read) \ + || defined(AO_HAVE_or_read) || defined(AO_HAVE_xor_read) + static AO_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_read) + (void)"AO_nop_read(): "; + AO_nop_read(); +# else + (void)"No AO_nop_read"; +# endif + +# ifdef AO_HAVE_load_read + (void)"AO_load_read(&val):"; + (void)AO_load_read(&val); +# else + (void)"No AO_load_read"; +# endif +# ifdef AO_HAVE_store_read + (void)"AO_store_read(&val, newval):"; + AO_store_read(&val, newval); +# else + (void)"No AO_store_read"; +# endif +# ifdef AO_HAVE_fetch_and_add_read + (void)"AO_fetch_and_add_read(&val, incr):"; + (void)AO_fetch_and_add_read(&val, incr); +# else + (void)"No AO_fetch_and_add_read"; +# endif +# ifdef AO_HAVE_fetch_and_add1_read + (void)"AO_fetch_and_add1_read(&val):"; + (void)AO_fetch_and_add1_read(&val); +# else + (void)"No AO_fetch_and_add1_read"; +# endif +# ifdef AO_HAVE_fetch_and_sub1_read + (void)"AO_fetch_and_sub1_read(&val):"; + (void)AO_fetch_and_sub1_read(&val); +# else + (void)"No AO_fetch_and_sub1_read"; +# endif +# ifdef AO_HAVE_and_read + (void)"AO_and_read(&val, incr):"; + AO_and_read(&val, incr); +# else + (void)"No AO_and_read"; +# endif +# ifdef AO_HAVE_or_read + (void)"AO_or_read(&val, incr):"; + AO_or_read(&val, incr); +# else + (void)"No AO_or_read"; +# endif +# ifdef AO_HAVE_xor_read + (void)"AO_xor_read(&val, incr):"; + AO_xor_read(&val, incr); +# else + (void)"No AO_xor_read"; +# endif +# ifdef AO_HAVE_compare_and_swap_read + (void)"AO_compare_and_swap_read(&val, oldval, newval):"; + if (!AO_compare_and_swap_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_compare_and_swap_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_read */ + /* TODO: Add AO_compare_and_swap_double_read */ +# ifdef AO_HAVE_fetch_compare_and_swap_read + (void)"AO_fetch_compare_and_swap_read(&val, oldval, newval):"; + if (AO_fetch_compare_and_swap_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_fetch_compare_and_swap_read"; +# endif + +# if defined(AO_HAVE_test_and_set_read) + (void)"AO_test_and_set_read(&ts):"; + (void)AO_test_and_set_read(&ts); +# else + (void)"No AO_test_and_set_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void list_atomic_write(void) +{ +# if defined(AO_HAVE_load_write) || defined(AO_HAVE_store_write) \ + || defined(AO_HAVE_fetch_and_add_write) \ + || defined(AO_HAVE_fetch_and_add1_write) \ + || defined(AO_HAVE_and_write) \ + || defined(AO_HAVE_compare_and_swap_write) \ + || defined(AO_HAVE_fetch_compare_and_swap_write) + static volatile AO_t val /* = 0 */; +# endif +# if defined(AO_HAVE_compare_and_swap_write) \ + || defined(AO_HAVE_fetch_compare_and_swap_write) + static AO_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_store_write) \ + || defined(AO_HAVE_compare_and_swap_write) \ + || defined(AO_HAVE_fetch_compare_and_swap_write) + static AO_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_write) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_fetch_and_add_write) || defined(AO_HAVE_and_write) \ + || defined(AO_HAVE_or_write) || defined(AO_HAVE_xor_write) + static AO_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_write) + (void)"AO_nop_write(): "; + AO_nop_write(); +# else + (void)"No AO_nop_write"; +# endif + +# ifdef AO_HAVE_load_write + (void)"AO_load_write(&val):"; + (void)AO_load_write(&val); +# else + (void)"No AO_load_write"; +# endif +# ifdef AO_HAVE_store_write + (void)"AO_store_write(&val, newval):"; + AO_store_write(&val, newval); +# else + (void)"No AO_store_write"; +# endif +# ifdef AO_HAVE_fetch_and_add_write + (void)"AO_fetch_and_add_write(&val, incr):"; + (void)AO_fetch_and_add_write(&val, incr); +# else + (void)"No AO_fetch_and_add_write"; +# endif +# ifdef AO_HAVE_fetch_and_add1_write + (void)"AO_fetch_and_add1_write(&val):"; + (void)AO_fetch_and_add1_write(&val); +# else + (void)"No AO_fetch_and_add1_write"; +# endif +# ifdef AO_HAVE_fetch_and_sub1_write + (void)"AO_fetch_and_sub1_write(&val):"; + (void)AO_fetch_and_sub1_write(&val); +# else + (void)"No AO_fetch_and_sub1_write"; +# endif +# ifdef AO_HAVE_and_write + (void)"AO_and_write(&val, incr):"; + AO_and_write(&val, incr); +# else + (void)"No AO_and_write"; +# endif +# ifdef AO_HAVE_or_write + (void)"AO_or_write(&val, incr):"; + AO_or_write(&val, incr); +# else + (void)"No AO_or_write"; +# endif +# ifdef AO_HAVE_xor_write + (void)"AO_xor_write(&val, incr):"; + AO_xor_write(&val, incr); +# else + (void)"No AO_xor_write"; +# endif +# ifdef AO_HAVE_compare_and_swap_write + (void)"AO_compare_and_swap_write(&val, oldval, newval):"; + if (!AO_compare_and_swap_write(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_compare_and_swap_write"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_write */ + /* TODO: Add AO_compare_and_swap_double_write */ +# ifdef AO_HAVE_fetch_compare_and_swap_write + (void)"AO_fetch_compare_and_swap_write(&val, oldval, newval):"; + if (AO_fetch_compare_and_swap_write(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_fetch_compare_and_swap_write"; +# endif + +# if defined(AO_HAVE_test_and_set_write) + (void)"AO_test_and_set_write(&ts):"; + (void)AO_test_and_set_write(&ts); +# else + (void)"No AO_test_and_set_write"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void list_atomic_full(void) +{ +# if defined(AO_HAVE_load_full) || defined(AO_HAVE_store_full) \ + || defined(AO_HAVE_fetch_and_add_full) \ + || defined(AO_HAVE_fetch_and_add1_full) \ + || defined(AO_HAVE_and_full) \ + || defined(AO_HAVE_compare_and_swap_full) \ + || defined(AO_HAVE_fetch_compare_and_swap_full) + static volatile AO_t val /* = 0 */; +# endif +# if defined(AO_HAVE_compare_and_swap_full) \ + || defined(AO_HAVE_fetch_compare_and_swap_full) + static AO_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_store_full) \ + || defined(AO_HAVE_compare_and_swap_full) \ + || defined(AO_HAVE_fetch_compare_and_swap_full) + static AO_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_full) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_fetch_and_add_full) || defined(AO_HAVE_and_full) \ + || defined(AO_HAVE_or_full) || defined(AO_HAVE_xor_full) + static AO_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_full) + (void)"AO_nop_full(): "; + AO_nop_full(); +# else + (void)"No AO_nop_full"; +# endif + +# ifdef AO_HAVE_load_full + (void)"AO_load_full(&val):"; + (void)AO_load_full(&val); +# else + (void)"No AO_load_full"; +# endif +# ifdef AO_HAVE_store_full + (void)"AO_store_full(&val, newval):"; + AO_store_full(&val, newval); +# else + (void)"No AO_store_full"; +# endif +# ifdef AO_HAVE_fetch_and_add_full + (void)"AO_fetch_and_add_full(&val, incr):"; + (void)AO_fetch_and_add_full(&val, incr); +# else + (void)"No AO_fetch_and_add_full"; +# endif +# ifdef AO_HAVE_fetch_and_add1_full + (void)"AO_fetch_and_add1_full(&val):"; + (void)AO_fetch_and_add1_full(&val); +# else + (void)"No AO_fetch_and_add1_full"; +# endif +# ifdef AO_HAVE_fetch_and_sub1_full + (void)"AO_fetch_and_sub1_full(&val):"; + (void)AO_fetch_and_sub1_full(&val); +# else + (void)"No AO_fetch_and_sub1_full"; +# endif +# ifdef AO_HAVE_and_full + (void)"AO_and_full(&val, incr):"; + AO_and_full(&val, incr); +# else + (void)"No AO_and_full"; +# endif +# ifdef AO_HAVE_or_full + (void)"AO_or_full(&val, incr):"; + AO_or_full(&val, incr); +# else + (void)"No AO_or_full"; +# endif +# ifdef AO_HAVE_xor_full + (void)"AO_xor_full(&val, incr):"; + AO_xor_full(&val, incr); +# else + (void)"No AO_xor_full"; +# endif +# ifdef AO_HAVE_compare_and_swap_full + (void)"AO_compare_and_swap_full(&val, oldval, newval):"; + if (!AO_compare_and_swap_full(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_compare_and_swap_full"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_full */ + /* TODO: Add AO_compare_and_swap_double_full */ +# ifdef AO_HAVE_fetch_compare_and_swap_full + (void)"AO_fetch_compare_and_swap_full(&val, oldval, newval):"; + if (AO_fetch_compare_and_swap_full(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_fetch_compare_and_swap_full"; +# endif + +# if defined(AO_HAVE_test_and_set_full) + (void)"AO_test_and_set_full(&ts):"; + (void)AO_test_and_set_full(&ts); +# else + (void)"No AO_test_and_set_full"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void list_atomic_release_write(void) +{ +# if defined(AO_HAVE_load_release_write) || defined(AO_HAVE_store_release_write) \ + || defined(AO_HAVE_fetch_and_add_release_write) \ + || defined(AO_HAVE_fetch_and_add1_release_write) \ + || defined(AO_HAVE_and_release_write) \ + || defined(AO_HAVE_compare_and_swap_release_write) \ + || defined(AO_HAVE_fetch_compare_and_swap_release_write) + static volatile AO_t val /* = 0 */; +# endif +# if defined(AO_HAVE_compare_and_swap_release_write) \ + || defined(AO_HAVE_fetch_compare_and_swap_release_write) + static AO_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_store_release_write) \ + || defined(AO_HAVE_compare_and_swap_release_write) \ + || defined(AO_HAVE_fetch_compare_and_swap_release_write) + static AO_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_release_write) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_fetch_and_add_release_write) || defined(AO_HAVE_and_release_write) \ + || defined(AO_HAVE_or_release_write) || defined(AO_HAVE_xor_release_write) + static AO_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_release_write) + (void)"AO_nop_release_write(): "; + AO_nop_release_write(); +# else + (void)"No AO_nop_release_write"; +# endif + +# ifdef AO_HAVE_load_release_write + (void)"AO_load_release_write(&val):"; + (void)AO_load_release_write(&val); +# else + (void)"No AO_load_release_write"; +# endif +# ifdef AO_HAVE_store_release_write + (void)"AO_store_release_write(&val, newval):"; + AO_store_release_write(&val, newval); +# else + (void)"No AO_store_release_write"; +# endif +# ifdef AO_HAVE_fetch_and_add_release_write + (void)"AO_fetch_and_add_release_write(&val, incr):"; + (void)AO_fetch_and_add_release_write(&val, incr); +# else + (void)"No AO_fetch_and_add_release_write"; +# endif +# ifdef AO_HAVE_fetch_and_add1_release_write + (void)"AO_fetch_and_add1_release_write(&val):"; + (void)AO_fetch_and_add1_release_write(&val); +# else + (void)"No AO_fetch_and_add1_release_write"; +# endif +# ifdef AO_HAVE_fetch_and_sub1_release_write + (void)"AO_fetch_and_sub1_release_write(&val):"; + (void)AO_fetch_and_sub1_release_write(&val); +# else + (void)"No AO_fetch_and_sub1_release_write"; +# endif +# ifdef AO_HAVE_and_release_write + (void)"AO_and_release_write(&val, incr):"; + AO_and_release_write(&val, incr); +# else + (void)"No AO_and_release_write"; +# endif +# ifdef AO_HAVE_or_release_write + (void)"AO_or_release_write(&val, incr):"; + AO_or_release_write(&val, incr); +# else + (void)"No AO_or_release_write"; +# endif +# ifdef AO_HAVE_xor_release_write + (void)"AO_xor_release_write(&val, incr):"; + AO_xor_release_write(&val, incr); +# else + (void)"No AO_xor_release_write"; +# endif +# ifdef AO_HAVE_compare_and_swap_release_write + (void)"AO_compare_and_swap_release_write(&val, oldval, newval):"; + if (!AO_compare_and_swap_release_write(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_compare_and_swap_release_write"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_release_write */ + /* TODO: Add AO_compare_and_swap_double_release_write */ +# ifdef AO_HAVE_fetch_compare_and_swap_release_write + (void)"AO_fetch_compare_and_swap_release_write(&val, oldval, newval):"; + if (AO_fetch_compare_and_swap_release_write(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_fetch_compare_and_swap_release_write"; +# endif + +# if defined(AO_HAVE_test_and_set_release_write) + (void)"AO_test_and_set_release_write(&ts):"; + (void)AO_test_and_set_release_write(&ts); +# else + (void)"No AO_test_and_set_release_write"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void list_atomic_acquire_read(void) +{ +# if defined(AO_HAVE_load_acquire_read) || defined(AO_HAVE_store_acquire_read) \ + || defined(AO_HAVE_fetch_and_add_acquire_read) \ + || defined(AO_HAVE_fetch_and_add1_acquire_read) \ + || defined(AO_HAVE_and_acquire_read) \ + || defined(AO_HAVE_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_fetch_compare_and_swap_acquire_read) + static volatile AO_t val /* = 0 */; +# endif +# if defined(AO_HAVE_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_fetch_compare_and_swap_acquire_read) + static AO_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_store_acquire_read) \ + || defined(AO_HAVE_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_fetch_compare_and_swap_acquire_read) + static AO_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_acquire_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_fetch_and_add_acquire_read) || defined(AO_HAVE_and_acquire_read) \ + || defined(AO_HAVE_or_acquire_read) || defined(AO_HAVE_xor_acquire_read) + static AO_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_acquire_read) + (void)"AO_nop_acquire_read(): "; + AO_nop_acquire_read(); +# else + (void)"No AO_nop_acquire_read"; +# endif + +# ifdef AO_HAVE_load_acquire_read + (void)"AO_load_acquire_read(&val):"; + (void)AO_load_acquire_read(&val); +# else + (void)"No AO_load_acquire_read"; +# endif +# ifdef AO_HAVE_store_acquire_read + (void)"AO_store_acquire_read(&val, newval):"; + AO_store_acquire_read(&val, newval); +# else + (void)"No AO_store_acquire_read"; +# endif +# ifdef AO_HAVE_fetch_and_add_acquire_read + (void)"AO_fetch_and_add_acquire_read(&val, incr):"; + (void)AO_fetch_and_add_acquire_read(&val, incr); +# else + (void)"No AO_fetch_and_add_acquire_read"; +# endif +# ifdef AO_HAVE_fetch_and_add1_acquire_read + (void)"AO_fetch_and_add1_acquire_read(&val):"; + (void)AO_fetch_and_add1_acquire_read(&val); +# else + (void)"No AO_fetch_and_add1_acquire_read"; +# endif +# ifdef AO_HAVE_fetch_and_sub1_acquire_read + (void)"AO_fetch_and_sub1_acquire_read(&val):"; + (void)AO_fetch_and_sub1_acquire_read(&val); +# else + (void)"No AO_fetch_and_sub1_acquire_read"; +# endif +# ifdef AO_HAVE_and_acquire_read + (void)"AO_and_acquire_read(&val, incr):"; + AO_and_acquire_read(&val, incr); +# else + (void)"No AO_and_acquire_read"; +# endif +# ifdef AO_HAVE_or_acquire_read + (void)"AO_or_acquire_read(&val, incr):"; + AO_or_acquire_read(&val, incr); +# else + (void)"No AO_or_acquire_read"; +# endif +# ifdef AO_HAVE_xor_acquire_read + (void)"AO_xor_acquire_read(&val, incr):"; + AO_xor_acquire_read(&val, incr); +# else + (void)"No AO_xor_acquire_read"; +# endif +# ifdef AO_HAVE_compare_and_swap_acquire_read + (void)"AO_compare_and_swap_acquire_read(&val, oldval, newval):"; + if (!AO_compare_and_swap_acquire_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_compare_and_swap_acquire_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_acquire_read */ + /* TODO: Add AO_compare_and_swap_double_acquire_read */ +# ifdef AO_HAVE_fetch_compare_and_swap_acquire_read + (void)"AO_fetch_compare_and_swap_acquire_read(&val, oldval, newval):"; + if (AO_fetch_compare_and_swap_acquire_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_fetch_compare_and_swap_acquire_read"; +# endif + +# if defined(AO_HAVE_test_and_set_acquire_read) + (void)"AO_test_and_set_acquire_read(&ts):"; + (void)AO_test_and_set_acquire_read(&ts); +# else + (void)"No AO_test_and_set_acquire_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void list_atomic_dd_acquire_read(void) +{ +# if defined(AO_HAVE_load_dd_acquire_read) || defined(AO_HAVE_store_dd_acquire_read) \ + || defined(AO_HAVE_fetch_and_add_dd_acquire_read) \ + || defined(AO_HAVE_fetch_and_add1_dd_acquire_read) \ + || defined(AO_HAVE_and_dd_acquire_read) \ + || defined(AO_HAVE_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_fetch_compare_and_swap_dd_acquire_read) + static volatile AO_t val /* = 0 */; +# endif +# if defined(AO_HAVE_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_fetch_compare_and_swap_dd_acquire_read) + static AO_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_store_dd_acquire_read) \ + || defined(AO_HAVE_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_fetch_compare_and_swap_dd_acquire_read) + static AO_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_fetch_and_add_dd_acquire_read) || defined(AO_HAVE_and_dd_acquire_read) \ + || defined(AO_HAVE_or_dd_acquire_read) || defined(AO_HAVE_xor_dd_acquire_read) + static AO_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_dd_acquire_read) + (void)"AO_nop_dd_acquire_read(): "; + AO_nop_dd_acquire_read(); +# else + (void)"No AO_nop_dd_acquire_read"; +# endif + +# ifdef AO_HAVE_load_dd_acquire_read + (void)"AO_load_dd_acquire_read(&val):"; + (void)AO_load_dd_acquire_read(&val); +# else + (void)"No AO_load_dd_acquire_read"; +# endif +# ifdef AO_HAVE_store_dd_acquire_read + (void)"AO_store_dd_acquire_read(&val, newval):"; + AO_store_dd_acquire_read(&val, newval); +# else + (void)"No AO_store_dd_acquire_read"; +# endif +# ifdef AO_HAVE_fetch_and_add_dd_acquire_read + (void)"AO_fetch_and_add_dd_acquire_read(&val, incr):"; + (void)AO_fetch_and_add_dd_acquire_read(&val, incr); +# else + (void)"No AO_fetch_and_add_dd_acquire_read"; +# endif +# ifdef AO_HAVE_fetch_and_add1_dd_acquire_read + (void)"AO_fetch_and_add1_dd_acquire_read(&val):"; + (void)AO_fetch_and_add1_dd_acquire_read(&val); +# else + (void)"No AO_fetch_and_add1_dd_acquire_read"; +# endif +# ifdef AO_HAVE_fetch_and_sub1_dd_acquire_read + (void)"AO_fetch_and_sub1_dd_acquire_read(&val):"; + (void)AO_fetch_and_sub1_dd_acquire_read(&val); +# else + (void)"No AO_fetch_and_sub1_dd_acquire_read"; +# endif +# ifdef AO_HAVE_and_dd_acquire_read + (void)"AO_and_dd_acquire_read(&val, incr):"; + AO_and_dd_acquire_read(&val, incr); +# else + (void)"No AO_and_dd_acquire_read"; +# endif +# ifdef AO_HAVE_or_dd_acquire_read + (void)"AO_or_dd_acquire_read(&val, incr):"; + AO_or_dd_acquire_read(&val, incr); +# else + (void)"No AO_or_dd_acquire_read"; +# endif +# ifdef AO_HAVE_xor_dd_acquire_read + (void)"AO_xor_dd_acquire_read(&val, incr):"; + AO_xor_dd_acquire_read(&val, incr); +# else + (void)"No AO_xor_dd_acquire_read"; +# endif +# ifdef AO_HAVE_compare_and_swap_dd_acquire_read + (void)"AO_compare_and_swap_dd_acquire_read(&val, oldval, newval):"; + if (!AO_compare_and_swap_dd_acquire_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_compare_and_swap_dd_acquire_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_dd_acquire_read */ + /* TODO: Add AO_compare_and_swap_double_dd_acquire_read */ +# ifdef AO_HAVE_fetch_compare_and_swap_dd_acquire_read + (void)"AO_fetch_compare_and_swap_dd_acquire_read(&val, oldval, newval):"; + if (AO_fetch_compare_and_swap_dd_acquire_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_fetch_compare_and_swap_dd_acquire_read"; +# endif + +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + (void)"AO_test_and_set_dd_acquire_read(&ts):"; + (void)AO_test_and_set_dd_acquire_read(&ts); +# else + (void)"No AO_test_and_set_dd_acquire_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void char_list_atomic(void) +{ +# if defined(AO_HAVE_char_load) || defined(AO_HAVE_char_store) \ + || defined(AO_HAVE_char_fetch_and_add) \ + || defined(AO_HAVE_char_fetch_and_add1) \ + || defined(AO_HAVE_char_and) \ + || defined(AO_HAVE_char_compare_and_swap) \ + || defined(AO_HAVE_char_fetch_compare_and_swap) + static volatile unsigned/**/char val /* = 0 */; +# endif +# if defined(AO_HAVE_char_compare_and_swap) \ + || defined(AO_HAVE_char_fetch_compare_and_swap) + static unsigned/**/char oldval /* = 0 */; +# endif +# if defined(AO_HAVE_char_store) \ + || defined(AO_HAVE_char_compare_and_swap) \ + || defined(AO_HAVE_char_fetch_compare_and_swap) + static unsigned/**/char newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_char_fetch_and_add) || defined(AO_HAVE_char_and) \ + || defined(AO_HAVE_char_or) || defined(AO_HAVE_char_xor) + static unsigned/**/char incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop) + (void)"AO_nop(): "; + AO_nop(); +# else + (void)"No AO_nop"; +# endif + +# ifdef AO_HAVE_char_load + (void)"AO_char_load(&val):"; + (void)AO_char_load(&val); +# else + (void)"No AO_char_load"; +# endif +# ifdef AO_HAVE_char_store + (void)"AO_char_store(&val, newval):"; + AO_char_store(&val, newval); +# else + (void)"No AO_char_store"; +# endif +# ifdef AO_HAVE_char_fetch_and_add + (void)"AO_char_fetch_and_add(&val, incr):"; + (void)AO_char_fetch_and_add(&val, incr); +# else + (void)"No AO_char_fetch_and_add"; +# endif +# ifdef AO_HAVE_char_fetch_and_add1 + (void)"AO_char_fetch_and_add1(&val):"; + (void)AO_char_fetch_and_add1(&val); +# else + (void)"No AO_char_fetch_and_add1"; +# endif +# ifdef AO_HAVE_char_fetch_and_sub1 + (void)"AO_char_fetch_and_sub1(&val):"; + (void)AO_char_fetch_and_sub1(&val); +# else + (void)"No AO_char_fetch_and_sub1"; +# endif +# ifdef AO_HAVE_char_and + (void)"AO_char_and(&val, incr):"; + AO_char_and(&val, incr); +# else + (void)"No AO_char_and"; +# endif +# ifdef AO_HAVE_char_or + (void)"AO_char_or(&val, incr):"; + AO_char_or(&val, incr); +# else + (void)"No AO_char_or"; +# endif +# ifdef AO_HAVE_char_xor + (void)"AO_char_xor(&val, incr):"; + AO_char_xor(&val, incr); +# else + (void)"No AO_char_xor"; +# endif +# ifdef AO_HAVE_char_compare_and_swap + (void)"AO_char_compare_and_swap(&val, oldval, newval):"; + if (!AO_char_compare_and_swap(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_char_compare_and_swap"; +# endif + /* TODO: Add AO_compare_double_and_swap_double */ + /* TODO: Add AO_compare_and_swap_double */ +# ifdef AO_HAVE_char_fetch_compare_and_swap + (void)"AO_char_fetch_compare_and_swap(&val, oldval, newval):"; + if (AO_char_fetch_compare_and_swap(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_char_fetch_compare_and_swap"; +# endif + +# if defined(AO_HAVE_test_and_set) + (void)"AO_test_and_set(&ts):"; + (void)AO_test_and_set(&ts); +# else + (void)"No AO_test_and_set"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void char_list_atomic_release(void) +{ +# if defined(AO_HAVE_char_load_release) || defined(AO_HAVE_char_store_release) \ + || defined(AO_HAVE_char_fetch_and_add_release) \ + || defined(AO_HAVE_char_fetch_and_add1_release) \ + || defined(AO_HAVE_char_and_release) \ + || defined(AO_HAVE_char_compare_and_swap_release) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_release) + static volatile unsigned/**/char val /* = 0 */; +# endif +# if defined(AO_HAVE_char_compare_and_swap_release) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_release) + static unsigned/**/char oldval /* = 0 */; +# endif +# if defined(AO_HAVE_char_store_release) \ + || defined(AO_HAVE_char_compare_and_swap_release) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_release) + static unsigned/**/char newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_release) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_char_fetch_and_add_release) || defined(AO_HAVE_char_and_release) \ + || defined(AO_HAVE_char_or_release) || defined(AO_HAVE_char_xor_release) + static unsigned/**/char incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_release) + (void)"AO_nop_release(): "; + AO_nop_release(); +# else + (void)"No AO_nop_release"; +# endif + +# ifdef AO_HAVE_char_load_release + (void)"AO_char_load_release(&val):"; + (void)AO_char_load_release(&val); +# else + (void)"No AO_char_load_release"; +# endif +# ifdef AO_HAVE_char_store_release + (void)"AO_char_store_release(&val, newval):"; + AO_char_store_release(&val, newval); +# else + (void)"No AO_char_store_release"; +# endif +# ifdef AO_HAVE_char_fetch_and_add_release + (void)"AO_char_fetch_and_add_release(&val, incr):"; + (void)AO_char_fetch_and_add_release(&val, incr); +# else + (void)"No AO_char_fetch_and_add_release"; +# endif +# ifdef AO_HAVE_char_fetch_and_add1_release + (void)"AO_char_fetch_and_add1_release(&val):"; + (void)AO_char_fetch_and_add1_release(&val); +# else + (void)"No AO_char_fetch_and_add1_release"; +# endif +# ifdef AO_HAVE_char_fetch_and_sub1_release + (void)"AO_char_fetch_and_sub1_release(&val):"; + (void)AO_char_fetch_and_sub1_release(&val); +# else + (void)"No AO_char_fetch_and_sub1_release"; +# endif +# ifdef AO_HAVE_char_and_release + (void)"AO_char_and_release(&val, incr):"; + AO_char_and_release(&val, incr); +# else + (void)"No AO_char_and_release"; +# endif +# ifdef AO_HAVE_char_or_release + (void)"AO_char_or_release(&val, incr):"; + AO_char_or_release(&val, incr); +# else + (void)"No AO_char_or_release"; +# endif +# ifdef AO_HAVE_char_xor_release + (void)"AO_char_xor_release(&val, incr):"; + AO_char_xor_release(&val, incr); +# else + (void)"No AO_char_xor_release"; +# endif +# ifdef AO_HAVE_char_compare_and_swap_release + (void)"AO_char_compare_and_swap_release(&val, oldval, newval):"; + if (!AO_char_compare_and_swap_release(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_char_compare_and_swap_release"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_release */ + /* TODO: Add AO_compare_and_swap_double_release */ +# ifdef AO_HAVE_char_fetch_compare_and_swap_release + (void)"AO_char_fetch_compare_and_swap_release(&val, oldval, newval):"; + if (AO_char_fetch_compare_and_swap_release(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_char_fetch_compare_and_swap_release"; +# endif + +# if defined(AO_HAVE_test_and_set_release) + (void)"AO_test_and_set_release(&ts):"; + (void)AO_test_and_set_release(&ts); +# else + (void)"No AO_test_and_set_release"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void char_list_atomic_acquire(void) +{ +# if defined(AO_HAVE_char_load_acquire) || defined(AO_HAVE_char_store_acquire) \ + || defined(AO_HAVE_char_fetch_and_add_acquire) \ + || defined(AO_HAVE_char_fetch_and_add1_acquire) \ + || defined(AO_HAVE_char_and_acquire) \ + || defined(AO_HAVE_char_compare_and_swap_acquire) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_acquire) + static volatile unsigned/**/char val /* = 0 */; +# endif +# if defined(AO_HAVE_char_compare_and_swap_acquire) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_acquire) + static unsigned/**/char oldval /* = 0 */; +# endif +# if defined(AO_HAVE_char_store_acquire) \ + || defined(AO_HAVE_char_compare_and_swap_acquire) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_acquire) + static unsigned/**/char newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_acquire) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_char_fetch_and_add_acquire) || defined(AO_HAVE_char_and_acquire) \ + || defined(AO_HAVE_char_or_acquire) || defined(AO_HAVE_char_xor_acquire) + static unsigned/**/char incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_acquire) + (void)"AO_nop_acquire(): "; + AO_nop_acquire(); +# else + (void)"No AO_nop_acquire"; +# endif + +# ifdef AO_HAVE_char_load_acquire + (void)"AO_char_load_acquire(&val):"; + (void)AO_char_load_acquire(&val); +# else + (void)"No AO_char_load_acquire"; +# endif +# ifdef AO_HAVE_char_store_acquire + (void)"AO_char_store_acquire(&val, newval):"; + AO_char_store_acquire(&val, newval); +# else + (void)"No AO_char_store_acquire"; +# endif +# ifdef AO_HAVE_char_fetch_and_add_acquire + (void)"AO_char_fetch_and_add_acquire(&val, incr):"; + (void)AO_char_fetch_and_add_acquire(&val, incr); +# else + (void)"No AO_char_fetch_and_add_acquire"; +# endif +# ifdef AO_HAVE_char_fetch_and_add1_acquire + (void)"AO_char_fetch_and_add1_acquire(&val):"; + (void)AO_char_fetch_and_add1_acquire(&val); +# else + (void)"No AO_char_fetch_and_add1_acquire"; +# endif +# ifdef AO_HAVE_char_fetch_and_sub1_acquire + (void)"AO_char_fetch_and_sub1_acquire(&val):"; + (void)AO_char_fetch_and_sub1_acquire(&val); +# else + (void)"No AO_char_fetch_and_sub1_acquire"; +# endif +# ifdef AO_HAVE_char_and_acquire + (void)"AO_char_and_acquire(&val, incr):"; + AO_char_and_acquire(&val, incr); +# else + (void)"No AO_char_and_acquire"; +# endif +# ifdef AO_HAVE_char_or_acquire + (void)"AO_char_or_acquire(&val, incr):"; + AO_char_or_acquire(&val, incr); +# else + (void)"No AO_char_or_acquire"; +# endif +# ifdef AO_HAVE_char_xor_acquire + (void)"AO_char_xor_acquire(&val, incr):"; + AO_char_xor_acquire(&val, incr); +# else + (void)"No AO_char_xor_acquire"; +# endif +# ifdef AO_HAVE_char_compare_and_swap_acquire + (void)"AO_char_compare_and_swap_acquire(&val, oldval, newval):"; + if (!AO_char_compare_and_swap_acquire(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_char_compare_and_swap_acquire"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_acquire */ + /* TODO: Add AO_compare_and_swap_double_acquire */ +# ifdef AO_HAVE_char_fetch_compare_and_swap_acquire + (void)"AO_char_fetch_compare_and_swap_acquire(&val, oldval, newval):"; + if (AO_char_fetch_compare_and_swap_acquire(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_char_fetch_compare_and_swap_acquire"; +# endif + +# if defined(AO_HAVE_test_and_set_acquire) + (void)"AO_test_and_set_acquire(&ts):"; + (void)AO_test_and_set_acquire(&ts); +# else + (void)"No AO_test_and_set_acquire"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void char_list_atomic_read(void) +{ +# if defined(AO_HAVE_char_load_read) || defined(AO_HAVE_char_store_read) \ + || defined(AO_HAVE_char_fetch_and_add_read) \ + || defined(AO_HAVE_char_fetch_and_add1_read) \ + || defined(AO_HAVE_char_and_read) \ + || defined(AO_HAVE_char_compare_and_swap_read) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_read) + static volatile unsigned/**/char val /* = 0 */; +# endif +# if defined(AO_HAVE_char_compare_and_swap_read) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_read) + static unsigned/**/char oldval /* = 0 */; +# endif +# if defined(AO_HAVE_char_store_read) \ + || defined(AO_HAVE_char_compare_and_swap_read) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_read) + static unsigned/**/char newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_char_fetch_and_add_read) || defined(AO_HAVE_char_and_read) \ + || defined(AO_HAVE_char_or_read) || defined(AO_HAVE_char_xor_read) + static unsigned/**/char incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_read) + (void)"AO_nop_read(): "; + AO_nop_read(); +# else + (void)"No AO_nop_read"; +# endif + +# ifdef AO_HAVE_char_load_read + (void)"AO_char_load_read(&val):"; + (void)AO_char_load_read(&val); +# else + (void)"No AO_char_load_read"; +# endif +# ifdef AO_HAVE_char_store_read + (void)"AO_char_store_read(&val, newval):"; + AO_char_store_read(&val, newval); +# else + (void)"No AO_char_store_read"; +# endif +# ifdef AO_HAVE_char_fetch_and_add_read + (void)"AO_char_fetch_and_add_read(&val, incr):"; + (void)AO_char_fetch_and_add_read(&val, incr); +# else + (void)"No AO_char_fetch_and_add_read"; +# endif +# ifdef AO_HAVE_char_fetch_and_add1_read + (void)"AO_char_fetch_and_add1_read(&val):"; + (void)AO_char_fetch_and_add1_read(&val); +# else + (void)"No AO_char_fetch_and_add1_read"; +# endif +# ifdef AO_HAVE_char_fetch_and_sub1_read + (void)"AO_char_fetch_and_sub1_read(&val):"; + (void)AO_char_fetch_and_sub1_read(&val); +# else + (void)"No AO_char_fetch_and_sub1_read"; +# endif +# ifdef AO_HAVE_char_and_read + (void)"AO_char_and_read(&val, incr):"; + AO_char_and_read(&val, incr); +# else + (void)"No AO_char_and_read"; +# endif +# ifdef AO_HAVE_char_or_read + (void)"AO_char_or_read(&val, incr):"; + AO_char_or_read(&val, incr); +# else + (void)"No AO_char_or_read"; +# endif +# ifdef AO_HAVE_char_xor_read + (void)"AO_char_xor_read(&val, incr):"; + AO_char_xor_read(&val, incr); +# else + (void)"No AO_char_xor_read"; +# endif +# ifdef AO_HAVE_char_compare_and_swap_read + (void)"AO_char_compare_and_swap_read(&val, oldval, newval):"; + if (!AO_char_compare_and_swap_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_char_compare_and_swap_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_read */ + /* TODO: Add AO_compare_and_swap_double_read */ +# ifdef AO_HAVE_char_fetch_compare_and_swap_read + (void)"AO_char_fetch_compare_and_swap_read(&val, oldval, newval):"; + if (AO_char_fetch_compare_and_swap_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_char_fetch_compare_and_swap_read"; +# endif + +# if defined(AO_HAVE_test_and_set_read) + (void)"AO_test_and_set_read(&ts):"; + (void)AO_test_and_set_read(&ts); +# else + (void)"No AO_test_and_set_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void char_list_atomic_write(void) +{ +# if defined(AO_HAVE_char_load_write) || defined(AO_HAVE_char_store_write) \ + || defined(AO_HAVE_char_fetch_and_add_write) \ + || defined(AO_HAVE_char_fetch_and_add1_write) \ + || defined(AO_HAVE_char_and_write) \ + || defined(AO_HAVE_char_compare_and_swap_write) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_write) + static volatile unsigned/**/char val /* = 0 */; +# endif +# if defined(AO_HAVE_char_compare_and_swap_write) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_write) + static unsigned/**/char oldval /* = 0 */; +# endif +# if defined(AO_HAVE_char_store_write) \ + || defined(AO_HAVE_char_compare_and_swap_write) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_write) + static unsigned/**/char newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_write) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_char_fetch_and_add_write) || defined(AO_HAVE_char_and_write) \ + || defined(AO_HAVE_char_or_write) || defined(AO_HAVE_char_xor_write) + static unsigned/**/char incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_write) + (void)"AO_nop_write(): "; + AO_nop_write(); +# else + (void)"No AO_nop_write"; +# endif + +# ifdef AO_HAVE_char_load_write + (void)"AO_char_load_write(&val):"; + (void)AO_char_load_write(&val); +# else + (void)"No AO_char_load_write"; +# endif +# ifdef AO_HAVE_char_store_write + (void)"AO_char_store_write(&val, newval):"; + AO_char_store_write(&val, newval); +# else + (void)"No AO_char_store_write"; +# endif +# ifdef AO_HAVE_char_fetch_and_add_write + (void)"AO_char_fetch_and_add_write(&val, incr):"; + (void)AO_char_fetch_and_add_write(&val, incr); +# else + (void)"No AO_char_fetch_and_add_write"; +# endif +# ifdef AO_HAVE_char_fetch_and_add1_write + (void)"AO_char_fetch_and_add1_write(&val):"; + (void)AO_char_fetch_and_add1_write(&val); +# else + (void)"No AO_char_fetch_and_add1_write"; +# endif +# ifdef AO_HAVE_char_fetch_and_sub1_write + (void)"AO_char_fetch_and_sub1_write(&val):"; + (void)AO_char_fetch_and_sub1_write(&val); +# else + (void)"No AO_char_fetch_and_sub1_write"; +# endif +# ifdef AO_HAVE_char_and_write + (void)"AO_char_and_write(&val, incr):"; + AO_char_and_write(&val, incr); +# else + (void)"No AO_char_and_write"; +# endif +# ifdef AO_HAVE_char_or_write + (void)"AO_char_or_write(&val, incr):"; + AO_char_or_write(&val, incr); +# else + (void)"No AO_char_or_write"; +# endif +# ifdef AO_HAVE_char_xor_write + (void)"AO_char_xor_write(&val, incr):"; + AO_char_xor_write(&val, incr); +# else + (void)"No AO_char_xor_write"; +# endif +# ifdef AO_HAVE_char_compare_and_swap_write + (void)"AO_char_compare_and_swap_write(&val, oldval, newval):"; + if (!AO_char_compare_and_swap_write(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_char_compare_and_swap_write"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_write */ + /* TODO: Add AO_compare_and_swap_double_write */ +# ifdef AO_HAVE_char_fetch_compare_and_swap_write + (void)"AO_char_fetch_compare_and_swap_write(&val, oldval, newval):"; + if (AO_char_fetch_compare_and_swap_write(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_char_fetch_compare_and_swap_write"; +# endif + +# if defined(AO_HAVE_test_and_set_write) + (void)"AO_test_and_set_write(&ts):"; + (void)AO_test_and_set_write(&ts); +# else + (void)"No AO_test_and_set_write"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void char_list_atomic_full(void) +{ +# if defined(AO_HAVE_char_load_full) || defined(AO_HAVE_char_store_full) \ + || defined(AO_HAVE_char_fetch_and_add_full) \ + || defined(AO_HAVE_char_fetch_and_add1_full) \ + || defined(AO_HAVE_char_and_full) \ + || defined(AO_HAVE_char_compare_and_swap_full) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_full) + static volatile unsigned/**/char val /* = 0 */; +# endif +# if defined(AO_HAVE_char_compare_and_swap_full) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_full) + static unsigned/**/char oldval /* = 0 */; +# endif +# if defined(AO_HAVE_char_store_full) \ + || defined(AO_HAVE_char_compare_and_swap_full) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_full) + static unsigned/**/char newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_full) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_char_fetch_and_add_full) || defined(AO_HAVE_char_and_full) \ + || defined(AO_HAVE_char_or_full) || defined(AO_HAVE_char_xor_full) + static unsigned/**/char incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_full) + (void)"AO_nop_full(): "; + AO_nop_full(); +# else + (void)"No AO_nop_full"; +# endif + +# ifdef AO_HAVE_char_load_full + (void)"AO_char_load_full(&val):"; + (void)AO_char_load_full(&val); +# else + (void)"No AO_char_load_full"; +# endif +# ifdef AO_HAVE_char_store_full + (void)"AO_char_store_full(&val, newval):"; + AO_char_store_full(&val, newval); +# else + (void)"No AO_char_store_full"; +# endif +# ifdef AO_HAVE_char_fetch_and_add_full + (void)"AO_char_fetch_and_add_full(&val, incr):"; + (void)AO_char_fetch_and_add_full(&val, incr); +# else + (void)"No AO_char_fetch_and_add_full"; +# endif +# ifdef AO_HAVE_char_fetch_and_add1_full + (void)"AO_char_fetch_and_add1_full(&val):"; + (void)AO_char_fetch_and_add1_full(&val); +# else + (void)"No AO_char_fetch_and_add1_full"; +# endif +# ifdef AO_HAVE_char_fetch_and_sub1_full + (void)"AO_char_fetch_and_sub1_full(&val):"; + (void)AO_char_fetch_and_sub1_full(&val); +# else + (void)"No AO_char_fetch_and_sub1_full"; +# endif +# ifdef AO_HAVE_char_and_full + (void)"AO_char_and_full(&val, incr):"; + AO_char_and_full(&val, incr); +# else + (void)"No AO_char_and_full"; +# endif +# ifdef AO_HAVE_char_or_full + (void)"AO_char_or_full(&val, incr):"; + AO_char_or_full(&val, incr); +# else + (void)"No AO_char_or_full"; +# endif +# ifdef AO_HAVE_char_xor_full + (void)"AO_char_xor_full(&val, incr):"; + AO_char_xor_full(&val, incr); +# else + (void)"No AO_char_xor_full"; +# endif +# ifdef AO_HAVE_char_compare_and_swap_full + (void)"AO_char_compare_and_swap_full(&val, oldval, newval):"; + if (!AO_char_compare_and_swap_full(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_char_compare_and_swap_full"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_full */ + /* TODO: Add AO_compare_and_swap_double_full */ +# ifdef AO_HAVE_char_fetch_compare_and_swap_full + (void)"AO_char_fetch_compare_and_swap_full(&val, oldval, newval):"; + if (AO_char_fetch_compare_and_swap_full(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_char_fetch_compare_and_swap_full"; +# endif + +# if defined(AO_HAVE_test_and_set_full) + (void)"AO_test_and_set_full(&ts):"; + (void)AO_test_and_set_full(&ts); +# else + (void)"No AO_test_and_set_full"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void char_list_atomic_release_write(void) +{ +# if defined(AO_HAVE_char_load_release_write) || defined(AO_HAVE_char_store_release_write) \ + || defined(AO_HAVE_char_fetch_and_add_release_write) \ + || defined(AO_HAVE_char_fetch_and_add1_release_write) \ + || defined(AO_HAVE_char_and_release_write) \ + || defined(AO_HAVE_char_compare_and_swap_release_write) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_release_write) + static volatile unsigned/**/char val /* = 0 */; +# endif +# if defined(AO_HAVE_char_compare_and_swap_release_write) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_release_write) + static unsigned/**/char oldval /* = 0 */; +# endif +# if defined(AO_HAVE_char_store_release_write) \ + || defined(AO_HAVE_char_compare_and_swap_release_write) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_release_write) + static unsigned/**/char newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_release_write) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_char_fetch_and_add_release_write) || defined(AO_HAVE_char_and_release_write) \ + || defined(AO_HAVE_char_or_release_write) || defined(AO_HAVE_char_xor_release_write) + static unsigned/**/char incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_release_write) + (void)"AO_nop_release_write(): "; + AO_nop_release_write(); +# else + (void)"No AO_nop_release_write"; +# endif + +# ifdef AO_HAVE_char_load_release_write + (void)"AO_char_load_release_write(&val):"; + (void)AO_char_load_release_write(&val); +# else + (void)"No AO_char_load_release_write"; +# endif +# ifdef AO_HAVE_char_store_release_write + (void)"AO_char_store_release_write(&val, newval):"; + AO_char_store_release_write(&val, newval); +# else + (void)"No AO_char_store_release_write"; +# endif +# ifdef AO_HAVE_char_fetch_and_add_release_write + (void)"AO_char_fetch_and_add_release_write(&val, incr):"; + (void)AO_char_fetch_and_add_release_write(&val, incr); +# else + (void)"No AO_char_fetch_and_add_release_write"; +# endif +# ifdef AO_HAVE_char_fetch_and_add1_release_write + (void)"AO_char_fetch_and_add1_release_write(&val):"; + (void)AO_char_fetch_and_add1_release_write(&val); +# else + (void)"No AO_char_fetch_and_add1_release_write"; +# endif +# ifdef AO_HAVE_char_fetch_and_sub1_release_write + (void)"AO_char_fetch_and_sub1_release_write(&val):"; + (void)AO_char_fetch_and_sub1_release_write(&val); +# else + (void)"No AO_char_fetch_and_sub1_release_write"; +# endif +# ifdef AO_HAVE_char_and_release_write + (void)"AO_char_and_release_write(&val, incr):"; + AO_char_and_release_write(&val, incr); +# else + (void)"No AO_char_and_release_write"; +# endif +# ifdef AO_HAVE_char_or_release_write + (void)"AO_char_or_release_write(&val, incr):"; + AO_char_or_release_write(&val, incr); +# else + (void)"No AO_char_or_release_write"; +# endif +# ifdef AO_HAVE_char_xor_release_write + (void)"AO_char_xor_release_write(&val, incr):"; + AO_char_xor_release_write(&val, incr); +# else + (void)"No AO_char_xor_release_write"; +# endif +# ifdef AO_HAVE_char_compare_and_swap_release_write + (void)"AO_char_compare_and_swap_release_write(&val, oldval, newval):"; + if (!AO_char_compare_and_swap_release_write(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_char_compare_and_swap_release_write"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_release_write */ + /* TODO: Add AO_compare_and_swap_double_release_write */ +# ifdef AO_HAVE_char_fetch_compare_and_swap_release_write + (void)"AO_char_fetch_compare_and_swap_release_write(&val, oldval, newval):"; + if (AO_char_fetch_compare_and_swap_release_write(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_char_fetch_compare_and_swap_release_write"; +# endif + +# if defined(AO_HAVE_test_and_set_release_write) + (void)"AO_test_and_set_release_write(&ts):"; + (void)AO_test_and_set_release_write(&ts); +# else + (void)"No AO_test_and_set_release_write"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void char_list_atomic_acquire_read(void) +{ +# if defined(AO_HAVE_char_load_acquire_read) || defined(AO_HAVE_char_store_acquire_read) \ + || defined(AO_HAVE_char_fetch_and_add_acquire_read) \ + || defined(AO_HAVE_char_fetch_and_add1_acquire_read) \ + || defined(AO_HAVE_char_and_acquire_read) \ + || defined(AO_HAVE_char_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_acquire_read) + static volatile unsigned/**/char val /* = 0 */; +# endif +# if defined(AO_HAVE_char_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_acquire_read) + static unsigned/**/char oldval /* = 0 */; +# endif +# if defined(AO_HAVE_char_store_acquire_read) \ + || defined(AO_HAVE_char_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_acquire_read) + static unsigned/**/char newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_acquire_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_char_fetch_and_add_acquire_read) || defined(AO_HAVE_char_and_acquire_read) \ + || defined(AO_HAVE_char_or_acquire_read) || defined(AO_HAVE_char_xor_acquire_read) + static unsigned/**/char incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_acquire_read) + (void)"AO_nop_acquire_read(): "; + AO_nop_acquire_read(); +# else + (void)"No AO_nop_acquire_read"; +# endif + +# ifdef AO_HAVE_char_load_acquire_read + (void)"AO_char_load_acquire_read(&val):"; + (void)AO_char_load_acquire_read(&val); +# else + (void)"No AO_char_load_acquire_read"; +# endif +# ifdef AO_HAVE_char_store_acquire_read + (void)"AO_char_store_acquire_read(&val, newval):"; + AO_char_store_acquire_read(&val, newval); +# else + (void)"No AO_char_store_acquire_read"; +# endif +# ifdef AO_HAVE_char_fetch_and_add_acquire_read + (void)"AO_char_fetch_and_add_acquire_read(&val, incr):"; + (void)AO_char_fetch_and_add_acquire_read(&val, incr); +# else + (void)"No AO_char_fetch_and_add_acquire_read"; +# endif +# ifdef AO_HAVE_char_fetch_and_add1_acquire_read + (void)"AO_char_fetch_and_add1_acquire_read(&val):"; + (void)AO_char_fetch_and_add1_acquire_read(&val); +# else + (void)"No AO_char_fetch_and_add1_acquire_read"; +# endif +# ifdef AO_HAVE_char_fetch_and_sub1_acquire_read + (void)"AO_char_fetch_and_sub1_acquire_read(&val):"; + (void)AO_char_fetch_and_sub1_acquire_read(&val); +# else + (void)"No AO_char_fetch_and_sub1_acquire_read"; +# endif +# ifdef AO_HAVE_char_and_acquire_read + (void)"AO_char_and_acquire_read(&val, incr):"; + AO_char_and_acquire_read(&val, incr); +# else + (void)"No AO_char_and_acquire_read"; +# endif +# ifdef AO_HAVE_char_or_acquire_read + (void)"AO_char_or_acquire_read(&val, incr):"; + AO_char_or_acquire_read(&val, incr); +# else + (void)"No AO_char_or_acquire_read"; +# endif +# ifdef AO_HAVE_char_xor_acquire_read + (void)"AO_char_xor_acquire_read(&val, incr):"; + AO_char_xor_acquire_read(&val, incr); +# else + (void)"No AO_char_xor_acquire_read"; +# endif +# ifdef AO_HAVE_char_compare_and_swap_acquire_read + (void)"AO_char_compare_and_swap_acquire_read(&val, oldval, newval):"; + if (!AO_char_compare_and_swap_acquire_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_char_compare_and_swap_acquire_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_acquire_read */ + /* TODO: Add AO_compare_and_swap_double_acquire_read */ +# ifdef AO_HAVE_char_fetch_compare_and_swap_acquire_read + (void)"AO_char_fetch_compare_and_swap_acquire_read(&val, oldval, newval):"; + if (AO_char_fetch_compare_and_swap_acquire_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_char_fetch_compare_and_swap_acquire_read"; +# endif + +# if defined(AO_HAVE_test_and_set_acquire_read) + (void)"AO_test_and_set_acquire_read(&ts):"; + (void)AO_test_and_set_acquire_read(&ts); +# else + (void)"No AO_test_and_set_acquire_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void char_list_atomic_dd_acquire_read(void) +{ +# if defined(AO_HAVE_char_load_dd_acquire_read) || defined(AO_HAVE_char_store_dd_acquire_read) \ + || defined(AO_HAVE_char_fetch_and_add_dd_acquire_read) \ + || defined(AO_HAVE_char_fetch_and_add1_dd_acquire_read) \ + || defined(AO_HAVE_char_and_dd_acquire_read) \ + || defined(AO_HAVE_char_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_dd_acquire_read) + static volatile unsigned/**/char val /* = 0 */; +# endif +# if defined(AO_HAVE_char_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_dd_acquire_read) + static unsigned/**/char oldval /* = 0 */; +# endif +# if defined(AO_HAVE_char_store_dd_acquire_read) \ + || defined(AO_HAVE_char_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_char_fetch_compare_and_swap_dd_acquire_read) + static unsigned/**/char newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_char_fetch_and_add_dd_acquire_read) || defined(AO_HAVE_char_and_dd_acquire_read) \ + || defined(AO_HAVE_char_or_dd_acquire_read) || defined(AO_HAVE_char_xor_dd_acquire_read) + static unsigned/**/char incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_dd_acquire_read) + (void)"AO_nop_dd_acquire_read(): "; + AO_nop_dd_acquire_read(); +# else + (void)"No AO_nop_dd_acquire_read"; +# endif + +# ifdef AO_HAVE_char_load_dd_acquire_read + (void)"AO_char_load_dd_acquire_read(&val):"; + (void)AO_char_load_dd_acquire_read(&val); +# else + (void)"No AO_char_load_dd_acquire_read"; +# endif +# ifdef AO_HAVE_char_store_dd_acquire_read + (void)"AO_char_store_dd_acquire_read(&val, newval):"; + AO_char_store_dd_acquire_read(&val, newval); +# else + (void)"No AO_char_store_dd_acquire_read"; +# endif +# ifdef AO_HAVE_char_fetch_and_add_dd_acquire_read + (void)"AO_char_fetch_and_add_dd_acquire_read(&val, incr):"; + (void)AO_char_fetch_and_add_dd_acquire_read(&val, incr); +# else + (void)"No AO_char_fetch_and_add_dd_acquire_read"; +# endif +# ifdef AO_HAVE_char_fetch_and_add1_dd_acquire_read + (void)"AO_char_fetch_and_add1_dd_acquire_read(&val):"; + (void)AO_char_fetch_and_add1_dd_acquire_read(&val); +# else + (void)"No AO_char_fetch_and_add1_dd_acquire_read"; +# endif +# ifdef AO_HAVE_char_fetch_and_sub1_dd_acquire_read + (void)"AO_char_fetch_and_sub1_dd_acquire_read(&val):"; + (void)AO_char_fetch_and_sub1_dd_acquire_read(&val); +# else + (void)"No AO_char_fetch_and_sub1_dd_acquire_read"; +# endif +# ifdef AO_HAVE_char_and_dd_acquire_read + (void)"AO_char_and_dd_acquire_read(&val, incr):"; + AO_char_and_dd_acquire_read(&val, incr); +# else + (void)"No AO_char_and_dd_acquire_read"; +# endif +# ifdef AO_HAVE_char_or_dd_acquire_read + (void)"AO_char_or_dd_acquire_read(&val, incr):"; + AO_char_or_dd_acquire_read(&val, incr); +# else + (void)"No AO_char_or_dd_acquire_read"; +# endif +# ifdef AO_HAVE_char_xor_dd_acquire_read + (void)"AO_char_xor_dd_acquire_read(&val, incr):"; + AO_char_xor_dd_acquire_read(&val, incr); +# else + (void)"No AO_char_xor_dd_acquire_read"; +# endif +# ifdef AO_HAVE_char_compare_and_swap_dd_acquire_read + (void)"AO_char_compare_and_swap_dd_acquire_read(&val, oldval, newval):"; + if (!AO_char_compare_and_swap_dd_acquire_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_char_compare_and_swap_dd_acquire_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_dd_acquire_read */ + /* TODO: Add AO_compare_and_swap_double_dd_acquire_read */ +# ifdef AO_HAVE_char_fetch_compare_and_swap_dd_acquire_read + (void)"AO_char_fetch_compare_and_swap_dd_acquire_read(&val, oldval, newval):"; + if (AO_char_fetch_compare_and_swap_dd_acquire_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_char_fetch_compare_and_swap_dd_acquire_read"; +# endif + +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + (void)"AO_test_and_set_dd_acquire_read(&ts):"; + (void)AO_test_and_set_dd_acquire_read(&ts); +# else + (void)"No AO_test_and_set_dd_acquire_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void short_list_atomic(void) +{ +# if defined(AO_HAVE_short_load) || defined(AO_HAVE_short_store) \ + || defined(AO_HAVE_short_fetch_and_add) \ + || defined(AO_HAVE_short_fetch_and_add1) \ + || defined(AO_HAVE_short_and) \ + || defined(AO_HAVE_short_compare_and_swap) \ + || defined(AO_HAVE_short_fetch_compare_and_swap) + static volatile unsigned/**/short val /* = 0 */; +# endif +# if defined(AO_HAVE_short_compare_and_swap) \ + || defined(AO_HAVE_short_fetch_compare_and_swap) + static unsigned/**/short oldval /* = 0 */; +# endif +# if defined(AO_HAVE_short_store) \ + || defined(AO_HAVE_short_compare_and_swap) \ + || defined(AO_HAVE_short_fetch_compare_and_swap) + static unsigned/**/short newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_short_fetch_and_add) || defined(AO_HAVE_short_and) \ + || defined(AO_HAVE_short_or) || defined(AO_HAVE_short_xor) + static unsigned/**/short incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop) + (void)"AO_nop(): "; + AO_nop(); +# else + (void)"No AO_nop"; +# endif + +# ifdef AO_HAVE_short_load + (void)"AO_short_load(&val):"; + (void)AO_short_load(&val); +# else + (void)"No AO_short_load"; +# endif +# ifdef AO_HAVE_short_store + (void)"AO_short_store(&val, newval):"; + AO_short_store(&val, newval); +# else + (void)"No AO_short_store"; +# endif +# ifdef AO_HAVE_short_fetch_and_add + (void)"AO_short_fetch_and_add(&val, incr):"; + (void)AO_short_fetch_and_add(&val, incr); +# else + (void)"No AO_short_fetch_and_add"; +# endif +# ifdef AO_HAVE_short_fetch_and_add1 + (void)"AO_short_fetch_and_add1(&val):"; + (void)AO_short_fetch_and_add1(&val); +# else + (void)"No AO_short_fetch_and_add1"; +# endif +# ifdef AO_HAVE_short_fetch_and_sub1 + (void)"AO_short_fetch_and_sub1(&val):"; + (void)AO_short_fetch_and_sub1(&val); +# else + (void)"No AO_short_fetch_and_sub1"; +# endif +# ifdef AO_HAVE_short_and + (void)"AO_short_and(&val, incr):"; + AO_short_and(&val, incr); +# else + (void)"No AO_short_and"; +# endif +# ifdef AO_HAVE_short_or + (void)"AO_short_or(&val, incr):"; + AO_short_or(&val, incr); +# else + (void)"No AO_short_or"; +# endif +# ifdef AO_HAVE_short_xor + (void)"AO_short_xor(&val, incr):"; + AO_short_xor(&val, incr); +# else + (void)"No AO_short_xor"; +# endif +# ifdef AO_HAVE_short_compare_and_swap + (void)"AO_short_compare_and_swap(&val, oldval, newval):"; + if (!AO_short_compare_and_swap(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_short_compare_and_swap"; +# endif + /* TODO: Add AO_compare_double_and_swap_double */ + /* TODO: Add AO_compare_and_swap_double */ +# ifdef AO_HAVE_short_fetch_compare_and_swap + (void)"AO_short_fetch_compare_and_swap(&val, oldval, newval):"; + if (AO_short_fetch_compare_and_swap(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_short_fetch_compare_and_swap"; +# endif + +# if defined(AO_HAVE_test_and_set) + (void)"AO_test_and_set(&ts):"; + (void)AO_test_and_set(&ts); +# else + (void)"No AO_test_and_set"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void short_list_atomic_release(void) +{ +# if defined(AO_HAVE_short_load_release) || defined(AO_HAVE_short_store_release) \ + || defined(AO_HAVE_short_fetch_and_add_release) \ + || defined(AO_HAVE_short_fetch_and_add1_release) \ + || defined(AO_HAVE_short_and_release) \ + || defined(AO_HAVE_short_compare_and_swap_release) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_release) + static volatile unsigned/**/short val /* = 0 */; +# endif +# if defined(AO_HAVE_short_compare_and_swap_release) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_release) + static unsigned/**/short oldval /* = 0 */; +# endif +# if defined(AO_HAVE_short_store_release) \ + || defined(AO_HAVE_short_compare_and_swap_release) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_release) + static unsigned/**/short newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_release) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_short_fetch_and_add_release) || defined(AO_HAVE_short_and_release) \ + || defined(AO_HAVE_short_or_release) || defined(AO_HAVE_short_xor_release) + static unsigned/**/short incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_release) + (void)"AO_nop_release(): "; + AO_nop_release(); +# else + (void)"No AO_nop_release"; +# endif + +# ifdef AO_HAVE_short_load_release + (void)"AO_short_load_release(&val):"; + (void)AO_short_load_release(&val); +# else + (void)"No AO_short_load_release"; +# endif +# ifdef AO_HAVE_short_store_release + (void)"AO_short_store_release(&val, newval):"; + AO_short_store_release(&val, newval); +# else + (void)"No AO_short_store_release"; +# endif +# ifdef AO_HAVE_short_fetch_and_add_release + (void)"AO_short_fetch_and_add_release(&val, incr):"; + (void)AO_short_fetch_and_add_release(&val, incr); +# else + (void)"No AO_short_fetch_and_add_release"; +# endif +# ifdef AO_HAVE_short_fetch_and_add1_release + (void)"AO_short_fetch_and_add1_release(&val):"; + (void)AO_short_fetch_and_add1_release(&val); +# else + (void)"No AO_short_fetch_and_add1_release"; +# endif +# ifdef AO_HAVE_short_fetch_and_sub1_release + (void)"AO_short_fetch_and_sub1_release(&val):"; + (void)AO_short_fetch_and_sub1_release(&val); +# else + (void)"No AO_short_fetch_and_sub1_release"; +# endif +# ifdef AO_HAVE_short_and_release + (void)"AO_short_and_release(&val, incr):"; + AO_short_and_release(&val, incr); +# else + (void)"No AO_short_and_release"; +# endif +# ifdef AO_HAVE_short_or_release + (void)"AO_short_or_release(&val, incr):"; + AO_short_or_release(&val, incr); +# else + (void)"No AO_short_or_release"; +# endif +# ifdef AO_HAVE_short_xor_release + (void)"AO_short_xor_release(&val, incr):"; + AO_short_xor_release(&val, incr); +# else + (void)"No AO_short_xor_release"; +# endif +# ifdef AO_HAVE_short_compare_and_swap_release + (void)"AO_short_compare_and_swap_release(&val, oldval, newval):"; + if (!AO_short_compare_and_swap_release(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_short_compare_and_swap_release"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_release */ + /* TODO: Add AO_compare_and_swap_double_release */ +# ifdef AO_HAVE_short_fetch_compare_and_swap_release + (void)"AO_short_fetch_compare_and_swap_release(&val, oldval, newval):"; + if (AO_short_fetch_compare_and_swap_release(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_short_fetch_compare_and_swap_release"; +# endif + +# if defined(AO_HAVE_test_and_set_release) + (void)"AO_test_and_set_release(&ts):"; + (void)AO_test_and_set_release(&ts); +# else + (void)"No AO_test_and_set_release"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void short_list_atomic_acquire(void) +{ +# if defined(AO_HAVE_short_load_acquire) || defined(AO_HAVE_short_store_acquire) \ + || defined(AO_HAVE_short_fetch_and_add_acquire) \ + || defined(AO_HAVE_short_fetch_and_add1_acquire) \ + || defined(AO_HAVE_short_and_acquire) \ + || defined(AO_HAVE_short_compare_and_swap_acquire) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_acquire) + static volatile unsigned/**/short val /* = 0 */; +# endif +# if defined(AO_HAVE_short_compare_and_swap_acquire) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_acquire) + static unsigned/**/short oldval /* = 0 */; +# endif +# if defined(AO_HAVE_short_store_acquire) \ + || defined(AO_HAVE_short_compare_and_swap_acquire) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_acquire) + static unsigned/**/short newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_acquire) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_short_fetch_and_add_acquire) || defined(AO_HAVE_short_and_acquire) \ + || defined(AO_HAVE_short_or_acquire) || defined(AO_HAVE_short_xor_acquire) + static unsigned/**/short incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_acquire) + (void)"AO_nop_acquire(): "; + AO_nop_acquire(); +# else + (void)"No AO_nop_acquire"; +# endif + +# ifdef AO_HAVE_short_load_acquire + (void)"AO_short_load_acquire(&val):"; + (void)AO_short_load_acquire(&val); +# else + (void)"No AO_short_load_acquire"; +# endif +# ifdef AO_HAVE_short_store_acquire + (void)"AO_short_store_acquire(&val, newval):"; + AO_short_store_acquire(&val, newval); +# else + (void)"No AO_short_store_acquire"; +# endif +# ifdef AO_HAVE_short_fetch_and_add_acquire + (void)"AO_short_fetch_and_add_acquire(&val, incr):"; + (void)AO_short_fetch_and_add_acquire(&val, incr); +# else + (void)"No AO_short_fetch_and_add_acquire"; +# endif +# ifdef AO_HAVE_short_fetch_and_add1_acquire + (void)"AO_short_fetch_and_add1_acquire(&val):"; + (void)AO_short_fetch_and_add1_acquire(&val); +# else + (void)"No AO_short_fetch_and_add1_acquire"; +# endif +# ifdef AO_HAVE_short_fetch_and_sub1_acquire + (void)"AO_short_fetch_and_sub1_acquire(&val):"; + (void)AO_short_fetch_and_sub1_acquire(&val); +# else + (void)"No AO_short_fetch_and_sub1_acquire"; +# endif +# ifdef AO_HAVE_short_and_acquire + (void)"AO_short_and_acquire(&val, incr):"; + AO_short_and_acquire(&val, incr); +# else + (void)"No AO_short_and_acquire"; +# endif +# ifdef AO_HAVE_short_or_acquire + (void)"AO_short_or_acquire(&val, incr):"; + AO_short_or_acquire(&val, incr); +# else + (void)"No AO_short_or_acquire"; +# endif +# ifdef AO_HAVE_short_xor_acquire + (void)"AO_short_xor_acquire(&val, incr):"; + AO_short_xor_acquire(&val, incr); +# else + (void)"No AO_short_xor_acquire"; +# endif +# ifdef AO_HAVE_short_compare_and_swap_acquire + (void)"AO_short_compare_and_swap_acquire(&val, oldval, newval):"; + if (!AO_short_compare_and_swap_acquire(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_short_compare_and_swap_acquire"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_acquire */ + /* TODO: Add AO_compare_and_swap_double_acquire */ +# ifdef AO_HAVE_short_fetch_compare_and_swap_acquire + (void)"AO_short_fetch_compare_and_swap_acquire(&val, oldval, newval):"; + if (AO_short_fetch_compare_and_swap_acquire(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_short_fetch_compare_and_swap_acquire"; +# endif + +# if defined(AO_HAVE_test_and_set_acquire) + (void)"AO_test_and_set_acquire(&ts):"; + (void)AO_test_and_set_acquire(&ts); +# else + (void)"No AO_test_and_set_acquire"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void short_list_atomic_read(void) +{ +# if defined(AO_HAVE_short_load_read) || defined(AO_HAVE_short_store_read) \ + || defined(AO_HAVE_short_fetch_and_add_read) \ + || defined(AO_HAVE_short_fetch_and_add1_read) \ + || defined(AO_HAVE_short_and_read) \ + || defined(AO_HAVE_short_compare_and_swap_read) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_read) + static volatile unsigned/**/short val /* = 0 */; +# endif +# if defined(AO_HAVE_short_compare_and_swap_read) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_read) + static unsigned/**/short oldval /* = 0 */; +# endif +# if defined(AO_HAVE_short_store_read) \ + || defined(AO_HAVE_short_compare_and_swap_read) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_read) + static unsigned/**/short newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_short_fetch_and_add_read) || defined(AO_HAVE_short_and_read) \ + || defined(AO_HAVE_short_or_read) || defined(AO_HAVE_short_xor_read) + static unsigned/**/short incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_read) + (void)"AO_nop_read(): "; + AO_nop_read(); +# else + (void)"No AO_nop_read"; +# endif + +# ifdef AO_HAVE_short_load_read + (void)"AO_short_load_read(&val):"; + (void)AO_short_load_read(&val); +# else + (void)"No AO_short_load_read"; +# endif +# ifdef AO_HAVE_short_store_read + (void)"AO_short_store_read(&val, newval):"; + AO_short_store_read(&val, newval); +# else + (void)"No AO_short_store_read"; +# endif +# ifdef AO_HAVE_short_fetch_and_add_read + (void)"AO_short_fetch_and_add_read(&val, incr):"; + (void)AO_short_fetch_and_add_read(&val, incr); +# else + (void)"No AO_short_fetch_and_add_read"; +# endif +# ifdef AO_HAVE_short_fetch_and_add1_read + (void)"AO_short_fetch_and_add1_read(&val):"; + (void)AO_short_fetch_and_add1_read(&val); +# else + (void)"No AO_short_fetch_and_add1_read"; +# endif +# ifdef AO_HAVE_short_fetch_and_sub1_read + (void)"AO_short_fetch_and_sub1_read(&val):"; + (void)AO_short_fetch_and_sub1_read(&val); +# else + (void)"No AO_short_fetch_and_sub1_read"; +# endif +# ifdef AO_HAVE_short_and_read + (void)"AO_short_and_read(&val, incr):"; + AO_short_and_read(&val, incr); +# else + (void)"No AO_short_and_read"; +# endif +# ifdef AO_HAVE_short_or_read + (void)"AO_short_or_read(&val, incr):"; + AO_short_or_read(&val, incr); +# else + (void)"No AO_short_or_read"; +# endif +# ifdef AO_HAVE_short_xor_read + (void)"AO_short_xor_read(&val, incr):"; + AO_short_xor_read(&val, incr); +# else + (void)"No AO_short_xor_read"; +# endif +# ifdef AO_HAVE_short_compare_and_swap_read + (void)"AO_short_compare_and_swap_read(&val, oldval, newval):"; + if (!AO_short_compare_and_swap_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_short_compare_and_swap_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_read */ + /* TODO: Add AO_compare_and_swap_double_read */ +# ifdef AO_HAVE_short_fetch_compare_and_swap_read + (void)"AO_short_fetch_compare_and_swap_read(&val, oldval, newval):"; + if (AO_short_fetch_compare_and_swap_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_short_fetch_compare_and_swap_read"; +# endif + +# if defined(AO_HAVE_test_and_set_read) + (void)"AO_test_and_set_read(&ts):"; + (void)AO_test_and_set_read(&ts); +# else + (void)"No AO_test_and_set_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void short_list_atomic_write(void) +{ +# if defined(AO_HAVE_short_load_write) || defined(AO_HAVE_short_store_write) \ + || defined(AO_HAVE_short_fetch_and_add_write) \ + || defined(AO_HAVE_short_fetch_and_add1_write) \ + || defined(AO_HAVE_short_and_write) \ + || defined(AO_HAVE_short_compare_and_swap_write) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_write) + static volatile unsigned/**/short val /* = 0 */; +# endif +# if defined(AO_HAVE_short_compare_and_swap_write) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_write) + static unsigned/**/short oldval /* = 0 */; +# endif +# if defined(AO_HAVE_short_store_write) \ + || defined(AO_HAVE_short_compare_and_swap_write) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_write) + static unsigned/**/short newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_write) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_short_fetch_and_add_write) || defined(AO_HAVE_short_and_write) \ + || defined(AO_HAVE_short_or_write) || defined(AO_HAVE_short_xor_write) + static unsigned/**/short incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_write) + (void)"AO_nop_write(): "; + AO_nop_write(); +# else + (void)"No AO_nop_write"; +# endif + +# ifdef AO_HAVE_short_load_write + (void)"AO_short_load_write(&val):"; + (void)AO_short_load_write(&val); +# else + (void)"No AO_short_load_write"; +# endif +# ifdef AO_HAVE_short_store_write + (void)"AO_short_store_write(&val, newval):"; + AO_short_store_write(&val, newval); +# else + (void)"No AO_short_store_write"; +# endif +# ifdef AO_HAVE_short_fetch_and_add_write + (void)"AO_short_fetch_and_add_write(&val, incr):"; + (void)AO_short_fetch_and_add_write(&val, incr); +# else + (void)"No AO_short_fetch_and_add_write"; +# endif +# ifdef AO_HAVE_short_fetch_and_add1_write + (void)"AO_short_fetch_and_add1_write(&val):"; + (void)AO_short_fetch_and_add1_write(&val); +# else + (void)"No AO_short_fetch_and_add1_write"; +# endif +# ifdef AO_HAVE_short_fetch_and_sub1_write + (void)"AO_short_fetch_and_sub1_write(&val):"; + (void)AO_short_fetch_and_sub1_write(&val); +# else + (void)"No AO_short_fetch_and_sub1_write"; +# endif +# ifdef AO_HAVE_short_and_write + (void)"AO_short_and_write(&val, incr):"; + AO_short_and_write(&val, incr); +# else + (void)"No AO_short_and_write"; +# endif +# ifdef AO_HAVE_short_or_write + (void)"AO_short_or_write(&val, incr):"; + AO_short_or_write(&val, incr); +# else + (void)"No AO_short_or_write"; +# endif +# ifdef AO_HAVE_short_xor_write + (void)"AO_short_xor_write(&val, incr):"; + AO_short_xor_write(&val, incr); +# else + (void)"No AO_short_xor_write"; +# endif +# ifdef AO_HAVE_short_compare_and_swap_write + (void)"AO_short_compare_and_swap_write(&val, oldval, newval):"; + if (!AO_short_compare_and_swap_write(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_short_compare_and_swap_write"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_write */ + /* TODO: Add AO_compare_and_swap_double_write */ +# ifdef AO_HAVE_short_fetch_compare_and_swap_write + (void)"AO_short_fetch_compare_and_swap_write(&val, oldval, newval):"; + if (AO_short_fetch_compare_and_swap_write(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_short_fetch_compare_and_swap_write"; +# endif + +# if defined(AO_HAVE_test_and_set_write) + (void)"AO_test_and_set_write(&ts):"; + (void)AO_test_and_set_write(&ts); +# else + (void)"No AO_test_and_set_write"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void short_list_atomic_full(void) +{ +# if defined(AO_HAVE_short_load_full) || defined(AO_HAVE_short_store_full) \ + || defined(AO_HAVE_short_fetch_and_add_full) \ + || defined(AO_HAVE_short_fetch_and_add1_full) \ + || defined(AO_HAVE_short_and_full) \ + || defined(AO_HAVE_short_compare_and_swap_full) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_full) + static volatile unsigned/**/short val /* = 0 */; +# endif +# if defined(AO_HAVE_short_compare_and_swap_full) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_full) + static unsigned/**/short oldval /* = 0 */; +# endif +# if defined(AO_HAVE_short_store_full) \ + || defined(AO_HAVE_short_compare_and_swap_full) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_full) + static unsigned/**/short newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_full) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_short_fetch_and_add_full) || defined(AO_HAVE_short_and_full) \ + || defined(AO_HAVE_short_or_full) || defined(AO_HAVE_short_xor_full) + static unsigned/**/short incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_full) + (void)"AO_nop_full(): "; + AO_nop_full(); +# else + (void)"No AO_nop_full"; +# endif + +# ifdef AO_HAVE_short_load_full + (void)"AO_short_load_full(&val):"; + (void)AO_short_load_full(&val); +# else + (void)"No AO_short_load_full"; +# endif +# ifdef AO_HAVE_short_store_full + (void)"AO_short_store_full(&val, newval):"; + AO_short_store_full(&val, newval); +# else + (void)"No AO_short_store_full"; +# endif +# ifdef AO_HAVE_short_fetch_and_add_full + (void)"AO_short_fetch_and_add_full(&val, incr):"; + (void)AO_short_fetch_and_add_full(&val, incr); +# else + (void)"No AO_short_fetch_and_add_full"; +# endif +# ifdef AO_HAVE_short_fetch_and_add1_full + (void)"AO_short_fetch_and_add1_full(&val):"; + (void)AO_short_fetch_and_add1_full(&val); +# else + (void)"No AO_short_fetch_and_add1_full"; +# endif +# ifdef AO_HAVE_short_fetch_and_sub1_full + (void)"AO_short_fetch_and_sub1_full(&val):"; + (void)AO_short_fetch_and_sub1_full(&val); +# else + (void)"No AO_short_fetch_and_sub1_full"; +# endif +# ifdef AO_HAVE_short_and_full + (void)"AO_short_and_full(&val, incr):"; + AO_short_and_full(&val, incr); +# else + (void)"No AO_short_and_full"; +# endif +# ifdef AO_HAVE_short_or_full + (void)"AO_short_or_full(&val, incr):"; + AO_short_or_full(&val, incr); +# else + (void)"No AO_short_or_full"; +# endif +# ifdef AO_HAVE_short_xor_full + (void)"AO_short_xor_full(&val, incr):"; + AO_short_xor_full(&val, incr); +# else + (void)"No AO_short_xor_full"; +# endif +# ifdef AO_HAVE_short_compare_and_swap_full + (void)"AO_short_compare_and_swap_full(&val, oldval, newval):"; + if (!AO_short_compare_and_swap_full(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_short_compare_and_swap_full"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_full */ + /* TODO: Add AO_compare_and_swap_double_full */ +# ifdef AO_HAVE_short_fetch_compare_and_swap_full + (void)"AO_short_fetch_compare_and_swap_full(&val, oldval, newval):"; + if (AO_short_fetch_compare_and_swap_full(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_short_fetch_compare_and_swap_full"; +# endif + +# if defined(AO_HAVE_test_and_set_full) + (void)"AO_test_and_set_full(&ts):"; + (void)AO_test_and_set_full(&ts); +# else + (void)"No AO_test_and_set_full"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void short_list_atomic_release_write(void) +{ +# if defined(AO_HAVE_short_load_release_write) || defined(AO_HAVE_short_store_release_write) \ + || defined(AO_HAVE_short_fetch_and_add_release_write) \ + || defined(AO_HAVE_short_fetch_and_add1_release_write) \ + || defined(AO_HAVE_short_and_release_write) \ + || defined(AO_HAVE_short_compare_and_swap_release_write) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_release_write) + static volatile unsigned/**/short val /* = 0 */; +# endif +# if defined(AO_HAVE_short_compare_and_swap_release_write) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_release_write) + static unsigned/**/short oldval /* = 0 */; +# endif +# if defined(AO_HAVE_short_store_release_write) \ + || defined(AO_HAVE_short_compare_and_swap_release_write) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_release_write) + static unsigned/**/short newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_release_write) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_short_fetch_and_add_release_write) || defined(AO_HAVE_short_and_release_write) \ + || defined(AO_HAVE_short_or_release_write) || defined(AO_HAVE_short_xor_release_write) + static unsigned/**/short incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_release_write) + (void)"AO_nop_release_write(): "; + AO_nop_release_write(); +# else + (void)"No AO_nop_release_write"; +# endif + +# ifdef AO_HAVE_short_load_release_write + (void)"AO_short_load_release_write(&val):"; + (void)AO_short_load_release_write(&val); +# else + (void)"No AO_short_load_release_write"; +# endif +# ifdef AO_HAVE_short_store_release_write + (void)"AO_short_store_release_write(&val, newval):"; + AO_short_store_release_write(&val, newval); +# else + (void)"No AO_short_store_release_write"; +# endif +# ifdef AO_HAVE_short_fetch_and_add_release_write + (void)"AO_short_fetch_and_add_release_write(&val, incr):"; + (void)AO_short_fetch_and_add_release_write(&val, incr); +# else + (void)"No AO_short_fetch_and_add_release_write"; +# endif +# ifdef AO_HAVE_short_fetch_and_add1_release_write + (void)"AO_short_fetch_and_add1_release_write(&val):"; + (void)AO_short_fetch_and_add1_release_write(&val); +# else + (void)"No AO_short_fetch_and_add1_release_write"; +# endif +# ifdef AO_HAVE_short_fetch_and_sub1_release_write + (void)"AO_short_fetch_and_sub1_release_write(&val):"; + (void)AO_short_fetch_and_sub1_release_write(&val); +# else + (void)"No AO_short_fetch_and_sub1_release_write"; +# endif +# ifdef AO_HAVE_short_and_release_write + (void)"AO_short_and_release_write(&val, incr):"; + AO_short_and_release_write(&val, incr); +# else + (void)"No AO_short_and_release_write"; +# endif +# ifdef AO_HAVE_short_or_release_write + (void)"AO_short_or_release_write(&val, incr):"; + AO_short_or_release_write(&val, incr); +# else + (void)"No AO_short_or_release_write"; +# endif +# ifdef AO_HAVE_short_xor_release_write + (void)"AO_short_xor_release_write(&val, incr):"; + AO_short_xor_release_write(&val, incr); +# else + (void)"No AO_short_xor_release_write"; +# endif +# ifdef AO_HAVE_short_compare_and_swap_release_write + (void)"AO_short_compare_and_swap_release_write(&val, oldval, newval):"; + if (!AO_short_compare_and_swap_release_write(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_short_compare_and_swap_release_write"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_release_write */ + /* TODO: Add AO_compare_and_swap_double_release_write */ +# ifdef AO_HAVE_short_fetch_compare_and_swap_release_write + (void)"AO_short_fetch_compare_and_swap_release_write(&val, oldval, newval):"; + if (AO_short_fetch_compare_and_swap_release_write(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_short_fetch_compare_and_swap_release_write"; +# endif + +# if defined(AO_HAVE_test_and_set_release_write) + (void)"AO_test_and_set_release_write(&ts):"; + (void)AO_test_and_set_release_write(&ts); +# else + (void)"No AO_test_and_set_release_write"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void short_list_atomic_acquire_read(void) +{ +# if defined(AO_HAVE_short_load_acquire_read) || defined(AO_HAVE_short_store_acquire_read) \ + || defined(AO_HAVE_short_fetch_and_add_acquire_read) \ + || defined(AO_HAVE_short_fetch_and_add1_acquire_read) \ + || defined(AO_HAVE_short_and_acquire_read) \ + || defined(AO_HAVE_short_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_acquire_read) + static volatile unsigned/**/short val /* = 0 */; +# endif +# if defined(AO_HAVE_short_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_acquire_read) + static unsigned/**/short oldval /* = 0 */; +# endif +# if defined(AO_HAVE_short_store_acquire_read) \ + || defined(AO_HAVE_short_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_acquire_read) + static unsigned/**/short newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_acquire_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_short_fetch_and_add_acquire_read) || defined(AO_HAVE_short_and_acquire_read) \ + || defined(AO_HAVE_short_or_acquire_read) || defined(AO_HAVE_short_xor_acquire_read) + static unsigned/**/short incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_acquire_read) + (void)"AO_nop_acquire_read(): "; + AO_nop_acquire_read(); +# else + (void)"No AO_nop_acquire_read"; +# endif + +# ifdef AO_HAVE_short_load_acquire_read + (void)"AO_short_load_acquire_read(&val):"; + (void)AO_short_load_acquire_read(&val); +# else + (void)"No AO_short_load_acquire_read"; +# endif +# ifdef AO_HAVE_short_store_acquire_read + (void)"AO_short_store_acquire_read(&val, newval):"; + AO_short_store_acquire_read(&val, newval); +# else + (void)"No AO_short_store_acquire_read"; +# endif +# ifdef AO_HAVE_short_fetch_and_add_acquire_read + (void)"AO_short_fetch_and_add_acquire_read(&val, incr):"; + (void)AO_short_fetch_and_add_acquire_read(&val, incr); +# else + (void)"No AO_short_fetch_and_add_acquire_read"; +# endif +# ifdef AO_HAVE_short_fetch_and_add1_acquire_read + (void)"AO_short_fetch_and_add1_acquire_read(&val):"; + (void)AO_short_fetch_and_add1_acquire_read(&val); +# else + (void)"No AO_short_fetch_and_add1_acquire_read"; +# endif +# ifdef AO_HAVE_short_fetch_and_sub1_acquire_read + (void)"AO_short_fetch_and_sub1_acquire_read(&val):"; + (void)AO_short_fetch_and_sub1_acquire_read(&val); +# else + (void)"No AO_short_fetch_and_sub1_acquire_read"; +# endif +# ifdef AO_HAVE_short_and_acquire_read + (void)"AO_short_and_acquire_read(&val, incr):"; + AO_short_and_acquire_read(&val, incr); +# else + (void)"No AO_short_and_acquire_read"; +# endif +# ifdef AO_HAVE_short_or_acquire_read + (void)"AO_short_or_acquire_read(&val, incr):"; + AO_short_or_acquire_read(&val, incr); +# else + (void)"No AO_short_or_acquire_read"; +# endif +# ifdef AO_HAVE_short_xor_acquire_read + (void)"AO_short_xor_acquire_read(&val, incr):"; + AO_short_xor_acquire_read(&val, incr); +# else + (void)"No AO_short_xor_acquire_read"; +# endif +# ifdef AO_HAVE_short_compare_and_swap_acquire_read + (void)"AO_short_compare_and_swap_acquire_read(&val, oldval, newval):"; + if (!AO_short_compare_and_swap_acquire_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_short_compare_and_swap_acquire_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_acquire_read */ + /* TODO: Add AO_compare_and_swap_double_acquire_read */ +# ifdef AO_HAVE_short_fetch_compare_and_swap_acquire_read + (void)"AO_short_fetch_compare_and_swap_acquire_read(&val, oldval, newval):"; + if (AO_short_fetch_compare_and_swap_acquire_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_short_fetch_compare_and_swap_acquire_read"; +# endif + +# if defined(AO_HAVE_test_and_set_acquire_read) + (void)"AO_test_and_set_acquire_read(&ts):"; + (void)AO_test_and_set_acquire_read(&ts); +# else + (void)"No AO_test_and_set_acquire_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void short_list_atomic_dd_acquire_read(void) +{ +# if defined(AO_HAVE_short_load_dd_acquire_read) || defined(AO_HAVE_short_store_dd_acquire_read) \ + || defined(AO_HAVE_short_fetch_and_add_dd_acquire_read) \ + || defined(AO_HAVE_short_fetch_and_add1_dd_acquire_read) \ + || defined(AO_HAVE_short_and_dd_acquire_read) \ + || defined(AO_HAVE_short_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_dd_acquire_read) + static volatile unsigned/**/short val /* = 0 */; +# endif +# if defined(AO_HAVE_short_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_dd_acquire_read) + static unsigned/**/short oldval /* = 0 */; +# endif +# if defined(AO_HAVE_short_store_dd_acquire_read) \ + || defined(AO_HAVE_short_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_short_fetch_compare_and_swap_dd_acquire_read) + static unsigned/**/short newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_short_fetch_and_add_dd_acquire_read) || defined(AO_HAVE_short_and_dd_acquire_read) \ + || defined(AO_HAVE_short_or_dd_acquire_read) || defined(AO_HAVE_short_xor_dd_acquire_read) + static unsigned/**/short incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_dd_acquire_read) + (void)"AO_nop_dd_acquire_read(): "; + AO_nop_dd_acquire_read(); +# else + (void)"No AO_nop_dd_acquire_read"; +# endif + +# ifdef AO_HAVE_short_load_dd_acquire_read + (void)"AO_short_load_dd_acquire_read(&val):"; + (void)AO_short_load_dd_acquire_read(&val); +# else + (void)"No AO_short_load_dd_acquire_read"; +# endif +# ifdef AO_HAVE_short_store_dd_acquire_read + (void)"AO_short_store_dd_acquire_read(&val, newval):"; + AO_short_store_dd_acquire_read(&val, newval); +# else + (void)"No AO_short_store_dd_acquire_read"; +# endif +# ifdef AO_HAVE_short_fetch_and_add_dd_acquire_read + (void)"AO_short_fetch_and_add_dd_acquire_read(&val, incr):"; + (void)AO_short_fetch_and_add_dd_acquire_read(&val, incr); +# else + (void)"No AO_short_fetch_and_add_dd_acquire_read"; +# endif +# ifdef AO_HAVE_short_fetch_and_add1_dd_acquire_read + (void)"AO_short_fetch_and_add1_dd_acquire_read(&val):"; + (void)AO_short_fetch_and_add1_dd_acquire_read(&val); +# else + (void)"No AO_short_fetch_and_add1_dd_acquire_read"; +# endif +# ifdef AO_HAVE_short_fetch_and_sub1_dd_acquire_read + (void)"AO_short_fetch_and_sub1_dd_acquire_read(&val):"; + (void)AO_short_fetch_and_sub1_dd_acquire_read(&val); +# else + (void)"No AO_short_fetch_and_sub1_dd_acquire_read"; +# endif +# ifdef AO_HAVE_short_and_dd_acquire_read + (void)"AO_short_and_dd_acquire_read(&val, incr):"; + AO_short_and_dd_acquire_read(&val, incr); +# else + (void)"No AO_short_and_dd_acquire_read"; +# endif +# ifdef AO_HAVE_short_or_dd_acquire_read + (void)"AO_short_or_dd_acquire_read(&val, incr):"; + AO_short_or_dd_acquire_read(&val, incr); +# else + (void)"No AO_short_or_dd_acquire_read"; +# endif +# ifdef AO_HAVE_short_xor_dd_acquire_read + (void)"AO_short_xor_dd_acquire_read(&val, incr):"; + AO_short_xor_dd_acquire_read(&val, incr); +# else + (void)"No AO_short_xor_dd_acquire_read"; +# endif +# ifdef AO_HAVE_short_compare_and_swap_dd_acquire_read + (void)"AO_short_compare_and_swap_dd_acquire_read(&val, oldval, newval):"; + if (!AO_short_compare_and_swap_dd_acquire_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_short_compare_and_swap_dd_acquire_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_dd_acquire_read */ + /* TODO: Add AO_compare_and_swap_double_dd_acquire_read */ +# ifdef AO_HAVE_short_fetch_compare_and_swap_dd_acquire_read + (void)"AO_short_fetch_compare_and_swap_dd_acquire_read(&val, oldval, newval):"; + if (AO_short_fetch_compare_and_swap_dd_acquire_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_short_fetch_compare_and_swap_dd_acquire_read"; +# endif + +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + (void)"AO_test_and_set_dd_acquire_read(&ts):"; + (void)AO_test_and_set_dd_acquire_read(&ts); +# else + (void)"No AO_test_and_set_dd_acquire_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void int_list_atomic(void) +{ +# if defined(AO_HAVE_int_load) || defined(AO_HAVE_int_store) \ + || defined(AO_HAVE_int_fetch_and_add) \ + || defined(AO_HAVE_int_fetch_and_add1) \ + || defined(AO_HAVE_int_and) \ + || defined(AO_HAVE_int_compare_and_swap) \ + || defined(AO_HAVE_int_fetch_compare_and_swap) + static volatile unsigned val /* = 0 */; +# endif +# if defined(AO_HAVE_int_compare_and_swap) \ + || defined(AO_HAVE_int_fetch_compare_and_swap) + static unsigned oldval /* = 0 */; +# endif +# if defined(AO_HAVE_int_store) \ + || defined(AO_HAVE_int_compare_and_swap) \ + || defined(AO_HAVE_int_fetch_compare_and_swap) + static unsigned newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_int_fetch_and_add) || defined(AO_HAVE_int_and) \ + || defined(AO_HAVE_int_or) || defined(AO_HAVE_int_xor) + static unsigned incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop) + (void)"AO_nop(): "; + AO_nop(); +# else + (void)"No AO_nop"; +# endif + +# ifdef AO_HAVE_int_load + (void)"AO_int_load(&val):"; + (void)AO_int_load(&val); +# else + (void)"No AO_int_load"; +# endif +# ifdef AO_HAVE_int_store + (void)"AO_int_store(&val, newval):"; + AO_int_store(&val, newval); +# else + (void)"No AO_int_store"; +# endif +# ifdef AO_HAVE_int_fetch_and_add + (void)"AO_int_fetch_and_add(&val, incr):"; + (void)AO_int_fetch_and_add(&val, incr); +# else + (void)"No AO_int_fetch_and_add"; +# endif +# ifdef AO_HAVE_int_fetch_and_add1 + (void)"AO_int_fetch_and_add1(&val):"; + (void)AO_int_fetch_and_add1(&val); +# else + (void)"No AO_int_fetch_and_add1"; +# endif +# ifdef AO_HAVE_int_fetch_and_sub1 + (void)"AO_int_fetch_and_sub1(&val):"; + (void)AO_int_fetch_and_sub1(&val); +# else + (void)"No AO_int_fetch_and_sub1"; +# endif +# ifdef AO_HAVE_int_and + (void)"AO_int_and(&val, incr):"; + AO_int_and(&val, incr); +# else + (void)"No AO_int_and"; +# endif +# ifdef AO_HAVE_int_or + (void)"AO_int_or(&val, incr):"; + AO_int_or(&val, incr); +# else + (void)"No AO_int_or"; +# endif +# ifdef AO_HAVE_int_xor + (void)"AO_int_xor(&val, incr):"; + AO_int_xor(&val, incr); +# else + (void)"No AO_int_xor"; +# endif +# ifdef AO_HAVE_int_compare_and_swap + (void)"AO_int_compare_and_swap(&val, oldval, newval):"; + if (!AO_int_compare_and_swap(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_int_compare_and_swap"; +# endif + /* TODO: Add AO_compare_double_and_swap_double */ + /* TODO: Add AO_compare_and_swap_double */ +# ifdef AO_HAVE_int_fetch_compare_and_swap + (void)"AO_int_fetch_compare_and_swap(&val, oldval, newval):"; + if (AO_int_fetch_compare_and_swap(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_int_fetch_compare_and_swap"; +# endif + +# if defined(AO_HAVE_test_and_set) + (void)"AO_test_and_set(&ts):"; + (void)AO_test_and_set(&ts); +# else + (void)"No AO_test_and_set"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void int_list_atomic_release(void) +{ +# if defined(AO_HAVE_int_load_release) || defined(AO_HAVE_int_store_release) \ + || defined(AO_HAVE_int_fetch_and_add_release) \ + || defined(AO_HAVE_int_fetch_and_add1_release) \ + || defined(AO_HAVE_int_and_release) \ + || defined(AO_HAVE_int_compare_and_swap_release) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_release) + static volatile unsigned val /* = 0 */; +# endif +# if defined(AO_HAVE_int_compare_and_swap_release) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_release) + static unsigned oldval /* = 0 */; +# endif +# if defined(AO_HAVE_int_store_release) \ + || defined(AO_HAVE_int_compare_and_swap_release) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_release) + static unsigned newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_release) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_int_fetch_and_add_release) || defined(AO_HAVE_int_and_release) \ + || defined(AO_HAVE_int_or_release) || defined(AO_HAVE_int_xor_release) + static unsigned incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_release) + (void)"AO_nop_release(): "; + AO_nop_release(); +# else + (void)"No AO_nop_release"; +# endif + +# ifdef AO_HAVE_int_load_release + (void)"AO_int_load_release(&val):"; + (void)AO_int_load_release(&val); +# else + (void)"No AO_int_load_release"; +# endif +# ifdef AO_HAVE_int_store_release + (void)"AO_int_store_release(&val, newval):"; + AO_int_store_release(&val, newval); +# else + (void)"No AO_int_store_release"; +# endif +# ifdef AO_HAVE_int_fetch_and_add_release + (void)"AO_int_fetch_and_add_release(&val, incr):"; + (void)AO_int_fetch_and_add_release(&val, incr); +# else + (void)"No AO_int_fetch_and_add_release"; +# endif +# ifdef AO_HAVE_int_fetch_and_add1_release + (void)"AO_int_fetch_and_add1_release(&val):"; + (void)AO_int_fetch_and_add1_release(&val); +# else + (void)"No AO_int_fetch_and_add1_release"; +# endif +# ifdef AO_HAVE_int_fetch_and_sub1_release + (void)"AO_int_fetch_and_sub1_release(&val):"; + (void)AO_int_fetch_and_sub1_release(&val); +# else + (void)"No AO_int_fetch_and_sub1_release"; +# endif +# ifdef AO_HAVE_int_and_release + (void)"AO_int_and_release(&val, incr):"; + AO_int_and_release(&val, incr); +# else + (void)"No AO_int_and_release"; +# endif +# ifdef AO_HAVE_int_or_release + (void)"AO_int_or_release(&val, incr):"; + AO_int_or_release(&val, incr); +# else + (void)"No AO_int_or_release"; +# endif +# ifdef AO_HAVE_int_xor_release + (void)"AO_int_xor_release(&val, incr):"; + AO_int_xor_release(&val, incr); +# else + (void)"No AO_int_xor_release"; +# endif +# ifdef AO_HAVE_int_compare_and_swap_release + (void)"AO_int_compare_and_swap_release(&val, oldval, newval):"; + if (!AO_int_compare_and_swap_release(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_int_compare_and_swap_release"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_release */ + /* TODO: Add AO_compare_and_swap_double_release */ +# ifdef AO_HAVE_int_fetch_compare_and_swap_release + (void)"AO_int_fetch_compare_and_swap_release(&val, oldval, newval):"; + if (AO_int_fetch_compare_and_swap_release(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_int_fetch_compare_and_swap_release"; +# endif + +# if defined(AO_HAVE_test_and_set_release) + (void)"AO_test_and_set_release(&ts):"; + (void)AO_test_and_set_release(&ts); +# else + (void)"No AO_test_and_set_release"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void int_list_atomic_acquire(void) +{ +# if defined(AO_HAVE_int_load_acquire) || defined(AO_HAVE_int_store_acquire) \ + || defined(AO_HAVE_int_fetch_and_add_acquire) \ + || defined(AO_HAVE_int_fetch_and_add1_acquire) \ + || defined(AO_HAVE_int_and_acquire) \ + || defined(AO_HAVE_int_compare_and_swap_acquire) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_acquire) + static volatile unsigned val /* = 0 */; +# endif +# if defined(AO_HAVE_int_compare_and_swap_acquire) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_acquire) + static unsigned oldval /* = 0 */; +# endif +# if defined(AO_HAVE_int_store_acquire) \ + || defined(AO_HAVE_int_compare_and_swap_acquire) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_acquire) + static unsigned newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_acquire) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_int_fetch_and_add_acquire) || defined(AO_HAVE_int_and_acquire) \ + || defined(AO_HAVE_int_or_acquire) || defined(AO_HAVE_int_xor_acquire) + static unsigned incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_acquire) + (void)"AO_nop_acquire(): "; + AO_nop_acquire(); +# else + (void)"No AO_nop_acquire"; +# endif + +# ifdef AO_HAVE_int_load_acquire + (void)"AO_int_load_acquire(&val):"; + (void)AO_int_load_acquire(&val); +# else + (void)"No AO_int_load_acquire"; +# endif +# ifdef AO_HAVE_int_store_acquire + (void)"AO_int_store_acquire(&val, newval):"; + AO_int_store_acquire(&val, newval); +# else + (void)"No AO_int_store_acquire"; +# endif +# ifdef AO_HAVE_int_fetch_and_add_acquire + (void)"AO_int_fetch_and_add_acquire(&val, incr):"; + (void)AO_int_fetch_and_add_acquire(&val, incr); +# else + (void)"No AO_int_fetch_and_add_acquire"; +# endif +# ifdef AO_HAVE_int_fetch_and_add1_acquire + (void)"AO_int_fetch_and_add1_acquire(&val):"; + (void)AO_int_fetch_and_add1_acquire(&val); +# else + (void)"No AO_int_fetch_and_add1_acquire"; +# endif +# ifdef AO_HAVE_int_fetch_and_sub1_acquire + (void)"AO_int_fetch_and_sub1_acquire(&val):"; + (void)AO_int_fetch_and_sub1_acquire(&val); +# else + (void)"No AO_int_fetch_and_sub1_acquire"; +# endif +# ifdef AO_HAVE_int_and_acquire + (void)"AO_int_and_acquire(&val, incr):"; + AO_int_and_acquire(&val, incr); +# else + (void)"No AO_int_and_acquire"; +# endif +# ifdef AO_HAVE_int_or_acquire + (void)"AO_int_or_acquire(&val, incr):"; + AO_int_or_acquire(&val, incr); +# else + (void)"No AO_int_or_acquire"; +# endif +# ifdef AO_HAVE_int_xor_acquire + (void)"AO_int_xor_acquire(&val, incr):"; + AO_int_xor_acquire(&val, incr); +# else + (void)"No AO_int_xor_acquire"; +# endif +# ifdef AO_HAVE_int_compare_and_swap_acquire + (void)"AO_int_compare_and_swap_acquire(&val, oldval, newval):"; + if (!AO_int_compare_and_swap_acquire(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_int_compare_and_swap_acquire"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_acquire */ + /* TODO: Add AO_compare_and_swap_double_acquire */ +# ifdef AO_HAVE_int_fetch_compare_and_swap_acquire + (void)"AO_int_fetch_compare_and_swap_acquire(&val, oldval, newval):"; + if (AO_int_fetch_compare_and_swap_acquire(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_int_fetch_compare_and_swap_acquire"; +# endif + +# if defined(AO_HAVE_test_and_set_acquire) + (void)"AO_test_and_set_acquire(&ts):"; + (void)AO_test_and_set_acquire(&ts); +# else + (void)"No AO_test_and_set_acquire"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void int_list_atomic_read(void) +{ +# if defined(AO_HAVE_int_load_read) || defined(AO_HAVE_int_store_read) \ + || defined(AO_HAVE_int_fetch_and_add_read) \ + || defined(AO_HAVE_int_fetch_and_add1_read) \ + || defined(AO_HAVE_int_and_read) \ + || defined(AO_HAVE_int_compare_and_swap_read) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_read) + static volatile unsigned val /* = 0 */; +# endif +# if defined(AO_HAVE_int_compare_and_swap_read) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_read) + static unsigned oldval /* = 0 */; +# endif +# if defined(AO_HAVE_int_store_read) \ + || defined(AO_HAVE_int_compare_and_swap_read) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_read) + static unsigned newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_int_fetch_and_add_read) || defined(AO_HAVE_int_and_read) \ + || defined(AO_HAVE_int_or_read) || defined(AO_HAVE_int_xor_read) + static unsigned incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_read) + (void)"AO_nop_read(): "; + AO_nop_read(); +# else + (void)"No AO_nop_read"; +# endif + +# ifdef AO_HAVE_int_load_read + (void)"AO_int_load_read(&val):"; + (void)AO_int_load_read(&val); +# else + (void)"No AO_int_load_read"; +# endif +# ifdef AO_HAVE_int_store_read + (void)"AO_int_store_read(&val, newval):"; + AO_int_store_read(&val, newval); +# else + (void)"No AO_int_store_read"; +# endif +# ifdef AO_HAVE_int_fetch_and_add_read + (void)"AO_int_fetch_and_add_read(&val, incr):"; + (void)AO_int_fetch_and_add_read(&val, incr); +# else + (void)"No AO_int_fetch_and_add_read"; +# endif +# ifdef AO_HAVE_int_fetch_and_add1_read + (void)"AO_int_fetch_and_add1_read(&val):"; + (void)AO_int_fetch_and_add1_read(&val); +# else + (void)"No AO_int_fetch_and_add1_read"; +# endif +# ifdef AO_HAVE_int_fetch_and_sub1_read + (void)"AO_int_fetch_and_sub1_read(&val):"; + (void)AO_int_fetch_and_sub1_read(&val); +# else + (void)"No AO_int_fetch_and_sub1_read"; +# endif +# ifdef AO_HAVE_int_and_read + (void)"AO_int_and_read(&val, incr):"; + AO_int_and_read(&val, incr); +# else + (void)"No AO_int_and_read"; +# endif +# ifdef AO_HAVE_int_or_read + (void)"AO_int_or_read(&val, incr):"; + AO_int_or_read(&val, incr); +# else + (void)"No AO_int_or_read"; +# endif +# ifdef AO_HAVE_int_xor_read + (void)"AO_int_xor_read(&val, incr):"; + AO_int_xor_read(&val, incr); +# else + (void)"No AO_int_xor_read"; +# endif +# ifdef AO_HAVE_int_compare_and_swap_read + (void)"AO_int_compare_and_swap_read(&val, oldval, newval):"; + if (!AO_int_compare_and_swap_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_int_compare_and_swap_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_read */ + /* TODO: Add AO_compare_and_swap_double_read */ +# ifdef AO_HAVE_int_fetch_compare_and_swap_read + (void)"AO_int_fetch_compare_and_swap_read(&val, oldval, newval):"; + if (AO_int_fetch_compare_and_swap_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_int_fetch_compare_and_swap_read"; +# endif + +# if defined(AO_HAVE_test_and_set_read) + (void)"AO_test_and_set_read(&ts):"; + (void)AO_test_and_set_read(&ts); +# else + (void)"No AO_test_and_set_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void int_list_atomic_write(void) +{ +# if defined(AO_HAVE_int_load_write) || defined(AO_HAVE_int_store_write) \ + || defined(AO_HAVE_int_fetch_and_add_write) \ + || defined(AO_HAVE_int_fetch_and_add1_write) \ + || defined(AO_HAVE_int_and_write) \ + || defined(AO_HAVE_int_compare_and_swap_write) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_write) + static volatile unsigned val /* = 0 */; +# endif +# if defined(AO_HAVE_int_compare_and_swap_write) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_write) + static unsigned oldval /* = 0 */; +# endif +# if defined(AO_HAVE_int_store_write) \ + || defined(AO_HAVE_int_compare_and_swap_write) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_write) + static unsigned newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_write) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_int_fetch_and_add_write) || defined(AO_HAVE_int_and_write) \ + || defined(AO_HAVE_int_or_write) || defined(AO_HAVE_int_xor_write) + static unsigned incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_write) + (void)"AO_nop_write(): "; + AO_nop_write(); +# else + (void)"No AO_nop_write"; +# endif + +# ifdef AO_HAVE_int_load_write + (void)"AO_int_load_write(&val):"; + (void)AO_int_load_write(&val); +# else + (void)"No AO_int_load_write"; +# endif +# ifdef AO_HAVE_int_store_write + (void)"AO_int_store_write(&val, newval):"; + AO_int_store_write(&val, newval); +# else + (void)"No AO_int_store_write"; +# endif +# ifdef AO_HAVE_int_fetch_and_add_write + (void)"AO_int_fetch_and_add_write(&val, incr):"; + (void)AO_int_fetch_and_add_write(&val, incr); +# else + (void)"No AO_int_fetch_and_add_write"; +# endif +# ifdef AO_HAVE_int_fetch_and_add1_write + (void)"AO_int_fetch_and_add1_write(&val):"; + (void)AO_int_fetch_and_add1_write(&val); +# else + (void)"No AO_int_fetch_and_add1_write"; +# endif +# ifdef AO_HAVE_int_fetch_and_sub1_write + (void)"AO_int_fetch_and_sub1_write(&val):"; + (void)AO_int_fetch_and_sub1_write(&val); +# else + (void)"No AO_int_fetch_and_sub1_write"; +# endif +# ifdef AO_HAVE_int_and_write + (void)"AO_int_and_write(&val, incr):"; + AO_int_and_write(&val, incr); +# else + (void)"No AO_int_and_write"; +# endif +# ifdef AO_HAVE_int_or_write + (void)"AO_int_or_write(&val, incr):"; + AO_int_or_write(&val, incr); +# else + (void)"No AO_int_or_write"; +# endif +# ifdef AO_HAVE_int_xor_write + (void)"AO_int_xor_write(&val, incr):"; + AO_int_xor_write(&val, incr); +# else + (void)"No AO_int_xor_write"; +# endif +# ifdef AO_HAVE_int_compare_and_swap_write + (void)"AO_int_compare_and_swap_write(&val, oldval, newval):"; + if (!AO_int_compare_and_swap_write(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_int_compare_and_swap_write"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_write */ + /* TODO: Add AO_compare_and_swap_double_write */ +# ifdef AO_HAVE_int_fetch_compare_and_swap_write + (void)"AO_int_fetch_compare_and_swap_write(&val, oldval, newval):"; + if (AO_int_fetch_compare_and_swap_write(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_int_fetch_compare_and_swap_write"; +# endif + +# if defined(AO_HAVE_test_and_set_write) + (void)"AO_test_and_set_write(&ts):"; + (void)AO_test_and_set_write(&ts); +# else + (void)"No AO_test_and_set_write"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void int_list_atomic_full(void) +{ +# if defined(AO_HAVE_int_load_full) || defined(AO_HAVE_int_store_full) \ + || defined(AO_HAVE_int_fetch_and_add_full) \ + || defined(AO_HAVE_int_fetch_and_add1_full) \ + || defined(AO_HAVE_int_and_full) \ + || defined(AO_HAVE_int_compare_and_swap_full) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_full) + static volatile unsigned val /* = 0 */; +# endif +# if defined(AO_HAVE_int_compare_and_swap_full) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_full) + static unsigned oldval /* = 0 */; +# endif +# if defined(AO_HAVE_int_store_full) \ + || defined(AO_HAVE_int_compare_and_swap_full) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_full) + static unsigned newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_full) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_int_fetch_and_add_full) || defined(AO_HAVE_int_and_full) \ + || defined(AO_HAVE_int_or_full) || defined(AO_HAVE_int_xor_full) + static unsigned incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_full) + (void)"AO_nop_full(): "; + AO_nop_full(); +# else + (void)"No AO_nop_full"; +# endif + +# ifdef AO_HAVE_int_load_full + (void)"AO_int_load_full(&val):"; + (void)AO_int_load_full(&val); +# else + (void)"No AO_int_load_full"; +# endif +# ifdef AO_HAVE_int_store_full + (void)"AO_int_store_full(&val, newval):"; + AO_int_store_full(&val, newval); +# else + (void)"No AO_int_store_full"; +# endif +# ifdef AO_HAVE_int_fetch_and_add_full + (void)"AO_int_fetch_and_add_full(&val, incr):"; + (void)AO_int_fetch_and_add_full(&val, incr); +# else + (void)"No AO_int_fetch_and_add_full"; +# endif +# ifdef AO_HAVE_int_fetch_and_add1_full + (void)"AO_int_fetch_and_add1_full(&val):"; + (void)AO_int_fetch_and_add1_full(&val); +# else + (void)"No AO_int_fetch_and_add1_full"; +# endif +# ifdef AO_HAVE_int_fetch_and_sub1_full + (void)"AO_int_fetch_and_sub1_full(&val):"; + (void)AO_int_fetch_and_sub1_full(&val); +# else + (void)"No AO_int_fetch_and_sub1_full"; +# endif +# ifdef AO_HAVE_int_and_full + (void)"AO_int_and_full(&val, incr):"; + AO_int_and_full(&val, incr); +# else + (void)"No AO_int_and_full"; +# endif +# ifdef AO_HAVE_int_or_full + (void)"AO_int_or_full(&val, incr):"; + AO_int_or_full(&val, incr); +# else + (void)"No AO_int_or_full"; +# endif +# ifdef AO_HAVE_int_xor_full + (void)"AO_int_xor_full(&val, incr):"; + AO_int_xor_full(&val, incr); +# else + (void)"No AO_int_xor_full"; +# endif +# ifdef AO_HAVE_int_compare_and_swap_full + (void)"AO_int_compare_and_swap_full(&val, oldval, newval):"; + if (!AO_int_compare_and_swap_full(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_int_compare_and_swap_full"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_full */ + /* TODO: Add AO_compare_and_swap_double_full */ +# ifdef AO_HAVE_int_fetch_compare_and_swap_full + (void)"AO_int_fetch_compare_and_swap_full(&val, oldval, newval):"; + if (AO_int_fetch_compare_and_swap_full(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_int_fetch_compare_and_swap_full"; +# endif + +# if defined(AO_HAVE_test_and_set_full) + (void)"AO_test_and_set_full(&ts):"; + (void)AO_test_and_set_full(&ts); +# else + (void)"No AO_test_and_set_full"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void int_list_atomic_release_write(void) +{ +# if defined(AO_HAVE_int_load_release_write) || defined(AO_HAVE_int_store_release_write) \ + || defined(AO_HAVE_int_fetch_and_add_release_write) \ + || defined(AO_HAVE_int_fetch_and_add1_release_write) \ + || defined(AO_HAVE_int_and_release_write) \ + || defined(AO_HAVE_int_compare_and_swap_release_write) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_release_write) + static volatile unsigned val /* = 0 */; +# endif +# if defined(AO_HAVE_int_compare_and_swap_release_write) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_release_write) + static unsigned oldval /* = 0 */; +# endif +# if defined(AO_HAVE_int_store_release_write) \ + || defined(AO_HAVE_int_compare_and_swap_release_write) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_release_write) + static unsigned newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_release_write) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_int_fetch_and_add_release_write) || defined(AO_HAVE_int_and_release_write) \ + || defined(AO_HAVE_int_or_release_write) || defined(AO_HAVE_int_xor_release_write) + static unsigned incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_release_write) + (void)"AO_nop_release_write(): "; + AO_nop_release_write(); +# else + (void)"No AO_nop_release_write"; +# endif + +# ifdef AO_HAVE_int_load_release_write + (void)"AO_int_load_release_write(&val):"; + (void)AO_int_load_release_write(&val); +# else + (void)"No AO_int_load_release_write"; +# endif +# ifdef AO_HAVE_int_store_release_write + (void)"AO_int_store_release_write(&val, newval):"; + AO_int_store_release_write(&val, newval); +# else + (void)"No AO_int_store_release_write"; +# endif +# ifdef AO_HAVE_int_fetch_and_add_release_write + (void)"AO_int_fetch_and_add_release_write(&val, incr):"; + (void)AO_int_fetch_and_add_release_write(&val, incr); +# else + (void)"No AO_int_fetch_and_add_release_write"; +# endif +# ifdef AO_HAVE_int_fetch_and_add1_release_write + (void)"AO_int_fetch_and_add1_release_write(&val):"; + (void)AO_int_fetch_and_add1_release_write(&val); +# else + (void)"No AO_int_fetch_and_add1_release_write"; +# endif +# ifdef AO_HAVE_int_fetch_and_sub1_release_write + (void)"AO_int_fetch_and_sub1_release_write(&val):"; + (void)AO_int_fetch_and_sub1_release_write(&val); +# else + (void)"No AO_int_fetch_and_sub1_release_write"; +# endif +# ifdef AO_HAVE_int_and_release_write + (void)"AO_int_and_release_write(&val, incr):"; + AO_int_and_release_write(&val, incr); +# else + (void)"No AO_int_and_release_write"; +# endif +# ifdef AO_HAVE_int_or_release_write + (void)"AO_int_or_release_write(&val, incr):"; + AO_int_or_release_write(&val, incr); +# else + (void)"No AO_int_or_release_write"; +# endif +# ifdef AO_HAVE_int_xor_release_write + (void)"AO_int_xor_release_write(&val, incr):"; + AO_int_xor_release_write(&val, incr); +# else + (void)"No AO_int_xor_release_write"; +# endif +# ifdef AO_HAVE_int_compare_and_swap_release_write + (void)"AO_int_compare_and_swap_release_write(&val, oldval, newval):"; + if (!AO_int_compare_and_swap_release_write(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_int_compare_and_swap_release_write"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_release_write */ + /* TODO: Add AO_compare_and_swap_double_release_write */ +# ifdef AO_HAVE_int_fetch_compare_and_swap_release_write + (void)"AO_int_fetch_compare_and_swap_release_write(&val, oldval, newval):"; + if (AO_int_fetch_compare_and_swap_release_write(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_int_fetch_compare_and_swap_release_write"; +# endif + +# if defined(AO_HAVE_test_and_set_release_write) + (void)"AO_test_and_set_release_write(&ts):"; + (void)AO_test_and_set_release_write(&ts); +# else + (void)"No AO_test_and_set_release_write"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void int_list_atomic_acquire_read(void) +{ +# if defined(AO_HAVE_int_load_acquire_read) || defined(AO_HAVE_int_store_acquire_read) \ + || defined(AO_HAVE_int_fetch_and_add_acquire_read) \ + || defined(AO_HAVE_int_fetch_and_add1_acquire_read) \ + || defined(AO_HAVE_int_and_acquire_read) \ + || defined(AO_HAVE_int_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_acquire_read) + static volatile unsigned val /* = 0 */; +# endif +# if defined(AO_HAVE_int_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_acquire_read) + static unsigned oldval /* = 0 */; +# endif +# if defined(AO_HAVE_int_store_acquire_read) \ + || defined(AO_HAVE_int_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_acquire_read) + static unsigned newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_acquire_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_int_fetch_and_add_acquire_read) || defined(AO_HAVE_int_and_acquire_read) \ + || defined(AO_HAVE_int_or_acquire_read) || defined(AO_HAVE_int_xor_acquire_read) + static unsigned incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_acquire_read) + (void)"AO_nop_acquire_read(): "; + AO_nop_acquire_read(); +# else + (void)"No AO_nop_acquire_read"; +# endif + +# ifdef AO_HAVE_int_load_acquire_read + (void)"AO_int_load_acquire_read(&val):"; + (void)AO_int_load_acquire_read(&val); +# else + (void)"No AO_int_load_acquire_read"; +# endif +# ifdef AO_HAVE_int_store_acquire_read + (void)"AO_int_store_acquire_read(&val, newval):"; + AO_int_store_acquire_read(&val, newval); +# else + (void)"No AO_int_store_acquire_read"; +# endif +# ifdef AO_HAVE_int_fetch_and_add_acquire_read + (void)"AO_int_fetch_and_add_acquire_read(&val, incr):"; + (void)AO_int_fetch_and_add_acquire_read(&val, incr); +# else + (void)"No AO_int_fetch_and_add_acquire_read"; +# endif +# ifdef AO_HAVE_int_fetch_and_add1_acquire_read + (void)"AO_int_fetch_and_add1_acquire_read(&val):"; + (void)AO_int_fetch_and_add1_acquire_read(&val); +# else + (void)"No AO_int_fetch_and_add1_acquire_read"; +# endif +# ifdef AO_HAVE_int_fetch_and_sub1_acquire_read + (void)"AO_int_fetch_and_sub1_acquire_read(&val):"; + (void)AO_int_fetch_and_sub1_acquire_read(&val); +# else + (void)"No AO_int_fetch_and_sub1_acquire_read"; +# endif +# ifdef AO_HAVE_int_and_acquire_read + (void)"AO_int_and_acquire_read(&val, incr):"; + AO_int_and_acquire_read(&val, incr); +# else + (void)"No AO_int_and_acquire_read"; +# endif +# ifdef AO_HAVE_int_or_acquire_read + (void)"AO_int_or_acquire_read(&val, incr):"; + AO_int_or_acquire_read(&val, incr); +# else + (void)"No AO_int_or_acquire_read"; +# endif +# ifdef AO_HAVE_int_xor_acquire_read + (void)"AO_int_xor_acquire_read(&val, incr):"; + AO_int_xor_acquire_read(&val, incr); +# else + (void)"No AO_int_xor_acquire_read"; +# endif +# ifdef AO_HAVE_int_compare_and_swap_acquire_read + (void)"AO_int_compare_and_swap_acquire_read(&val, oldval, newval):"; + if (!AO_int_compare_and_swap_acquire_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_int_compare_and_swap_acquire_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_acquire_read */ + /* TODO: Add AO_compare_and_swap_double_acquire_read */ +# ifdef AO_HAVE_int_fetch_compare_and_swap_acquire_read + (void)"AO_int_fetch_compare_and_swap_acquire_read(&val, oldval, newval):"; + if (AO_int_fetch_compare_and_swap_acquire_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_int_fetch_compare_and_swap_acquire_read"; +# endif + +# if defined(AO_HAVE_test_and_set_acquire_read) + (void)"AO_test_and_set_acquire_read(&ts):"; + (void)AO_test_and_set_acquire_read(&ts); +# else + (void)"No AO_test_and_set_acquire_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void int_list_atomic_dd_acquire_read(void) +{ +# if defined(AO_HAVE_int_load_dd_acquire_read) || defined(AO_HAVE_int_store_dd_acquire_read) \ + || defined(AO_HAVE_int_fetch_and_add_dd_acquire_read) \ + || defined(AO_HAVE_int_fetch_and_add1_dd_acquire_read) \ + || defined(AO_HAVE_int_and_dd_acquire_read) \ + || defined(AO_HAVE_int_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_dd_acquire_read) + static volatile unsigned val /* = 0 */; +# endif +# if defined(AO_HAVE_int_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_dd_acquire_read) + static unsigned oldval /* = 0 */; +# endif +# if defined(AO_HAVE_int_store_dd_acquire_read) \ + || defined(AO_HAVE_int_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_int_fetch_compare_and_swap_dd_acquire_read) + static unsigned newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_int_fetch_and_add_dd_acquire_read) || defined(AO_HAVE_int_and_dd_acquire_read) \ + || defined(AO_HAVE_int_or_dd_acquire_read) || defined(AO_HAVE_int_xor_dd_acquire_read) + static unsigned incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_dd_acquire_read) + (void)"AO_nop_dd_acquire_read(): "; + AO_nop_dd_acquire_read(); +# else + (void)"No AO_nop_dd_acquire_read"; +# endif + +# ifdef AO_HAVE_int_load_dd_acquire_read + (void)"AO_int_load_dd_acquire_read(&val):"; + (void)AO_int_load_dd_acquire_read(&val); +# else + (void)"No AO_int_load_dd_acquire_read"; +# endif +# ifdef AO_HAVE_int_store_dd_acquire_read + (void)"AO_int_store_dd_acquire_read(&val, newval):"; + AO_int_store_dd_acquire_read(&val, newval); +# else + (void)"No AO_int_store_dd_acquire_read"; +# endif +# ifdef AO_HAVE_int_fetch_and_add_dd_acquire_read + (void)"AO_int_fetch_and_add_dd_acquire_read(&val, incr):"; + (void)AO_int_fetch_and_add_dd_acquire_read(&val, incr); +# else + (void)"No AO_int_fetch_and_add_dd_acquire_read"; +# endif +# ifdef AO_HAVE_int_fetch_and_add1_dd_acquire_read + (void)"AO_int_fetch_and_add1_dd_acquire_read(&val):"; + (void)AO_int_fetch_and_add1_dd_acquire_read(&val); +# else + (void)"No AO_int_fetch_and_add1_dd_acquire_read"; +# endif +# ifdef AO_HAVE_int_fetch_and_sub1_dd_acquire_read + (void)"AO_int_fetch_and_sub1_dd_acquire_read(&val):"; + (void)AO_int_fetch_and_sub1_dd_acquire_read(&val); +# else + (void)"No AO_int_fetch_and_sub1_dd_acquire_read"; +# endif +# ifdef AO_HAVE_int_and_dd_acquire_read + (void)"AO_int_and_dd_acquire_read(&val, incr):"; + AO_int_and_dd_acquire_read(&val, incr); +# else + (void)"No AO_int_and_dd_acquire_read"; +# endif +# ifdef AO_HAVE_int_or_dd_acquire_read + (void)"AO_int_or_dd_acquire_read(&val, incr):"; + AO_int_or_dd_acquire_read(&val, incr); +# else + (void)"No AO_int_or_dd_acquire_read"; +# endif +# ifdef AO_HAVE_int_xor_dd_acquire_read + (void)"AO_int_xor_dd_acquire_read(&val, incr):"; + AO_int_xor_dd_acquire_read(&val, incr); +# else + (void)"No AO_int_xor_dd_acquire_read"; +# endif +# ifdef AO_HAVE_int_compare_and_swap_dd_acquire_read + (void)"AO_int_compare_and_swap_dd_acquire_read(&val, oldval, newval):"; + if (!AO_int_compare_and_swap_dd_acquire_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_int_compare_and_swap_dd_acquire_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_dd_acquire_read */ + /* TODO: Add AO_compare_and_swap_double_dd_acquire_read */ +# ifdef AO_HAVE_int_fetch_compare_and_swap_dd_acquire_read + (void)"AO_int_fetch_compare_and_swap_dd_acquire_read(&val, oldval, newval):"; + if (AO_int_fetch_compare_and_swap_dd_acquire_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_int_fetch_compare_and_swap_dd_acquire_read"; +# endif + +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + (void)"AO_test_and_set_dd_acquire_read(&ts):"; + (void)AO_test_and_set_dd_acquire_read(&ts); +# else + (void)"No AO_test_and_set_dd_acquire_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void double_list_atomic(void) +{ +# if defined(AO_HAVE_double_load) || defined(AO_HAVE_double_store) \ + || defined(AO_HAVE_double_fetch_and_add) \ + || defined(AO_HAVE_double_fetch_and_add1) \ + || defined(AO_HAVE_double_and) \ + || defined(AO_HAVE_double_compare_and_swap) \ + || defined(AO_HAVE_double_fetch_compare_and_swap) + static volatile AO_double_t val /* = 0 */; +# endif +# if defined(AO_HAVE_double_compare_and_swap) \ + || defined(AO_HAVE_double_fetch_compare_and_swap) + static AO_double_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_double_store) \ + || defined(AO_HAVE_double_compare_and_swap) \ + || defined(AO_HAVE_double_fetch_compare_and_swap) + static AO_double_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_fetch_and_add) || defined(AO_HAVE_double_and) \ + || defined(AO_HAVE_double_or) || defined(AO_HAVE_double_xor) + static AO_double_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop) + (void)"AO_nop(): "; + AO_nop(); +# else + (void)"No AO_nop"; +# endif + +# ifdef AO_HAVE_double_load + (void)"AO_double_load(&val):"; + (void)AO_double_load(&val); +# else + (void)"No AO_double_load"; +# endif +# ifdef AO_HAVE_double_store + (void)"AO_double_store(&val, newval):"; + AO_double_store(&val, newval); +# else + (void)"No AO_double_store"; +# endif +# ifdef AO_HAVE_double_fetch_and_add + (void)"AO_double_fetch_and_add(&val, incr):"; + (void)AO_double_fetch_and_add(&val, incr); +# else + (void)"No AO_double_fetch_and_add"; +# endif +# ifdef AO_HAVE_double_fetch_and_add1 + (void)"AO_double_fetch_and_add1(&val):"; + (void)AO_double_fetch_and_add1(&val); +# else + (void)"No AO_double_fetch_and_add1"; +# endif +# ifdef AO_HAVE_double_fetch_and_sub1 + (void)"AO_double_fetch_and_sub1(&val):"; + (void)AO_double_fetch_and_sub1(&val); +# else + (void)"No AO_double_fetch_and_sub1"; +# endif +# ifdef AO_HAVE_double_and + (void)"AO_double_and(&val, incr):"; + AO_double_and(&val, incr); +# else + (void)"No AO_double_and"; +# endif +# ifdef AO_HAVE_double_or + (void)"AO_double_or(&val, incr):"; + AO_double_or(&val, incr); +# else + (void)"No AO_double_or"; +# endif +# ifdef AO_HAVE_double_xor + (void)"AO_double_xor(&val, incr):"; + AO_double_xor(&val, incr); +# else + (void)"No AO_double_xor"; +# endif +# ifdef AO_HAVE_double_compare_and_swap + (void)"AO_double_compare_and_swap(&val, oldval, newval):"; + if (!AO_double_compare_and_swap(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_double_compare_and_swap"; +# endif + /* TODO: Add AO_compare_double_and_swap_double */ + /* TODO: Add AO_compare_and_swap_double */ +# ifdef AO_HAVE_double_fetch_compare_and_swap + (void)"AO_double_fetch_compare_and_swap(&val, oldval, newval):"; + if (AO_double_fetch_compare_and_swap(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_double_fetch_compare_and_swap"; +# endif + +# if defined(AO_HAVE_test_and_set) + (void)"AO_test_and_set(&ts):"; + (void)AO_test_and_set(&ts); +# else + (void)"No AO_test_and_set"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void double_list_atomic_release(void) +{ +# if defined(AO_HAVE_double_load_release) || defined(AO_HAVE_double_store_release) \ + || defined(AO_HAVE_double_fetch_and_add_release) \ + || defined(AO_HAVE_double_fetch_and_add1_release) \ + || defined(AO_HAVE_double_and_release) \ + || defined(AO_HAVE_double_compare_and_swap_release) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_release) + static volatile AO_double_t val /* = 0 */; +# endif +# if defined(AO_HAVE_double_compare_and_swap_release) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_release) + static AO_double_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_double_store_release) \ + || defined(AO_HAVE_double_compare_and_swap_release) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_release) + static AO_double_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_release) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_fetch_and_add_release) || defined(AO_HAVE_double_and_release) \ + || defined(AO_HAVE_double_or_release) || defined(AO_HAVE_double_xor_release) + static AO_double_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_release) + (void)"AO_nop_release(): "; + AO_nop_release(); +# else + (void)"No AO_nop_release"; +# endif + +# ifdef AO_HAVE_double_load_release + (void)"AO_double_load_release(&val):"; + (void)AO_double_load_release(&val); +# else + (void)"No AO_double_load_release"; +# endif +# ifdef AO_HAVE_double_store_release + (void)"AO_double_store_release(&val, newval):"; + AO_double_store_release(&val, newval); +# else + (void)"No AO_double_store_release"; +# endif +# ifdef AO_HAVE_double_fetch_and_add_release + (void)"AO_double_fetch_and_add_release(&val, incr):"; + (void)AO_double_fetch_and_add_release(&val, incr); +# else + (void)"No AO_double_fetch_and_add_release"; +# endif +# ifdef AO_HAVE_double_fetch_and_add1_release + (void)"AO_double_fetch_and_add1_release(&val):"; + (void)AO_double_fetch_and_add1_release(&val); +# else + (void)"No AO_double_fetch_and_add1_release"; +# endif +# ifdef AO_HAVE_double_fetch_and_sub1_release + (void)"AO_double_fetch_and_sub1_release(&val):"; + (void)AO_double_fetch_and_sub1_release(&val); +# else + (void)"No AO_double_fetch_and_sub1_release"; +# endif +# ifdef AO_HAVE_double_and_release + (void)"AO_double_and_release(&val, incr):"; + AO_double_and_release(&val, incr); +# else + (void)"No AO_double_and_release"; +# endif +# ifdef AO_HAVE_double_or_release + (void)"AO_double_or_release(&val, incr):"; + AO_double_or_release(&val, incr); +# else + (void)"No AO_double_or_release"; +# endif +# ifdef AO_HAVE_double_xor_release + (void)"AO_double_xor_release(&val, incr):"; + AO_double_xor_release(&val, incr); +# else + (void)"No AO_double_xor_release"; +# endif +# ifdef AO_HAVE_double_compare_and_swap_release + (void)"AO_double_compare_and_swap_release(&val, oldval, newval):"; + if (!AO_double_compare_and_swap_release(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_double_compare_and_swap_release"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_release */ + /* TODO: Add AO_compare_and_swap_double_release */ +# ifdef AO_HAVE_double_fetch_compare_and_swap_release + (void)"AO_double_fetch_compare_and_swap_release(&val, oldval, newval):"; + if (AO_double_fetch_compare_and_swap_release(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_double_fetch_compare_and_swap_release"; +# endif + +# if defined(AO_HAVE_test_and_set_release) + (void)"AO_test_and_set_release(&ts):"; + (void)AO_test_and_set_release(&ts); +# else + (void)"No AO_test_and_set_release"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void double_list_atomic_acquire(void) +{ +# if defined(AO_HAVE_double_load_acquire) || defined(AO_HAVE_double_store_acquire) \ + || defined(AO_HAVE_double_fetch_and_add_acquire) \ + || defined(AO_HAVE_double_fetch_and_add1_acquire) \ + || defined(AO_HAVE_double_and_acquire) \ + || defined(AO_HAVE_double_compare_and_swap_acquire) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_acquire) + static volatile AO_double_t val /* = 0 */; +# endif +# if defined(AO_HAVE_double_compare_and_swap_acquire) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_acquire) + static AO_double_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_double_store_acquire) \ + || defined(AO_HAVE_double_compare_and_swap_acquire) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_acquire) + static AO_double_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_acquire) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_fetch_and_add_acquire) || defined(AO_HAVE_double_and_acquire) \ + || defined(AO_HAVE_double_or_acquire) || defined(AO_HAVE_double_xor_acquire) + static AO_double_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_acquire) + (void)"AO_nop_acquire(): "; + AO_nop_acquire(); +# else + (void)"No AO_nop_acquire"; +# endif + +# ifdef AO_HAVE_double_load_acquire + (void)"AO_double_load_acquire(&val):"; + (void)AO_double_load_acquire(&val); +# else + (void)"No AO_double_load_acquire"; +# endif +# ifdef AO_HAVE_double_store_acquire + (void)"AO_double_store_acquire(&val, newval):"; + AO_double_store_acquire(&val, newval); +# else + (void)"No AO_double_store_acquire"; +# endif +# ifdef AO_HAVE_double_fetch_and_add_acquire + (void)"AO_double_fetch_and_add_acquire(&val, incr):"; + (void)AO_double_fetch_and_add_acquire(&val, incr); +# else + (void)"No AO_double_fetch_and_add_acquire"; +# endif +# ifdef AO_HAVE_double_fetch_and_add1_acquire + (void)"AO_double_fetch_and_add1_acquire(&val):"; + (void)AO_double_fetch_and_add1_acquire(&val); +# else + (void)"No AO_double_fetch_and_add1_acquire"; +# endif +# ifdef AO_HAVE_double_fetch_and_sub1_acquire + (void)"AO_double_fetch_and_sub1_acquire(&val):"; + (void)AO_double_fetch_and_sub1_acquire(&val); +# else + (void)"No AO_double_fetch_and_sub1_acquire"; +# endif +# ifdef AO_HAVE_double_and_acquire + (void)"AO_double_and_acquire(&val, incr):"; + AO_double_and_acquire(&val, incr); +# else + (void)"No AO_double_and_acquire"; +# endif +# ifdef AO_HAVE_double_or_acquire + (void)"AO_double_or_acquire(&val, incr):"; + AO_double_or_acquire(&val, incr); +# else + (void)"No AO_double_or_acquire"; +# endif +# ifdef AO_HAVE_double_xor_acquire + (void)"AO_double_xor_acquire(&val, incr):"; + AO_double_xor_acquire(&val, incr); +# else + (void)"No AO_double_xor_acquire"; +# endif +# ifdef AO_HAVE_double_compare_and_swap_acquire + (void)"AO_double_compare_and_swap_acquire(&val, oldval, newval):"; + if (!AO_double_compare_and_swap_acquire(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_double_compare_and_swap_acquire"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_acquire */ + /* TODO: Add AO_compare_and_swap_double_acquire */ +# ifdef AO_HAVE_double_fetch_compare_and_swap_acquire + (void)"AO_double_fetch_compare_and_swap_acquire(&val, oldval, newval):"; + if (AO_double_fetch_compare_and_swap_acquire(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_double_fetch_compare_and_swap_acquire"; +# endif + +# if defined(AO_HAVE_test_and_set_acquire) + (void)"AO_test_and_set_acquire(&ts):"; + (void)AO_test_and_set_acquire(&ts); +# else + (void)"No AO_test_and_set_acquire"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void double_list_atomic_read(void) +{ +# if defined(AO_HAVE_double_load_read) || defined(AO_HAVE_double_store_read) \ + || defined(AO_HAVE_double_fetch_and_add_read) \ + || defined(AO_HAVE_double_fetch_and_add1_read) \ + || defined(AO_HAVE_double_and_read) \ + || defined(AO_HAVE_double_compare_and_swap_read) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_read) + static volatile AO_double_t val /* = 0 */; +# endif +# if defined(AO_HAVE_double_compare_and_swap_read) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_read) + static AO_double_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_double_store_read) \ + || defined(AO_HAVE_double_compare_and_swap_read) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_read) + static AO_double_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_fetch_and_add_read) || defined(AO_HAVE_double_and_read) \ + || defined(AO_HAVE_double_or_read) || defined(AO_HAVE_double_xor_read) + static AO_double_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_read) + (void)"AO_nop_read(): "; + AO_nop_read(); +# else + (void)"No AO_nop_read"; +# endif + +# ifdef AO_HAVE_double_load_read + (void)"AO_double_load_read(&val):"; + (void)AO_double_load_read(&val); +# else + (void)"No AO_double_load_read"; +# endif +# ifdef AO_HAVE_double_store_read + (void)"AO_double_store_read(&val, newval):"; + AO_double_store_read(&val, newval); +# else + (void)"No AO_double_store_read"; +# endif +# ifdef AO_HAVE_double_fetch_and_add_read + (void)"AO_double_fetch_and_add_read(&val, incr):"; + (void)AO_double_fetch_and_add_read(&val, incr); +# else + (void)"No AO_double_fetch_and_add_read"; +# endif +# ifdef AO_HAVE_double_fetch_and_add1_read + (void)"AO_double_fetch_and_add1_read(&val):"; + (void)AO_double_fetch_and_add1_read(&val); +# else + (void)"No AO_double_fetch_and_add1_read"; +# endif +# ifdef AO_HAVE_double_fetch_and_sub1_read + (void)"AO_double_fetch_and_sub1_read(&val):"; + (void)AO_double_fetch_and_sub1_read(&val); +# else + (void)"No AO_double_fetch_and_sub1_read"; +# endif +# ifdef AO_HAVE_double_and_read + (void)"AO_double_and_read(&val, incr):"; + AO_double_and_read(&val, incr); +# else + (void)"No AO_double_and_read"; +# endif +# ifdef AO_HAVE_double_or_read + (void)"AO_double_or_read(&val, incr):"; + AO_double_or_read(&val, incr); +# else + (void)"No AO_double_or_read"; +# endif +# ifdef AO_HAVE_double_xor_read + (void)"AO_double_xor_read(&val, incr):"; + AO_double_xor_read(&val, incr); +# else + (void)"No AO_double_xor_read"; +# endif +# ifdef AO_HAVE_double_compare_and_swap_read + (void)"AO_double_compare_and_swap_read(&val, oldval, newval):"; + if (!AO_double_compare_and_swap_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_double_compare_and_swap_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_read */ + /* TODO: Add AO_compare_and_swap_double_read */ +# ifdef AO_HAVE_double_fetch_compare_and_swap_read + (void)"AO_double_fetch_compare_and_swap_read(&val, oldval, newval):"; + if (AO_double_fetch_compare_and_swap_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_double_fetch_compare_and_swap_read"; +# endif + +# if defined(AO_HAVE_test_and_set_read) + (void)"AO_test_and_set_read(&ts):"; + (void)AO_test_and_set_read(&ts); +# else + (void)"No AO_test_and_set_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void double_list_atomic_write(void) +{ +# if defined(AO_HAVE_double_load_write) || defined(AO_HAVE_double_store_write) \ + || defined(AO_HAVE_double_fetch_and_add_write) \ + || defined(AO_HAVE_double_fetch_and_add1_write) \ + || defined(AO_HAVE_double_and_write) \ + || defined(AO_HAVE_double_compare_and_swap_write) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_write) + static volatile AO_double_t val /* = 0 */; +# endif +# if defined(AO_HAVE_double_compare_and_swap_write) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_write) + static AO_double_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_double_store_write) \ + || defined(AO_HAVE_double_compare_and_swap_write) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_write) + static AO_double_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_write) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_fetch_and_add_write) || defined(AO_HAVE_double_and_write) \ + || defined(AO_HAVE_double_or_write) || defined(AO_HAVE_double_xor_write) + static AO_double_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_write) + (void)"AO_nop_write(): "; + AO_nop_write(); +# else + (void)"No AO_nop_write"; +# endif + +# ifdef AO_HAVE_double_load_write + (void)"AO_double_load_write(&val):"; + (void)AO_double_load_write(&val); +# else + (void)"No AO_double_load_write"; +# endif +# ifdef AO_HAVE_double_store_write + (void)"AO_double_store_write(&val, newval):"; + AO_double_store_write(&val, newval); +# else + (void)"No AO_double_store_write"; +# endif +# ifdef AO_HAVE_double_fetch_and_add_write + (void)"AO_double_fetch_and_add_write(&val, incr):"; + (void)AO_double_fetch_and_add_write(&val, incr); +# else + (void)"No AO_double_fetch_and_add_write"; +# endif +# ifdef AO_HAVE_double_fetch_and_add1_write + (void)"AO_double_fetch_and_add1_write(&val):"; + (void)AO_double_fetch_and_add1_write(&val); +# else + (void)"No AO_double_fetch_and_add1_write"; +# endif +# ifdef AO_HAVE_double_fetch_and_sub1_write + (void)"AO_double_fetch_and_sub1_write(&val):"; + (void)AO_double_fetch_and_sub1_write(&val); +# else + (void)"No AO_double_fetch_and_sub1_write"; +# endif +# ifdef AO_HAVE_double_and_write + (void)"AO_double_and_write(&val, incr):"; + AO_double_and_write(&val, incr); +# else + (void)"No AO_double_and_write"; +# endif +# ifdef AO_HAVE_double_or_write + (void)"AO_double_or_write(&val, incr):"; + AO_double_or_write(&val, incr); +# else + (void)"No AO_double_or_write"; +# endif +# ifdef AO_HAVE_double_xor_write + (void)"AO_double_xor_write(&val, incr):"; + AO_double_xor_write(&val, incr); +# else + (void)"No AO_double_xor_write"; +# endif +# ifdef AO_HAVE_double_compare_and_swap_write + (void)"AO_double_compare_and_swap_write(&val, oldval, newval):"; + if (!AO_double_compare_and_swap_write(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_double_compare_and_swap_write"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_write */ + /* TODO: Add AO_compare_and_swap_double_write */ +# ifdef AO_HAVE_double_fetch_compare_and_swap_write + (void)"AO_double_fetch_compare_and_swap_write(&val, oldval, newval):"; + if (AO_double_fetch_compare_and_swap_write(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_double_fetch_compare_and_swap_write"; +# endif + +# if defined(AO_HAVE_test_and_set_write) + (void)"AO_test_and_set_write(&ts):"; + (void)AO_test_and_set_write(&ts); +# else + (void)"No AO_test_and_set_write"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void double_list_atomic_full(void) +{ +# if defined(AO_HAVE_double_load_full) || defined(AO_HAVE_double_store_full) \ + || defined(AO_HAVE_double_fetch_and_add_full) \ + || defined(AO_HAVE_double_fetch_and_add1_full) \ + || defined(AO_HAVE_double_and_full) \ + || defined(AO_HAVE_double_compare_and_swap_full) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_full) + static volatile AO_double_t val /* = 0 */; +# endif +# if defined(AO_HAVE_double_compare_and_swap_full) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_full) + static AO_double_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_double_store_full) \ + || defined(AO_HAVE_double_compare_and_swap_full) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_full) + static AO_double_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_full) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_fetch_and_add_full) || defined(AO_HAVE_double_and_full) \ + || defined(AO_HAVE_double_or_full) || defined(AO_HAVE_double_xor_full) + static AO_double_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_full) + (void)"AO_nop_full(): "; + AO_nop_full(); +# else + (void)"No AO_nop_full"; +# endif + +# ifdef AO_HAVE_double_load_full + (void)"AO_double_load_full(&val):"; + (void)AO_double_load_full(&val); +# else + (void)"No AO_double_load_full"; +# endif +# ifdef AO_HAVE_double_store_full + (void)"AO_double_store_full(&val, newval):"; + AO_double_store_full(&val, newval); +# else + (void)"No AO_double_store_full"; +# endif +# ifdef AO_HAVE_double_fetch_and_add_full + (void)"AO_double_fetch_and_add_full(&val, incr):"; + (void)AO_double_fetch_and_add_full(&val, incr); +# else + (void)"No AO_double_fetch_and_add_full"; +# endif +# ifdef AO_HAVE_double_fetch_and_add1_full + (void)"AO_double_fetch_and_add1_full(&val):"; + (void)AO_double_fetch_and_add1_full(&val); +# else + (void)"No AO_double_fetch_and_add1_full"; +# endif +# ifdef AO_HAVE_double_fetch_and_sub1_full + (void)"AO_double_fetch_and_sub1_full(&val):"; + (void)AO_double_fetch_and_sub1_full(&val); +# else + (void)"No AO_double_fetch_and_sub1_full"; +# endif +# ifdef AO_HAVE_double_and_full + (void)"AO_double_and_full(&val, incr):"; + AO_double_and_full(&val, incr); +# else + (void)"No AO_double_and_full"; +# endif +# ifdef AO_HAVE_double_or_full + (void)"AO_double_or_full(&val, incr):"; + AO_double_or_full(&val, incr); +# else + (void)"No AO_double_or_full"; +# endif +# ifdef AO_HAVE_double_xor_full + (void)"AO_double_xor_full(&val, incr):"; + AO_double_xor_full(&val, incr); +# else + (void)"No AO_double_xor_full"; +# endif +# ifdef AO_HAVE_double_compare_and_swap_full + (void)"AO_double_compare_and_swap_full(&val, oldval, newval):"; + if (!AO_double_compare_and_swap_full(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_double_compare_and_swap_full"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_full */ + /* TODO: Add AO_compare_and_swap_double_full */ +# ifdef AO_HAVE_double_fetch_compare_and_swap_full + (void)"AO_double_fetch_compare_and_swap_full(&val, oldval, newval):"; + if (AO_double_fetch_compare_and_swap_full(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_double_fetch_compare_and_swap_full"; +# endif + +# if defined(AO_HAVE_test_and_set_full) + (void)"AO_test_and_set_full(&ts):"; + (void)AO_test_and_set_full(&ts); +# else + (void)"No AO_test_and_set_full"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void double_list_atomic_release_write(void) +{ +# if defined(AO_HAVE_double_load_release_write) || defined(AO_HAVE_double_store_release_write) \ + || defined(AO_HAVE_double_fetch_and_add_release_write) \ + || defined(AO_HAVE_double_fetch_and_add1_release_write) \ + || defined(AO_HAVE_double_and_release_write) \ + || defined(AO_HAVE_double_compare_and_swap_release_write) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_release_write) + static volatile AO_double_t val /* = 0 */; +# endif +# if defined(AO_HAVE_double_compare_and_swap_release_write) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_release_write) + static AO_double_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_double_store_release_write) \ + || defined(AO_HAVE_double_compare_and_swap_release_write) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_release_write) + static AO_double_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_release_write) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_fetch_and_add_release_write) || defined(AO_HAVE_double_and_release_write) \ + || defined(AO_HAVE_double_or_release_write) || defined(AO_HAVE_double_xor_release_write) + static AO_double_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_release_write) + (void)"AO_nop_release_write(): "; + AO_nop_release_write(); +# else + (void)"No AO_nop_release_write"; +# endif + +# ifdef AO_HAVE_double_load_release_write + (void)"AO_double_load_release_write(&val):"; + (void)AO_double_load_release_write(&val); +# else + (void)"No AO_double_load_release_write"; +# endif +# ifdef AO_HAVE_double_store_release_write + (void)"AO_double_store_release_write(&val, newval):"; + AO_double_store_release_write(&val, newval); +# else + (void)"No AO_double_store_release_write"; +# endif +# ifdef AO_HAVE_double_fetch_and_add_release_write + (void)"AO_double_fetch_and_add_release_write(&val, incr):"; + (void)AO_double_fetch_and_add_release_write(&val, incr); +# else + (void)"No AO_double_fetch_and_add_release_write"; +# endif +# ifdef AO_HAVE_double_fetch_and_add1_release_write + (void)"AO_double_fetch_and_add1_release_write(&val):"; + (void)AO_double_fetch_and_add1_release_write(&val); +# else + (void)"No AO_double_fetch_and_add1_release_write"; +# endif +# ifdef AO_HAVE_double_fetch_and_sub1_release_write + (void)"AO_double_fetch_and_sub1_release_write(&val):"; + (void)AO_double_fetch_and_sub1_release_write(&val); +# else + (void)"No AO_double_fetch_and_sub1_release_write"; +# endif +# ifdef AO_HAVE_double_and_release_write + (void)"AO_double_and_release_write(&val, incr):"; + AO_double_and_release_write(&val, incr); +# else + (void)"No AO_double_and_release_write"; +# endif +# ifdef AO_HAVE_double_or_release_write + (void)"AO_double_or_release_write(&val, incr):"; + AO_double_or_release_write(&val, incr); +# else + (void)"No AO_double_or_release_write"; +# endif +# ifdef AO_HAVE_double_xor_release_write + (void)"AO_double_xor_release_write(&val, incr):"; + AO_double_xor_release_write(&val, incr); +# else + (void)"No AO_double_xor_release_write"; +# endif +# ifdef AO_HAVE_double_compare_and_swap_release_write + (void)"AO_double_compare_and_swap_release_write(&val, oldval, newval):"; + if (!AO_double_compare_and_swap_release_write(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_double_compare_and_swap_release_write"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_release_write */ + /* TODO: Add AO_compare_and_swap_double_release_write */ +# ifdef AO_HAVE_double_fetch_compare_and_swap_release_write + (void)"AO_double_fetch_compare_and_swap_release_write(&val, oldval, newval):"; + if (AO_double_fetch_compare_and_swap_release_write(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_double_fetch_compare_and_swap_release_write"; +# endif + +# if defined(AO_HAVE_test_and_set_release_write) + (void)"AO_test_and_set_release_write(&ts):"; + (void)AO_test_and_set_release_write(&ts); +# else + (void)"No AO_test_and_set_release_write"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void double_list_atomic_acquire_read(void) +{ +# if defined(AO_HAVE_double_load_acquire_read) || defined(AO_HAVE_double_store_acquire_read) \ + || defined(AO_HAVE_double_fetch_and_add_acquire_read) \ + || defined(AO_HAVE_double_fetch_and_add1_acquire_read) \ + || defined(AO_HAVE_double_and_acquire_read) \ + || defined(AO_HAVE_double_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_acquire_read) + static volatile AO_double_t val /* = 0 */; +# endif +# if defined(AO_HAVE_double_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_acquire_read) + static AO_double_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_double_store_acquire_read) \ + || defined(AO_HAVE_double_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_acquire_read) + static AO_double_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_acquire_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_fetch_and_add_acquire_read) || defined(AO_HAVE_double_and_acquire_read) \ + || defined(AO_HAVE_double_or_acquire_read) || defined(AO_HAVE_double_xor_acquire_read) + static AO_double_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_acquire_read) + (void)"AO_nop_acquire_read(): "; + AO_nop_acquire_read(); +# else + (void)"No AO_nop_acquire_read"; +# endif + +# ifdef AO_HAVE_double_load_acquire_read + (void)"AO_double_load_acquire_read(&val):"; + (void)AO_double_load_acquire_read(&val); +# else + (void)"No AO_double_load_acquire_read"; +# endif +# ifdef AO_HAVE_double_store_acquire_read + (void)"AO_double_store_acquire_read(&val, newval):"; + AO_double_store_acquire_read(&val, newval); +# else + (void)"No AO_double_store_acquire_read"; +# endif +# ifdef AO_HAVE_double_fetch_and_add_acquire_read + (void)"AO_double_fetch_and_add_acquire_read(&val, incr):"; + (void)AO_double_fetch_and_add_acquire_read(&val, incr); +# else + (void)"No AO_double_fetch_and_add_acquire_read"; +# endif +# ifdef AO_HAVE_double_fetch_and_add1_acquire_read + (void)"AO_double_fetch_and_add1_acquire_read(&val):"; + (void)AO_double_fetch_and_add1_acquire_read(&val); +# else + (void)"No AO_double_fetch_and_add1_acquire_read"; +# endif +# ifdef AO_HAVE_double_fetch_and_sub1_acquire_read + (void)"AO_double_fetch_and_sub1_acquire_read(&val):"; + (void)AO_double_fetch_and_sub1_acquire_read(&val); +# else + (void)"No AO_double_fetch_and_sub1_acquire_read"; +# endif +# ifdef AO_HAVE_double_and_acquire_read + (void)"AO_double_and_acquire_read(&val, incr):"; + AO_double_and_acquire_read(&val, incr); +# else + (void)"No AO_double_and_acquire_read"; +# endif +# ifdef AO_HAVE_double_or_acquire_read + (void)"AO_double_or_acquire_read(&val, incr):"; + AO_double_or_acquire_read(&val, incr); +# else + (void)"No AO_double_or_acquire_read"; +# endif +# ifdef AO_HAVE_double_xor_acquire_read + (void)"AO_double_xor_acquire_read(&val, incr):"; + AO_double_xor_acquire_read(&val, incr); +# else + (void)"No AO_double_xor_acquire_read"; +# endif +# ifdef AO_HAVE_double_compare_and_swap_acquire_read + (void)"AO_double_compare_and_swap_acquire_read(&val, oldval, newval):"; + if (!AO_double_compare_and_swap_acquire_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_double_compare_and_swap_acquire_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_acquire_read */ + /* TODO: Add AO_compare_and_swap_double_acquire_read */ +# ifdef AO_HAVE_double_fetch_compare_and_swap_acquire_read + (void)"AO_double_fetch_compare_and_swap_acquire_read(&val, oldval, newval):"; + if (AO_double_fetch_compare_and_swap_acquire_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_double_fetch_compare_and_swap_acquire_read"; +# endif + +# if defined(AO_HAVE_test_and_set_acquire_read) + (void)"AO_test_and_set_acquire_read(&ts):"; + (void)AO_test_and_set_acquire_read(&ts); +# else + (void)"No AO_test_and_set_acquire_read"; +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* This generates a compilable program. But it is really meant to be */ +/* be used only with cc -E, to inspect the expensions generated by */ +/* primitives. */ + +/* The result will not link or run. */ + +#include /* for exit() */ + +void double_list_atomic_dd_acquire_read(void) +{ +# if defined(AO_HAVE_double_load_dd_acquire_read) || defined(AO_HAVE_double_store_dd_acquire_read) \ + || defined(AO_HAVE_double_fetch_and_add_dd_acquire_read) \ + || defined(AO_HAVE_double_fetch_and_add1_dd_acquire_read) \ + || defined(AO_HAVE_double_and_dd_acquire_read) \ + || defined(AO_HAVE_double_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_dd_acquire_read) + static volatile AO_double_t val /* = 0 */; +# endif +# if defined(AO_HAVE_double_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_dd_acquire_read) + static AO_double_t oldval /* = 0 */; +# endif +# if defined(AO_HAVE_double_store_dd_acquire_read) \ + || defined(AO_HAVE_double_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_double_fetch_compare_and_swap_dd_acquire_read) + static AO_double_t newval /* = 0 */; +# endif +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + AO_TS_t ts = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_fetch_and_add_dd_acquire_read) || defined(AO_HAVE_double_and_dd_acquire_read) \ + || defined(AO_HAVE_double_or_dd_acquire_read) || defined(AO_HAVE_double_xor_dd_acquire_read) + static AO_double_t incr /* = 0 */; +# endif + +# if defined(AO_HAVE_nop_dd_acquire_read) + (void)"AO_nop_dd_acquire_read(): "; + AO_nop_dd_acquire_read(); +# else + (void)"No AO_nop_dd_acquire_read"; +# endif + +# ifdef AO_HAVE_double_load_dd_acquire_read + (void)"AO_double_load_dd_acquire_read(&val):"; + (void)AO_double_load_dd_acquire_read(&val); +# else + (void)"No AO_double_load_dd_acquire_read"; +# endif +# ifdef AO_HAVE_double_store_dd_acquire_read + (void)"AO_double_store_dd_acquire_read(&val, newval):"; + AO_double_store_dd_acquire_read(&val, newval); +# else + (void)"No AO_double_store_dd_acquire_read"; +# endif +# ifdef AO_HAVE_double_fetch_and_add_dd_acquire_read + (void)"AO_double_fetch_and_add_dd_acquire_read(&val, incr):"; + (void)AO_double_fetch_and_add_dd_acquire_read(&val, incr); +# else + (void)"No AO_double_fetch_and_add_dd_acquire_read"; +# endif +# ifdef AO_HAVE_double_fetch_and_add1_dd_acquire_read + (void)"AO_double_fetch_and_add1_dd_acquire_read(&val):"; + (void)AO_double_fetch_and_add1_dd_acquire_read(&val); +# else + (void)"No AO_double_fetch_and_add1_dd_acquire_read"; +# endif +# ifdef AO_HAVE_double_fetch_and_sub1_dd_acquire_read + (void)"AO_double_fetch_and_sub1_dd_acquire_read(&val):"; + (void)AO_double_fetch_and_sub1_dd_acquire_read(&val); +# else + (void)"No AO_double_fetch_and_sub1_dd_acquire_read"; +# endif +# ifdef AO_HAVE_double_and_dd_acquire_read + (void)"AO_double_and_dd_acquire_read(&val, incr):"; + AO_double_and_dd_acquire_read(&val, incr); +# else + (void)"No AO_double_and_dd_acquire_read"; +# endif +# ifdef AO_HAVE_double_or_dd_acquire_read + (void)"AO_double_or_dd_acquire_read(&val, incr):"; + AO_double_or_dd_acquire_read(&val, incr); +# else + (void)"No AO_double_or_dd_acquire_read"; +# endif +# ifdef AO_HAVE_double_xor_dd_acquire_read + (void)"AO_double_xor_dd_acquire_read(&val, incr):"; + AO_double_xor_dd_acquire_read(&val, incr); +# else + (void)"No AO_double_xor_dd_acquire_read"; +# endif +# ifdef AO_HAVE_double_compare_and_swap_dd_acquire_read + (void)"AO_double_compare_and_swap_dd_acquire_read(&val, oldval, newval):"; + if (!AO_double_compare_and_swap_dd_acquire_read(&val, oldval, newval)) + exit(1); +# else + (void)"No AO_double_compare_and_swap_dd_acquire_read"; +# endif + /* TODO: Add AO_compare_double_and_swap_double_dd_acquire_read */ + /* TODO: Add AO_compare_and_swap_double_dd_acquire_read */ +# ifdef AO_HAVE_double_fetch_compare_and_swap_dd_acquire_read + (void)"AO_double_fetch_compare_and_swap_dd_acquire_read(&val, oldval, newval):"; + if (AO_double_fetch_compare_and_swap_dd_acquire_read(&val, oldval, newval) != oldval) + exit(1); +# else + (void)"No AO_double_fetch_compare_and_swap_dd_acquire_read"; +# endif + +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + (void)"AO_test_and_set_dd_acquire_read(&ts):"; + (void)AO_test_and_set_dd_acquire_read(&ts); +# else + (void)"No AO_test_and_set_dd_acquire_read"; +# endif +} diff --git a/src/bdwgc/libatomic_ops/tests/list_atomic.template b/src/bdwgc/libatomic_ops/tests/list_atomic.template index 3e748f4b0..26a13f4b7 100644 --- a/src/bdwgc/libatomic_ops/tests/list_atomic.template +++ b/src/bdwgc/libatomic_ops/tests/list_atomic.template @@ -11,6 +11,8 @@ /* The result will not link or run. */ +#include /* for exit() */ + void XSIZE_list_atomicXX(void) { # if defined(AO_HAVE_XSIZE_loadXX) || defined(AO_HAVE_XSIZE_storeXX) \ @@ -31,7 +33,7 @@ void XSIZE_list_atomicXX(void) static XCTYPE newval /* = 0 */; # endif # if defined(AO_HAVE_test_and_setXX) - AO_TS_t ts; + AO_TS_t ts = AO_TS_INITIALIZER; # endif # if defined(AO_HAVE_XSIZE_fetch_and_addXX) || defined(AO_HAVE_XSIZE_andXX) \ || defined(AO_HAVE_XSIZE_orXX) || defined(AO_HAVE_XSIZE_xorXX) @@ -47,7 +49,7 @@ void XSIZE_list_atomicXX(void) # ifdef AO_HAVE_XSIZE_loadXX (void)"AO_XSIZE_loadXX(&val):"; - AO_XSIZE_loadXX(&val); + (void)AO_XSIZE_loadXX(&val); # else (void)"No AO_XSIZE_loadXX"; # endif @@ -59,19 +61,19 @@ void XSIZE_list_atomicXX(void) # endif # ifdef AO_HAVE_XSIZE_fetch_and_addXX (void)"AO_XSIZE_fetch_and_addXX(&val, incr):"; - AO_XSIZE_fetch_and_addXX(&val, incr); + (void)AO_XSIZE_fetch_and_addXX(&val, incr); # else (void)"No AO_XSIZE_fetch_and_addXX"; # endif # ifdef AO_HAVE_XSIZE_fetch_and_add1XX (void)"AO_XSIZE_fetch_and_add1XX(&val):"; - AO_XSIZE_fetch_and_add1XX(&val); + (void)AO_XSIZE_fetch_and_add1XX(&val); # else (void)"No AO_XSIZE_fetch_and_add1XX"; # endif # ifdef AO_HAVE_XSIZE_fetch_and_sub1XX (void)"AO_XSIZE_fetch_and_sub1XX(&val):"; - AO_XSIZE_fetch_and_sub1XX(&val); + (void)AO_XSIZE_fetch_and_sub1XX(&val); # else (void)"No AO_XSIZE_fetch_and_sub1XX"; # endif @@ -95,7 +97,8 @@ void XSIZE_list_atomicXX(void) # endif # ifdef AO_HAVE_XSIZE_compare_and_swapXX (void)"AO_XSIZE_compare_and_swapXX(&val, oldval, newval):"; - AO_XSIZE_compare_and_swapXX(&val, oldval, newval); + if (!AO_XSIZE_compare_and_swapXX(&val, oldval, newval)) + exit(1); # else (void)"No AO_XSIZE_compare_and_swapXX"; # endif @@ -103,14 +106,15 @@ void XSIZE_list_atomicXX(void) /* TODO: Add AO_compare_and_swap_doubleXX */ # ifdef AO_HAVE_XSIZE_fetch_compare_and_swapXX (void)"AO_XSIZE_fetch_compare_and_swapXX(&val, oldval, newval):"; - AO_XSIZE_fetch_compare_and_swapXX(&val, oldval, newval); + if (AO_XSIZE_fetch_compare_and_swapXX(&val, oldval, newval) != oldval) + exit(1); # else (void)"No AO_XSIZE_fetch_compare_and_swapXX"; # endif # if defined(AO_HAVE_test_and_setXX) (void)"AO_test_and_setXX(&ts):"; - AO_test_and_setXX(&ts); + (void)AO_test_and_setXX(&ts); # else (void)"No AO_test_and_setXX"; # endif diff --git a/src/bdwgc/libatomic_ops/tests/run_parallel.h b/src/bdwgc/libatomic_ops/tests/run_parallel.h index 42110dc17..376b3c766 100644 --- a/src/bdwgc/libatomic_ops/tests/run_parallel.h +++ b/src/bdwgc/libatomic_ops/tests/run_parallel.h @@ -33,16 +33,20 @@ #include "atomic_ops.h" -#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(abort) +#if !defined(AO_ATOMIC_OPS_H) && !defined(CPPCHECK) +# error Wrong atomic_ops.h included. +#endif + +#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(AO_HAVE_abort) # define abort() _exit(-1) /* there is no abort() in WinCE */ #endif -#ifndef _WIN64 -# define AO_PTRDIFF_T long -#elif defined(__int64) -# define AO_PTRDIFF_T __int64 -#else -# define AO_PTRDIFF_T long long +#ifndef AO_PTRDIFF_T +# define AO_PTRDIFF_T ptrdiff_t +#endif + +#ifndef MAX_NTHREADS +# define MAX_NTHREADS 100 #endif typedef void * (* thr_func)(void *); @@ -55,12 +59,11 @@ void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name); void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name) { pthread_attr_t attr; - pthread_t thr[100]; + pthread_t thr[MAX_NTHREADS]; int i; - int code; printf("Testing %s\n", name); - if (nthreads > 100) + if (nthreads > MAX_NTHREADS) { fprintf(stderr, "run_parallel: requested too many threads\n"); abort(); @@ -80,7 +83,8 @@ void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name) for (i = 0; i < nthreads; ++i) { - if ((code = pthread_create(thr + i, &attr, f1, (void *)(long)i)) != 0) + int code = pthread_create(thr + i, &attr, f1, (void *)(long)i); + if (code != 0) { fprintf(stderr, "pthread_create returned %d, thread %d\n", code, i); abort(); @@ -88,7 +92,8 @@ void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name) } for (i = 0; i < nthreads; ++i) { - if ((code = pthread_join(thr[i], NULL)) != 0) + int code = pthread_join(thr[i], NULL); + if (code != 0) { fprintf(stderr, "pthread_join returned %d, thread %d\n", code, i); abort(); @@ -110,11 +115,11 @@ void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name) #ifdef USE_VXTHREADS void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name) { - int thr[100]; + int thr[MAX_NTHREADS]; int i; printf("Testing %s\n", name); - if (nthreads > 100) + if (nthreads > MAX_NTHREADS) { fprintf(stderr, "run_parallel: requested too many threads\n"); taskSuspend(0); @@ -165,13 +170,12 @@ DWORD WINAPI tramp(LPVOID param) void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name) { - HANDLE thr[100]; - struct tramp_args args[100]; + HANDLE thr[MAX_NTHREADS]; + struct tramp_args args[MAX_NTHREADS]; int i; - DWORD code; printf("Testing %s\n", name); - if (nthreads > 100) + if (nthreads > MAX_NTHREADS) { fprintf(stderr, "run_parallel: requested too many threads\n"); abort(); @@ -191,7 +195,8 @@ void * run_parallel(int nthreads, thr_func f1, test_func t, const char *name) } for (i = 0; i < nthreads; ++i) { - if ((code = WaitForSingleObject(thr[i], INFINITE)) != WAIT_OBJECT_0) + DWORD code = WaitForSingleObject(thr[i], INFINITE); + if (code != WAIT_OBJECT_0) { fprintf(stderr, "WaitForSingleObject returned %lu, thread %d\n", (unsigned long)code, i); diff --git a/src/bdwgc/libatomic_ops/tests/test_atomic.c b/src/bdwgc/libatomic_ops/tests/test_atomic.c index b063a92d9..a301ced88 100644 --- a/src/bdwgc/libatomic_ops/tests/test_atomic.c +++ b/src/bdwgc/libatomic_ops/tests/test_atomic.c @@ -15,7 +15,8 @@ # include "config.h" #endif -#if defined(AO_NO_PTHREADS) && defined(AO_USE_PTHREAD_DEFS) +#if (defined(AO_NO_PTHREADS) || defined(__MINGW32__)) \ + && defined(AO_USE_PTHREAD_DEFS) # include int main(void) @@ -30,7 +31,7 @@ #include "test_atomic_include.h" -#ifdef AO_USE_PTHREAD_DEFS +#if defined(AO_USE_PTHREAD_DEFS) || defined(AO_PREFER_GENERALIZED) # define NITERS 100000 #else # define NITERS 10000000 @@ -137,6 +138,13 @@ AO_TS_t lock = AO_TS_INITIALIZER; unsigned long locked_counter; volatile unsigned long junk = 13; +AO_ATTR_NO_SANITIZE_THREAD +void do_junk(void) +{ + junk *= 17; + junk *= 19; +} + void * test_and_set_thr(void * id) { unsigned long i; @@ -164,8 +172,7 @@ void * test_and_set_thr(void * id) --locked_counter; AO_CLEAR(&lock); /* Spend a bit of time outside the lock. */ - junk *= 17; - junk *= 17; + do_junk(); } return 0; } @@ -177,6 +184,54 @@ int test_and_set_test(void) #endif /* defined(AO_HAVE_test_and_set_acquire) */ +#if (!defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__BORLANDC__) \ + || defined(AO_USE_NO_SIGNALS) || defined(AO_USE_WIN32_PTHREADS)) \ + && defined(AO_TEST_EMULATION) + +# ifdef __cplusplus + extern "C" { +# endif + + void AO_store_full_emulation(volatile AO_t *addr, AO_t val); + AO_t AO_fetch_compare_and_swap_emulation(volatile AO_t *addr, AO_t old_val, + AO_t new_val); +# ifdef AO_HAVE_double_t + int AO_compare_double_and_swap_double_emulation(volatile AO_double_t *, + AO_t old_val1, AO_t old_val2, + AO_t new_val1, AO_t new_val2); +# endif + +# ifdef __cplusplus + } /* extern "C" */ +# endif + + void test_atomic_emulation(void) + { + AO_t x; +# ifdef AO_HAVE_double_t + AO_double_t w; /* double-word alignment not needed */ + + w.AO_val1 = 0; + w.AO_val2 = 0; + TA_assert(!AO_compare_double_and_swap_double_emulation(&w, 4116, 2121, + 8537, 6410)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_double_and_swap_double_emulation(&w, 0, 0, + 8537, 6410)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); +# endif + AO_store_full_emulation(&x, 1314); + TA_assert(x == 1314); + TA_assert(AO_fetch_compare_and_swap_emulation(&x, 14, 13117) == 1314); + TA_assert(x == 1314); + TA_assert(AO_fetch_compare_and_swap_emulation(&x, 1314, 14117) == 1314); + TA_assert(x == 14117); + } + +#else +# define test_atomic_emulation() (void)0 +#endif /* _MSC_VER && !AO_USE_NO_SIGNALS || !AO_TEST_EMULATION */ + int main(void) { test_atomic(); @@ -187,6 +242,7 @@ int main(void) test_atomic_full(); test_atomic_release_write(); test_atomic_acquire_read(); + test_atomic_dd_acquire_read(); # if defined(AO_HAVE_fetch_and_add1) && defined(AO_HAVE_fetch_and_sub1) run_parallel(4, add1sub1_thr, add1sub1_test, "add1/sub1"); # endif @@ -198,6 +254,7 @@ int main(void) run_parallel(5, test_and_set_thr, test_and_set_test, "test_and_set"); # endif + test_atomic_emulation(); return 0; } diff --git a/src/bdwgc/libatomic_ops/tests/test_atomic_include.h b/src/bdwgc/libatomic_ops/tests/test_atomic_include.h new file mode 100644 index 000000000..2ec639698 --- /dev/null +++ b/src/bdwgc/libatomic_ops/tests/test_atomic_include.h @@ -0,0 +1,5265 @@ +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* Some basic sanity tests. These do not test the barrier semantics. */ + +#undef TA_assert +#define TA_assert(e) \ + if (!(e)) { fprintf(stderr, "Assertion failed %s:%d (barrier: )\n", \ + __FILE__, __LINE__), exit(1); } + +#undef MISSING +#define MISSING(name) \ + printf("Missing: %s\n", #name "") + +#if defined(CPPCHECK) + void list_atomic(void); + void char_list_atomic(void); + void short_list_atomic(void); + void int_list_atomic(void); + void double_list_atomic(void); +#endif + +void test_atomic(void) +{ + AO_t x; + unsigned char b; + unsigned short s; + unsigned int zz; +# if defined(AO_HAVE_test_and_set) + AO_TS_t z = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_compare_and_swap) \ + || defined(AO_HAVE_double_load) \ + || defined(AO_HAVE_double_store) + static AO_double_t old_w; /* static to avoid misalignment */ + AO_double_t new_w; +# endif +# if defined(AO_HAVE_compare_and_swap_double) \ + || defined(AO_HAVE_compare_double_and_swap_double) \ + || defined(AO_HAVE_double_compare_and_swap) + static AO_double_t w; /* static to avoid misalignment */ + w.AO_val1 = 0; + w.AO_val2 = 0; +# endif + +# if defined(CPPCHECK) + list_atomic(); + char_list_atomic(); + short_list_atomic(); + int_list_atomic(); + double_list_atomic(); +# endif +# if defined(AO_HAVE_nop) + AO_nop(); +# elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \ + || !defined(AO_HAVE_nop_read) || !defined(AO_HAVE_nop_write) + MISSING(AO_nop); +# endif +# if defined(AO_HAVE_store) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile AO_t *)&x = 0; /* initialize to avoid false warning */ +# endif + AO_store(&x, 13); + TA_assert(x == 13); +# else +# if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \ + || !defined(AO_HAVE_store_release) \ + || !defined(AO_HAVE_store_release_write) \ + || !defined(AO_HAVE_store_write) + MISSING(AO_store); +# endif + x = 13; +# endif +# if defined(AO_HAVE_load) + TA_assert(AO_load(&x) == 13); +# elif !defined(AO_HAVE_load) || !defined(AO_HAVE_load_acquire) \ + || !defined(AO_HAVE_load_acquire_read) \ + || !defined(AO_HAVE_load_dd_acquire_read) \ + || !defined(AO_HAVE_load_full) || !defined(AO_HAVE_load_read) + MISSING(AO_load); +# endif +# if defined(AO_HAVE_test_and_set) + TA_assert(AO_test_and_set(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_set(&z) == AO_TS_SET); + TA_assert(AO_test_and_set(&z) == AO_TS_SET); + AO_CLEAR(&z); +# else + MISSING(AO_test_and_set); +# endif +# if defined(AO_HAVE_fetch_and_add) + TA_assert(AO_fetch_and_add(&x, 42) == 13); + TA_assert(AO_fetch_and_add(&x, (AO_t)(-42)) == 55); +# else + MISSING(AO_fetch_and_add); +# endif +# if defined(AO_HAVE_fetch_and_add1) + TA_assert(AO_fetch_and_add1(&x) == 13); +# else + MISSING(AO_fetch_and_add1); + ++x; +# endif +# if defined(AO_HAVE_fetch_and_sub1) + TA_assert(AO_fetch_and_sub1(&x) == 14); +# else + MISSING(AO_fetch_and_sub1); + --x; +# endif +# if defined(AO_HAVE_short_store) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile short *)&s = 0; +# endif + AO_short_store(&s, 13); +# else +# if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \ + || !defined(AO_HAVE_short_store_release) \ + || !defined(AO_HAVE_short_store_release_write) \ + || !defined(AO_HAVE_short_store_write) + MISSING(AO_short_store); +# endif + s = 13; +# endif +# if defined(AO_HAVE_short_load) + TA_assert(AO_short_load(&s) == 13); +# elif !defined(AO_HAVE_short_load) || !defined(AO_HAVE_short_load_acquire) \ + || !defined(AO_HAVE_short_load_acquire_read) \ + || !defined(AO_HAVE_short_load_dd_acquire_read) \ + || !defined(AO_HAVE_short_load_full) \ + || !defined(AO_HAVE_short_load_read) + MISSING(AO_short_load); +# endif +# if defined(AO_HAVE_short_fetch_and_add) + TA_assert(AO_short_fetch_and_add(&s, 42) == 13); + TA_assert(AO_short_fetch_and_add(&s, (unsigned short)-42) == 55); +# else + MISSING(AO_short_fetch_and_add); +# endif +# if defined(AO_HAVE_short_fetch_and_add1) + TA_assert(AO_short_fetch_and_add1(&s) == 13); +# else + MISSING(AO_short_fetch_and_add1); + ++s; +# endif +# if defined(AO_HAVE_short_fetch_and_sub1) + TA_assert(AO_short_fetch_and_sub1(&s) == 14); +# else + MISSING(AO_short_fetch_and_sub1); + --s; +# endif + TA_assert(*(volatile short *)&s == 13); +# if defined(AO_HAVE_char_store) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile char *)&b = 0; +# endif + AO_char_store(&b, 13); +# else +# if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \ + || !defined(AO_HAVE_char_store_release) \ + || !defined(AO_HAVE_char_store_release_write) \ + || !defined(AO_HAVE_char_store_write) + MISSING(AO_char_store); +# endif + b = 13; +# endif +# if defined(AO_HAVE_char_load) + TA_assert(AO_char_load(&b) == 13); +# elif !defined(AO_HAVE_char_load) || !defined(AO_HAVE_char_load_acquire) \ + || !defined(AO_HAVE_char_load_acquire_read) \ + || !defined(AO_HAVE_char_load_dd_acquire_read) \ + || !defined(AO_HAVE_char_load_full) || !defined(AO_HAVE_char_load_read) + MISSING(AO_char_load); +# endif +# if defined(AO_HAVE_char_fetch_and_add) + TA_assert(AO_char_fetch_and_add(&b, 42) == 13); + TA_assert(AO_char_fetch_and_add(&b, (unsigned char)-42) == 55); +# else + MISSING(AO_char_fetch_and_add); +# endif +# if defined(AO_HAVE_char_fetch_and_add1) + TA_assert(AO_char_fetch_and_add1(&b) == 13); +# else + MISSING(AO_char_fetch_and_add1); + ++b; +# endif +# if defined(AO_HAVE_char_fetch_and_sub1) + TA_assert(AO_char_fetch_and_sub1(&b) == 14); +# else + MISSING(AO_char_fetch_and_sub1); + --b; +# endif + TA_assert(*(volatile char *)&b == 13); +# if defined(AO_HAVE_int_store) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile int *)&zz = 0; +# endif + AO_int_store(&zz, 13); +# else +# if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \ + || !defined(AO_HAVE_int_store_release) \ + || !defined(AO_HAVE_int_store_release_write) \ + || !defined(AO_HAVE_int_store_write) + MISSING(AO_int_store); +# endif + zz = 13; +# endif +# if defined(AO_HAVE_int_load) + TA_assert(AO_int_load(&zz) == 13); +# elif !defined(AO_HAVE_int_load) || !defined(AO_HAVE_int_load_acquire) \ + || !defined(AO_HAVE_int_load_acquire_read) \ + || !defined(AO_HAVE_int_load_dd_acquire_read) \ + || !defined(AO_HAVE_int_load_full) || !defined(AO_HAVE_int_load_read) + MISSING(AO_int_load); +# endif +# if defined(AO_HAVE_int_fetch_and_add) + TA_assert(AO_int_fetch_and_add(&zz, 42) == 13); + TA_assert(AO_int_fetch_and_add(&zz, (unsigned int)-42) == 55); +# else + MISSING(AO_int_fetch_and_add); +# endif +# if defined(AO_HAVE_int_fetch_and_add1) + TA_assert(AO_int_fetch_and_add1(&zz) == 13); +# else + MISSING(AO_int_fetch_and_add1); + ++zz; +# endif +# if defined(AO_HAVE_int_fetch_and_sub1) + TA_assert(AO_int_fetch_and_sub1(&zz) == 14); +# else + MISSING(AO_int_fetch_and_sub1); + --zz; +# endif + TA_assert(*(volatile int *)&zz == 13); +# if defined(AO_HAVE_compare_and_swap) + TA_assert(!AO_compare_and_swap(&x, 14, 42)); + TA_assert(x == 13); + TA_assert(AO_compare_and_swap(&x, 13, 42)); + TA_assert(x == 42); +# else + MISSING(AO_compare_and_swap); + if (*(volatile AO_t *)&x == 13) x = 42; +# endif +# if defined(AO_HAVE_or) + AO_or(&x, 66); + TA_assert(x == 106); +# else +# if !defined(AO_HAVE_or) || !defined(AO_HAVE_or_acquire) \ + || !defined(AO_HAVE_or_acquire_read) || !defined(AO_HAVE_or_full) \ + || !defined(AO_HAVE_or_read) || !defined(AO_HAVE_or_release) \ + || !defined(AO_HAVE_or_release_write) || !defined(AO_HAVE_or_write) + MISSING(AO_or); +# endif + x |= 66; +# endif +# if defined(AO_HAVE_xor) + AO_xor(&x, 181); + TA_assert(x == 223); +# else +# if !defined(AO_HAVE_xor) || !defined(AO_HAVE_xor_acquire) \ + || !defined(AO_HAVE_xor_acquire_read) || !defined(AO_HAVE_xor_full) \ + || !defined(AO_HAVE_xor_read) || !defined(AO_HAVE_xor_release) \ + || !defined(AO_HAVE_xor_release_write) || !defined(AO_HAVE_xor_write) + MISSING(AO_xor); +# endif + x ^= 181; +# endif +# if defined(AO_HAVE_and) + AO_and(&x, 57); + TA_assert(x == 25); +# else +# if !defined(AO_HAVE_and) || !defined(AO_HAVE_and_acquire) \ + || !defined(AO_HAVE_and_acquire_read) || !defined(AO_HAVE_and_full) \ + || !defined(AO_HAVE_and_read) || !defined(AO_HAVE_and_release) \ + || !defined(AO_HAVE_and_release_write) || !defined(AO_HAVE_and_write) + MISSING(AO_and); +# endif + x &= 57; +# endif +# if defined(AO_HAVE_fetch_compare_and_swap) + TA_assert(AO_fetch_compare_and_swap(&x, 14, 117) == 25); + TA_assert(x == 25); + TA_assert(AO_fetch_compare_and_swap(&x, 25, 117) == 25); +# else + MISSING(AO_fetch_compare_and_swap); + if (x == 25) x = 117; +# endif + TA_assert(x == 117); +# if defined(AO_HAVE_short_compare_and_swap) + TA_assert(!AO_short_compare_and_swap(&s, 14, 42)); + TA_assert(s == 13); + TA_assert(AO_short_compare_and_swap(&s, 13, 42)); + TA_assert(s == 42); +# else + MISSING(AO_short_compare_and_swap); + if (*(volatile short *)&s == 13) s = 42; +# endif +# if defined(AO_HAVE_short_or) + AO_short_or(&s, 66); + TA_assert(s == 106); +# else +# if !defined(AO_HAVE_short_or) || !defined(AO_HAVE_short_or_acquire) \ + || !defined(AO_HAVE_short_or_acquire_read) \ + || !defined(AO_HAVE_short_or_full) || !defined(AO_HAVE_short_or_read) \ + || !defined(AO_HAVE_short_or_release) \ + || !defined(AO_HAVE_short_or_release_write) \ + || !defined(AO_HAVE_short_or_write) + MISSING(AO_short_or); +# endif + s |= 66; +# endif +# if defined(AO_HAVE_short_xor) + AO_short_xor(&s, 181); + TA_assert(s == 223); +# else +# if !defined(AO_HAVE_short_xor) || !defined(AO_HAVE_short_xor_acquire) \ + || !defined(AO_HAVE_short_xor_acquire_read) \ + || !defined(AO_HAVE_short_xor_full) \ + || !defined(AO_HAVE_short_xor_read) \ + || !defined(AO_HAVE_short_xor_release) \ + || !defined(AO_HAVE_short_xor_release_write) \ + || !defined(AO_HAVE_short_xor_write) + MISSING(AO_short_xor); +# endif + s ^= 181; +# endif +# if defined(AO_HAVE_short_and) + AO_short_and(&s, 57); + TA_assert(s == 25); +# else +# if !defined(AO_HAVE_short_and) || !defined(AO_HAVE_short_and_acquire) \ + || !defined(AO_HAVE_short_and_acquire_read) \ + || !defined(AO_HAVE_short_and_full) \ + || !defined(AO_HAVE_short_and_read) \ + || !defined(AO_HAVE_short_and_release) \ + || !defined(AO_HAVE_short_and_release_write) \ + || !defined(AO_HAVE_short_and_write) + MISSING(AO_short_and); +# endif + s &= 57; +# endif +# if defined(AO_HAVE_short_fetch_compare_and_swap) + TA_assert(AO_short_fetch_compare_and_swap(&s, 14, 117) == 25); + TA_assert(s == 25); + TA_assert(AO_short_fetch_compare_and_swap(&s, 25, 117) == 25); +# else + MISSING(AO_short_fetch_compare_and_swap); + if (s == 25) s = 117; +# endif + TA_assert(s == 117); +# if defined(AO_HAVE_char_compare_and_swap) + TA_assert(!AO_char_compare_and_swap(&b, 14, 42)); + TA_assert(b == 13); + TA_assert(AO_char_compare_and_swap(&b, 13, 42)); + TA_assert(b == 42); +# else + MISSING(AO_char_compare_and_swap); + if (*(volatile char *)&b == 13) b = 42; +# endif +# if defined(AO_HAVE_char_or) + AO_char_or(&b, 66); + TA_assert(b == 106); +# else +# if !defined(AO_HAVE_char_or) || !defined(AO_HAVE_char_or_acquire) \ + || !defined(AO_HAVE_char_or_acquire_read) \ + || !defined(AO_HAVE_char_or_full) || !defined(AO_HAVE_char_or_read) \ + || !defined(AO_HAVE_char_or_release) \ + || !defined(AO_HAVE_char_or_release_write) \ + || !defined(AO_HAVE_char_or_write) + MISSING(AO_char_or); +# endif + b |= 66; +# endif +# if defined(AO_HAVE_char_xor) + AO_char_xor(&b, 181); + TA_assert(b == 223); +# else +# if !defined(AO_HAVE_char_xor) || !defined(AO_HAVE_char_xor_acquire) \ + || !defined(AO_HAVE_char_xor_acquire_read) \ + || !defined(AO_HAVE_char_xor_full) || !defined(AO_HAVE_char_xor_read) \ + || !defined(AO_HAVE_char_xor_release) \ + || !defined(AO_HAVE_char_xor_release_write) \ + || !defined(AO_HAVE_char_xor_write) + MISSING(AO_char_xor); +# endif + b ^= 181; +# endif +# if defined(AO_HAVE_char_and) + AO_char_and(&b, 57); + TA_assert(b == 25); +# else +# if !defined(AO_HAVE_char_and) || !defined(AO_HAVE_char_and_acquire) \ + || !defined(AO_HAVE_char_and_acquire_read) \ + || !defined(AO_HAVE_char_and_full) || !defined(AO_HAVE_char_and_read) \ + || !defined(AO_HAVE_char_and_release) \ + || !defined(AO_HAVE_char_and_release_write) \ + || !defined(AO_HAVE_char_and_write) + MISSING(AO_char_and); +# endif + b &= 57; +# endif +# if defined(AO_HAVE_char_fetch_compare_and_swap) + TA_assert(AO_char_fetch_compare_and_swap(&b, 14, 117) == 25); + TA_assert(b == 25); + TA_assert(AO_char_fetch_compare_and_swap(&b, 25, 117) == 25); +# else + MISSING(AO_char_fetch_compare_and_swap); + if (b == 25) b = 117; +# endif + TA_assert(b == 117); +# if defined(AO_HAVE_int_compare_and_swap) + TA_assert(!AO_int_compare_and_swap(&zz, 14, 42)); + TA_assert(zz == 13); + TA_assert(AO_int_compare_and_swap(&zz, 13, 42)); + TA_assert(zz == 42); +# else + MISSING(AO_int_compare_and_swap); + if (*(volatile int *)&zz == 13) zz = 42; +# endif +# if defined(AO_HAVE_int_or) + AO_int_or(&zz, 66); + TA_assert(zz == 106); +# else +# if !defined(AO_HAVE_int_or) || !defined(AO_HAVE_int_or_acquire) \ + || !defined(AO_HAVE_int_or_acquire_read) \ + || !defined(AO_HAVE_int_or_full) || !defined(AO_HAVE_int_or_read) \ + || !defined(AO_HAVE_int_or_release) \ + || !defined(AO_HAVE_int_or_release_write) \ + || !defined(AO_HAVE_int_or_write) + MISSING(AO_int_or); +# endif + zz |= 66; +# endif +# if defined(AO_HAVE_int_xor) + AO_int_xor(&zz, 181); + TA_assert(zz == 223); +# else +# if !defined(AO_HAVE_int_xor) || !defined(AO_HAVE_int_xor_acquire) \ + || !defined(AO_HAVE_int_xor_acquire_read) \ + || !defined(AO_HAVE_int_xor_full) || !defined(AO_HAVE_int_xor_read) \ + || !defined(AO_HAVE_int_xor_release) \ + || !defined(AO_HAVE_int_xor_release_write) \ + || !defined(AO_HAVE_int_xor_write) + MISSING(AO_int_xor); +# endif + zz ^= 181; +# endif +# if defined(AO_HAVE_int_and) + AO_int_and(&zz, 57); + TA_assert(zz == 25); +# else +# if !defined(AO_HAVE_int_and) || !defined(AO_HAVE_int_and_acquire) \ + || !defined(AO_HAVE_int_and_acquire_read) \ + || !defined(AO_HAVE_int_and_full) || !defined(AO_HAVE_int_and_read) \ + || !defined(AO_HAVE_int_and_release) \ + || !defined(AO_HAVE_int_and_release_write) \ + || !defined(AO_HAVE_int_and_write) + MISSING(AO_int_and); +# endif + zz &= 57; +# endif +# if defined(AO_HAVE_int_fetch_compare_and_swap) + TA_assert(AO_int_fetch_compare_and_swap(&zz, 14, 117) == 25); + TA_assert(zz == 25); + TA_assert(AO_int_fetch_compare_and_swap(&zz, 25, 117) == 25); +# else + MISSING(AO_int_fetch_compare_and_swap); + if (zz == 25) zz = 117; +# endif + TA_assert(zz == 117); +# if defined(AO_HAVE_double_load) || defined(AO_HAVE_double_store) + /* Initialize old_w even for store to workaround MSan warning. */ + old_w.AO_val1 = 3316; + old_w.AO_val2 = 2921; +# endif +# if defined(AO_HAVE_double_load) + new_w = AO_double_load(&old_w); + TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921); +# elif !defined(AO_HAVE_double_load) \ + || !defined(AO_HAVE_double_load_acquire) \ + || !defined(AO_HAVE_double_load_acquire_read) \ + || !defined(AO_HAVE_double_load_dd_acquire_read) \ + || !defined(AO_HAVE_double_load_full) \ + || !defined(AO_HAVE_double_load_read) + MISSING(AO_double_load); +# endif +# if defined(AO_HAVE_double_store) + new_w.AO_val1 = 1375; + new_w.AO_val2 = 8243; + AO_double_store(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + AO_double_store(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + new_w.AO_val1 ^= old_w.AO_val1; + new_w.AO_val2 ^= old_w.AO_val2; + AO_double_store(&old_w, new_w); + TA_assert(old_w.AO_val1 == 0 && old_w.AO_val2 == 0); +# elif !defined(AO_HAVE_double_store) \ + || !defined(AO_HAVE_double_store_full) \ + || !defined(AO_HAVE_double_store_release) \ + || !defined(AO_HAVE_double_store_release_write) \ + || !defined(AO_HAVE_double_store_write) + MISSING(AO_double_store); +# endif +# if defined(AO_HAVE_compare_double_and_swap_double) + TA_assert(!AO_compare_double_and_swap_double(&w, 17, 42, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_double_and_swap_double(&w, 0, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double(&w, 12, 14, 64, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double(&w, 11, 13, 85, 82)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double(&w, 13, 12, 17, 42)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_double_and_swap_double(&w, 12, 13, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_double_and_swap_double(&w, 17, 42, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_double_and_swap_double); +# endif +# if defined(AO_HAVE_compare_and_swap_double) + TA_assert(!AO_compare_and_swap_double(&w, 17, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_and_swap_double(&w, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double(&w, 13, 12, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double(&w, 1213, 48, 86)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_and_swap_double(&w, 12, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_and_swap_double(&w, 17, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_and_swap_double); +# endif +# if defined(AO_HAVE_double_compare_and_swap) + old_w.AO_val1 = 4116; + old_w.AO_val2 = 2121; + new_w.AO_val1 = 8537; + new_w.AO_val2 = 6410; + TA_assert(!AO_double_compare_and_swap(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_double_compare_and_swap(&w, w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = 29; + new_w.AO_val1 = 820; + new_w.AO_val2 = 5917; + TA_assert(!AO_double_compare_and_swap(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = 11; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 3552; + new_w.AO_val2 = 1746; + TA_assert(!AO_double_compare_and_swap(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 8537; + new_w.AO_val1 = 4116; + new_w.AO_val2 = 2121; + TA_assert(!AO_double_compare_and_swap(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 1; + TA_assert(AO_double_compare_and_swap(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 1 && w.AO_val2 == 2121); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = w.AO_val2; + new_w.AO_val1--; + new_w.AO_val2 = 0; + TA_assert(AO_double_compare_and_swap(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_double_compare_and_swap); +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* Some basic sanity tests. These do not test the barrier semantics. */ + +#undef TA_assert +#define TA_assert(e) \ + if (!(e)) { fprintf(stderr, "Assertion failed %s:%d (barrier: _release)\n", \ + __FILE__, __LINE__), exit(1); } + +#undef MISSING +#define MISSING(name) \ + printf("Missing: %s\n", #name "_release") + +#if defined(CPPCHECK) + void list_atomic_release(void); + void char_list_atomic_release(void); + void short_list_atomic_release(void); + void int_list_atomic_release(void); + void double_list_atomic_release(void); +#endif + +void test_atomic_release(void) +{ + AO_t x; + unsigned char b; + unsigned short s; + unsigned int zz; +# if defined(AO_HAVE_test_and_set_release) + AO_TS_t z = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_compare_and_swap_release) \ + || defined(AO_HAVE_double_load_release) \ + || defined(AO_HAVE_double_store_release) + static AO_double_t old_w; /* static to avoid misalignment */ + AO_double_t new_w; +# endif +# if defined(AO_HAVE_compare_and_swap_double_release) \ + || defined(AO_HAVE_compare_double_and_swap_double_release) \ + || defined(AO_HAVE_double_compare_and_swap_release) + static AO_double_t w; /* static to avoid misalignment */ + w.AO_val1 = 0; + w.AO_val2 = 0; +# endif + +# if defined(CPPCHECK) + list_atomic_release(); + char_list_atomic_release(); + short_list_atomic_release(); + int_list_atomic_release(); + double_list_atomic_release(); +# endif +# if defined(AO_HAVE_nop_release) + AO_nop_release(); +# elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \ + || !defined(AO_HAVE_nop_read) || !defined(AO_HAVE_nop_write) + MISSING(AO_nop); +# endif +# if defined(AO_HAVE_store_release) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile AO_t *)&x = 0; /* initialize to avoid false warning */ +# endif + AO_store_release(&x, 13); + TA_assert(x == 13); +# else +# if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \ + || !defined(AO_HAVE_store_release) \ + || !defined(AO_HAVE_store_release_write) \ + || !defined(AO_HAVE_store_write) + MISSING(AO_store); +# endif + x = 13; +# endif +# if defined(AO_HAVE_load_release) + TA_assert(AO_load_release(&x) == 13); +# elif !defined(AO_HAVE_load) || !defined(AO_HAVE_load_acquire) \ + || !defined(AO_HAVE_load_acquire_read) \ + || !defined(AO_HAVE_load_dd_acquire_read) \ + || !defined(AO_HAVE_load_full) || !defined(AO_HAVE_load_read) + MISSING(AO_load); +# endif +# if defined(AO_HAVE_test_and_set_release) + TA_assert(AO_test_and_set_release(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_set_release(&z) == AO_TS_SET); + TA_assert(AO_test_and_set_release(&z) == AO_TS_SET); + AO_CLEAR(&z); +# else + MISSING(AO_test_and_set); +# endif +# if defined(AO_HAVE_fetch_and_add_release) + TA_assert(AO_fetch_and_add_release(&x, 42) == 13); + TA_assert(AO_fetch_and_add_release(&x, (AO_t)(-42)) == 55); +# else + MISSING(AO_fetch_and_add); +# endif +# if defined(AO_HAVE_fetch_and_add1_release) + TA_assert(AO_fetch_and_add1_release(&x) == 13); +# else + MISSING(AO_fetch_and_add1); + ++x; +# endif +# if defined(AO_HAVE_fetch_and_sub1_release) + TA_assert(AO_fetch_and_sub1_release(&x) == 14); +# else + MISSING(AO_fetch_and_sub1); + --x; +# endif +# if defined(AO_HAVE_short_store_release) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile short *)&s = 0; +# endif + AO_short_store_release(&s, 13); +# else +# if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \ + || !defined(AO_HAVE_short_store_release) \ + || !defined(AO_HAVE_short_store_release_write) \ + || !defined(AO_HAVE_short_store_write) + MISSING(AO_short_store); +# endif + s = 13; +# endif +# if defined(AO_HAVE_short_load_release) + TA_assert(AO_short_load(&s) == 13); +# elif !defined(AO_HAVE_short_load) || !defined(AO_HAVE_short_load_acquire) \ + || !defined(AO_HAVE_short_load_acquire_read) \ + || !defined(AO_HAVE_short_load_dd_acquire_read) \ + || !defined(AO_HAVE_short_load_full) \ + || !defined(AO_HAVE_short_load_read) + MISSING(AO_short_load); +# endif +# if defined(AO_HAVE_short_fetch_and_add_release) + TA_assert(AO_short_fetch_and_add_release(&s, 42) == 13); + TA_assert(AO_short_fetch_and_add_release(&s, (unsigned short)-42) == 55); +# else + MISSING(AO_short_fetch_and_add); +# endif +# if defined(AO_HAVE_short_fetch_and_add1_release) + TA_assert(AO_short_fetch_and_add1_release(&s) == 13); +# else + MISSING(AO_short_fetch_and_add1); + ++s; +# endif +# if defined(AO_HAVE_short_fetch_and_sub1_release) + TA_assert(AO_short_fetch_and_sub1_release(&s) == 14); +# else + MISSING(AO_short_fetch_and_sub1); + --s; +# endif + TA_assert(*(volatile short *)&s == 13); +# if defined(AO_HAVE_char_store_release) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile char *)&b = 0; +# endif + AO_char_store_release(&b, 13); +# else +# if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \ + || !defined(AO_HAVE_char_store_release) \ + || !defined(AO_HAVE_char_store_release_write) \ + || !defined(AO_HAVE_char_store_write) + MISSING(AO_char_store); +# endif + b = 13; +# endif +# if defined(AO_HAVE_char_load_release) + TA_assert(AO_char_load(&b) == 13); +# elif !defined(AO_HAVE_char_load) || !defined(AO_HAVE_char_load_acquire) \ + || !defined(AO_HAVE_char_load_acquire_read) \ + || !defined(AO_HAVE_char_load_dd_acquire_read) \ + || !defined(AO_HAVE_char_load_full) || !defined(AO_HAVE_char_load_read) + MISSING(AO_char_load); +# endif +# if defined(AO_HAVE_char_fetch_and_add_release) + TA_assert(AO_char_fetch_and_add_release(&b, 42) == 13); + TA_assert(AO_char_fetch_and_add_release(&b, (unsigned char)-42) == 55); +# else + MISSING(AO_char_fetch_and_add); +# endif +# if defined(AO_HAVE_char_fetch_and_add1_release) + TA_assert(AO_char_fetch_and_add1_release(&b) == 13); +# else + MISSING(AO_char_fetch_and_add1); + ++b; +# endif +# if defined(AO_HAVE_char_fetch_and_sub1_release) + TA_assert(AO_char_fetch_and_sub1_release(&b) == 14); +# else + MISSING(AO_char_fetch_and_sub1); + --b; +# endif + TA_assert(*(volatile char *)&b == 13); +# if defined(AO_HAVE_int_store_release) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile int *)&zz = 0; +# endif + AO_int_store_release(&zz, 13); +# else +# if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \ + || !defined(AO_HAVE_int_store_release) \ + || !defined(AO_HAVE_int_store_release_write) \ + || !defined(AO_HAVE_int_store_write) + MISSING(AO_int_store); +# endif + zz = 13; +# endif +# if defined(AO_HAVE_int_load_release) + TA_assert(AO_int_load(&zz) == 13); +# elif !defined(AO_HAVE_int_load) || !defined(AO_HAVE_int_load_acquire) \ + || !defined(AO_HAVE_int_load_acquire_read) \ + || !defined(AO_HAVE_int_load_dd_acquire_read) \ + || !defined(AO_HAVE_int_load_full) || !defined(AO_HAVE_int_load_read) + MISSING(AO_int_load); +# endif +# if defined(AO_HAVE_int_fetch_and_add_release) + TA_assert(AO_int_fetch_and_add_release(&zz, 42) == 13); + TA_assert(AO_int_fetch_and_add_release(&zz, (unsigned int)-42) == 55); +# else + MISSING(AO_int_fetch_and_add); +# endif +# if defined(AO_HAVE_int_fetch_and_add1_release) + TA_assert(AO_int_fetch_and_add1_release(&zz) == 13); +# else + MISSING(AO_int_fetch_and_add1); + ++zz; +# endif +# if defined(AO_HAVE_int_fetch_and_sub1_release) + TA_assert(AO_int_fetch_and_sub1_release(&zz) == 14); +# else + MISSING(AO_int_fetch_and_sub1); + --zz; +# endif + TA_assert(*(volatile int *)&zz == 13); +# if defined(AO_HAVE_compare_and_swap_release) + TA_assert(!AO_compare_and_swap_release(&x, 14, 42)); + TA_assert(x == 13); + TA_assert(AO_compare_and_swap_release(&x, 13, 42)); + TA_assert(x == 42); +# else + MISSING(AO_compare_and_swap); + if (*(volatile AO_t *)&x == 13) x = 42; +# endif +# if defined(AO_HAVE_or_release) + AO_or_release(&x, 66); + TA_assert(x == 106); +# else +# if !defined(AO_HAVE_or) || !defined(AO_HAVE_or_acquire) \ + || !defined(AO_HAVE_or_acquire_read) || !defined(AO_HAVE_or_full) \ + || !defined(AO_HAVE_or_read) || !defined(AO_HAVE_or_release) \ + || !defined(AO_HAVE_or_release_write) || !defined(AO_HAVE_or_write) + MISSING(AO_or); +# endif + x |= 66; +# endif +# if defined(AO_HAVE_xor_release) + AO_xor_release(&x, 181); + TA_assert(x == 223); +# else +# if !defined(AO_HAVE_xor) || !defined(AO_HAVE_xor_acquire) \ + || !defined(AO_HAVE_xor_acquire_read) || !defined(AO_HAVE_xor_full) \ + || !defined(AO_HAVE_xor_read) || !defined(AO_HAVE_xor_release) \ + || !defined(AO_HAVE_xor_release_write) || !defined(AO_HAVE_xor_write) + MISSING(AO_xor); +# endif + x ^= 181; +# endif +# if defined(AO_HAVE_and_release) + AO_and_release(&x, 57); + TA_assert(x == 25); +# else +# if !defined(AO_HAVE_and) || !defined(AO_HAVE_and_acquire) \ + || !defined(AO_HAVE_and_acquire_read) || !defined(AO_HAVE_and_full) \ + || !defined(AO_HAVE_and_read) || !defined(AO_HAVE_and_release) \ + || !defined(AO_HAVE_and_release_write) || !defined(AO_HAVE_and_write) + MISSING(AO_and); +# endif + x &= 57; +# endif +# if defined(AO_HAVE_fetch_compare_and_swap_release) + TA_assert(AO_fetch_compare_and_swap_release(&x, 14, 117) == 25); + TA_assert(x == 25); + TA_assert(AO_fetch_compare_and_swap_release(&x, 25, 117) == 25); +# else + MISSING(AO_fetch_compare_and_swap); + if (x == 25) x = 117; +# endif + TA_assert(x == 117); +# if defined(AO_HAVE_short_compare_and_swap_release) + TA_assert(!AO_short_compare_and_swap_release(&s, 14, 42)); + TA_assert(s == 13); + TA_assert(AO_short_compare_and_swap_release(&s, 13, 42)); + TA_assert(s == 42); +# else + MISSING(AO_short_compare_and_swap); + if (*(volatile short *)&s == 13) s = 42; +# endif +# if defined(AO_HAVE_short_or_release) + AO_short_or_release(&s, 66); + TA_assert(s == 106); +# else +# if !defined(AO_HAVE_short_or) || !defined(AO_HAVE_short_or_acquire) \ + || !defined(AO_HAVE_short_or_acquire_read) \ + || !defined(AO_HAVE_short_or_full) || !defined(AO_HAVE_short_or_read) \ + || !defined(AO_HAVE_short_or_release) \ + || !defined(AO_HAVE_short_or_release_write) \ + || !defined(AO_HAVE_short_or_write) + MISSING(AO_short_or); +# endif + s |= 66; +# endif +# if defined(AO_HAVE_short_xor_release) + AO_short_xor_release(&s, 181); + TA_assert(s == 223); +# else +# if !defined(AO_HAVE_short_xor) || !defined(AO_HAVE_short_xor_acquire) \ + || !defined(AO_HAVE_short_xor_acquire_read) \ + || !defined(AO_HAVE_short_xor_full) \ + || !defined(AO_HAVE_short_xor_read) \ + || !defined(AO_HAVE_short_xor_release) \ + || !defined(AO_HAVE_short_xor_release_write) \ + || !defined(AO_HAVE_short_xor_write) + MISSING(AO_short_xor); +# endif + s ^= 181; +# endif +# if defined(AO_HAVE_short_and_release) + AO_short_and_release(&s, 57); + TA_assert(s == 25); +# else +# if !defined(AO_HAVE_short_and) || !defined(AO_HAVE_short_and_acquire) \ + || !defined(AO_HAVE_short_and_acquire_read) \ + || !defined(AO_HAVE_short_and_full) \ + || !defined(AO_HAVE_short_and_read) \ + || !defined(AO_HAVE_short_and_release) \ + || !defined(AO_HAVE_short_and_release_write) \ + || !defined(AO_HAVE_short_and_write) + MISSING(AO_short_and); +# endif + s &= 57; +# endif +# if defined(AO_HAVE_short_fetch_compare_and_swap_release) + TA_assert(AO_short_fetch_compare_and_swap_release(&s, 14, 117) == 25); + TA_assert(s == 25); + TA_assert(AO_short_fetch_compare_and_swap_release(&s, 25, 117) == 25); +# else + MISSING(AO_short_fetch_compare_and_swap); + if (s == 25) s = 117; +# endif + TA_assert(s == 117); +# if defined(AO_HAVE_char_compare_and_swap_release) + TA_assert(!AO_char_compare_and_swap_release(&b, 14, 42)); + TA_assert(b == 13); + TA_assert(AO_char_compare_and_swap_release(&b, 13, 42)); + TA_assert(b == 42); +# else + MISSING(AO_char_compare_and_swap); + if (*(volatile char *)&b == 13) b = 42; +# endif +# if defined(AO_HAVE_char_or_release) + AO_char_or_release(&b, 66); + TA_assert(b == 106); +# else +# if !defined(AO_HAVE_char_or) || !defined(AO_HAVE_char_or_acquire) \ + || !defined(AO_HAVE_char_or_acquire_read) \ + || !defined(AO_HAVE_char_or_full) || !defined(AO_HAVE_char_or_read) \ + || !defined(AO_HAVE_char_or_release) \ + || !defined(AO_HAVE_char_or_release_write) \ + || !defined(AO_HAVE_char_or_write) + MISSING(AO_char_or); +# endif + b |= 66; +# endif +# if defined(AO_HAVE_char_xor_release) + AO_char_xor_release(&b, 181); + TA_assert(b == 223); +# else +# if !defined(AO_HAVE_char_xor) || !defined(AO_HAVE_char_xor_acquire) \ + || !defined(AO_HAVE_char_xor_acquire_read) \ + || !defined(AO_HAVE_char_xor_full) || !defined(AO_HAVE_char_xor_read) \ + || !defined(AO_HAVE_char_xor_release) \ + || !defined(AO_HAVE_char_xor_release_write) \ + || !defined(AO_HAVE_char_xor_write) + MISSING(AO_char_xor); +# endif + b ^= 181; +# endif +# if defined(AO_HAVE_char_and_release) + AO_char_and_release(&b, 57); + TA_assert(b == 25); +# else +# if !defined(AO_HAVE_char_and) || !defined(AO_HAVE_char_and_acquire) \ + || !defined(AO_HAVE_char_and_acquire_read) \ + || !defined(AO_HAVE_char_and_full) || !defined(AO_HAVE_char_and_read) \ + || !defined(AO_HAVE_char_and_release) \ + || !defined(AO_HAVE_char_and_release_write) \ + || !defined(AO_HAVE_char_and_write) + MISSING(AO_char_and); +# endif + b &= 57; +# endif +# if defined(AO_HAVE_char_fetch_compare_and_swap_release) + TA_assert(AO_char_fetch_compare_and_swap_release(&b, 14, 117) == 25); + TA_assert(b == 25); + TA_assert(AO_char_fetch_compare_and_swap_release(&b, 25, 117) == 25); +# else + MISSING(AO_char_fetch_compare_and_swap); + if (b == 25) b = 117; +# endif + TA_assert(b == 117); +# if defined(AO_HAVE_int_compare_and_swap_release) + TA_assert(!AO_int_compare_and_swap_release(&zz, 14, 42)); + TA_assert(zz == 13); + TA_assert(AO_int_compare_and_swap_release(&zz, 13, 42)); + TA_assert(zz == 42); +# else + MISSING(AO_int_compare_and_swap); + if (*(volatile int *)&zz == 13) zz = 42; +# endif +# if defined(AO_HAVE_int_or_release) + AO_int_or_release(&zz, 66); + TA_assert(zz == 106); +# else +# if !defined(AO_HAVE_int_or) || !defined(AO_HAVE_int_or_acquire) \ + || !defined(AO_HAVE_int_or_acquire_read) \ + || !defined(AO_HAVE_int_or_full) || !defined(AO_HAVE_int_or_read) \ + || !defined(AO_HAVE_int_or_release) \ + || !defined(AO_HAVE_int_or_release_write) \ + || !defined(AO_HAVE_int_or_write) + MISSING(AO_int_or); +# endif + zz |= 66; +# endif +# if defined(AO_HAVE_int_xor_release) + AO_int_xor_release(&zz, 181); + TA_assert(zz == 223); +# else +# if !defined(AO_HAVE_int_xor) || !defined(AO_HAVE_int_xor_acquire) \ + || !defined(AO_HAVE_int_xor_acquire_read) \ + || !defined(AO_HAVE_int_xor_full) || !defined(AO_HAVE_int_xor_read) \ + || !defined(AO_HAVE_int_xor_release) \ + || !defined(AO_HAVE_int_xor_release_write) \ + || !defined(AO_HAVE_int_xor_write) + MISSING(AO_int_xor); +# endif + zz ^= 181; +# endif +# if defined(AO_HAVE_int_and_release) + AO_int_and_release(&zz, 57); + TA_assert(zz == 25); +# else +# if !defined(AO_HAVE_int_and) || !defined(AO_HAVE_int_and_acquire) \ + || !defined(AO_HAVE_int_and_acquire_read) \ + || !defined(AO_HAVE_int_and_full) || !defined(AO_HAVE_int_and_read) \ + || !defined(AO_HAVE_int_and_release) \ + || !defined(AO_HAVE_int_and_release_write) \ + || !defined(AO_HAVE_int_and_write) + MISSING(AO_int_and); +# endif + zz &= 57; +# endif +# if defined(AO_HAVE_int_fetch_compare_and_swap_release) + TA_assert(AO_int_fetch_compare_and_swap_release(&zz, 14, 117) == 25); + TA_assert(zz == 25); + TA_assert(AO_int_fetch_compare_and_swap_release(&zz, 25, 117) == 25); +# else + MISSING(AO_int_fetch_compare_and_swap); + if (zz == 25) zz = 117; +# endif + TA_assert(zz == 117); +# if defined(AO_HAVE_double_load_release) || defined(AO_HAVE_double_store_release) + /* Initialize old_w even for store to workaround MSan warning. */ + old_w.AO_val1 = 3316; + old_w.AO_val2 = 2921; +# endif +# if defined(AO_HAVE_double_load_release) + new_w = AO_double_load_release(&old_w); + TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921); +# elif !defined(AO_HAVE_double_load) \ + || !defined(AO_HAVE_double_load_acquire) \ + || !defined(AO_HAVE_double_load_acquire_read) \ + || !defined(AO_HAVE_double_load_dd_acquire_read) \ + || !defined(AO_HAVE_double_load_full) \ + || !defined(AO_HAVE_double_load_read) + MISSING(AO_double_load); +# endif +# if defined(AO_HAVE_double_store_release) + new_w.AO_val1 = 1375; + new_w.AO_val2 = 8243; + AO_double_store_release(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + AO_double_store_release(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + new_w.AO_val1 ^= old_w.AO_val1; + new_w.AO_val2 ^= old_w.AO_val2; + AO_double_store_release(&old_w, new_w); + TA_assert(old_w.AO_val1 == 0 && old_w.AO_val2 == 0); +# elif !defined(AO_HAVE_double_store) \ + || !defined(AO_HAVE_double_store_full) \ + || !defined(AO_HAVE_double_store_release) \ + || !defined(AO_HAVE_double_store_release_write) \ + || !defined(AO_HAVE_double_store_write) + MISSING(AO_double_store); +# endif +# if defined(AO_HAVE_compare_double_and_swap_double_release) + TA_assert(!AO_compare_double_and_swap_double_release(&w, 17, 42, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_double_and_swap_double_release(&w, 0, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_release(&w, 12, 14, 64, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_release(&w, 11, 13, 85, 82)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_release(&w, 13, 12, 17, 42)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_double_and_swap_double_release(&w, 12, 13, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_double_and_swap_double_release(&w, 17, 42, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_double_and_swap_double); +# endif +# if defined(AO_HAVE_compare_and_swap_double_release) + TA_assert(!AO_compare_and_swap_double_release(&w, 17, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_and_swap_double_release(&w, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_release(&w, 13, 12, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_release(&w, 1213, 48, 86)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_and_swap_double_release(&w, 12, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_and_swap_double_release(&w, 17, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_and_swap_double); +# endif +# if defined(AO_HAVE_double_compare_and_swap_release) + old_w.AO_val1 = 4116; + old_w.AO_val2 = 2121; + new_w.AO_val1 = 8537; + new_w.AO_val2 = 6410; + TA_assert(!AO_double_compare_and_swap_release(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_double_compare_and_swap_release(&w, w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = 29; + new_w.AO_val1 = 820; + new_w.AO_val2 = 5917; + TA_assert(!AO_double_compare_and_swap_release(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = 11; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 3552; + new_w.AO_val2 = 1746; + TA_assert(!AO_double_compare_and_swap_release(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 8537; + new_w.AO_val1 = 4116; + new_w.AO_val2 = 2121; + TA_assert(!AO_double_compare_and_swap_release(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 1; + TA_assert(AO_double_compare_and_swap_release(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 1 && w.AO_val2 == 2121); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = w.AO_val2; + new_w.AO_val1--; + new_w.AO_val2 = 0; + TA_assert(AO_double_compare_and_swap_release(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_double_compare_and_swap); +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* Some basic sanity tests. These do not test the barrier semantics. */ + +#undef TA_assert +#define TA_assert(e) \ + if (!(e)) { fprintf(stderr, "Assertion failed %s:%d (barrier: _acquire)\n", \ + __FILE__, __LINE__), exit(1); } + +#undef MISSING +#define MISSING(name) \ + printf("Missing: %s\n", #name "_acquire") + +#if defined(CPPCHECK) + void list_atomic_acquire(void); + void char_list_atomic_acquire(void); + void short_list_atomic_acquire(void); + void int_list_atomic_acquire(void); + void double_list_atomic_acquire(void); +#endif + +void test_atomic_acquire(void) +{ + AO_t x; + unsigned char b; + unsigned short s; + unsigned int zz; +# if defined(AO_HAVE_test_and_set_acquire) + AO_TS_t z = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_compare_and_swap_acquire) \ + || defined(AO_HAVE_double_load_acquire) \ + || defined(AO_HAVE_double_store_acquire) + static AO_double_t old_w; /* static to avoid misalignment */ + AO_double_t new_w; +# endif +# if defined(AO_HAVE_compare_and_swap_double_acquire) \ + || defined(AO_HAVE_compare_double_and_swap_double_acquire) \ + || defined(AO_HAVE_double_compare_and_swap_acquire) + static AO_double_t w; /* static to avoid misalignment */ + w.AO_val1 = 0; + w.AO_val2 = 0; +# endif + +# if defined(CPPCHECK) + list_atomic_acquire(); + char_list_atomic_acquire(); + short_list_atomic_acquire(); + int_list_atomic_acquire(); + double_list_atomic_acquire(); +# endif +# if defined(AO_HAVE_nop_acquire) + AO_nop_acquire(); +# elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \ + || !defined(AO_HAVE_nop_read) || !defined(AO_HAVE_nop_write) + MISSING(AO_nop); +# endif +# if defined(AO_HAVE_store_acquire) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile AO_t *)&x = 0; /* initialize to avoid false warning */ +# endif + AO_store_acquire(&x, 13); + TA_assert(x == 13); +# else +# if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \ + || !defined(AO_HAVE_store_release) \ + || !defined(AO_HAVE_store_release_write) \ + || !defined(AO_HAVE_store_write) + MISSING(AO_store); +# endif + x = 13; +# endif +# if defined(AO_HAVE_load_acquire) + TA_assert(AO_load_acquire(&x) == 13); +# elif !defined(AO_HAVE_load) || !defined(AO_HAVE_load_acquire) \ + || !defined(AO_HAVE_load_acquire_read) \ + || !defined(AO_HAVE_load_dd_acquire_read) \ + || !defined(AO_HAVE_load_full) || !defined(AO_HAVE_load_read) + MISSING(AO_load); +# endif +# if defined(AO_HAVE_test_and_set_acquire) + TA_assert(AO_test_and_set_acquire(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_set_acquire(&z) == AO_TS_SET); + TA_assert(AO_test_and_set_acquire(&z) == AO_TS_SET); + AO_CLEAR(&z); +# else + MISSING(AO_test_and_set); +# endif +# if defined(AO_HAVE_fetch_and_add_acquire) + TA_assert(AO_fetch_and_add_acquire(&x, 42) == 13); + TA_assert(AO_fetch_and_add_acquire(&x, (AO_t)(-42)) == 55); +# else + MISSING(AO_fetch_and_add); +# endif +# if defined(AO_HAVE_fetch_and_add1_acquire) + TA_assert(AO_fetch_and_add1_acquire(&x) == 13); +# else + MISSING(AO_fetch_and_add1); + ++x; +# endif +# if defined(AO_HAVE_fetch_and_sub1_acquire) + TA_assert(AO_fetch_and_sub1_acquire(&x) == 14); +# else + MISSING(AO_fetch_and_sub1); + --x; +# endif +# if defined(AO_HAVE_short_store_acquire) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile short *)&s = 0; +# endif + AO_short_store_acquire(&s, 13); +# else +# if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \ + || !defined(AO_HAVE_short_store_release) \ + || !defined(AO_HAVE_short_store_release_write) \ + || !defined(AO_HAVE_short_store_write) + MISSING(AO_short_store); +# endif + s = 13; +# endif +# if defined(AO_HAVE_short_load_acquire) + TA_assert(AO_short_load(&s) == 13); +# elif !defined(AO_HAVE_short_load) || !defined(AO_HAVE_short_load_acquire) \ + || !defined(AO_HAVE_short_load_acquire_read) \ + || !defined(AO_HAVE_short_load_dd_acquire_read) \ + || !defined(AO_HAVE_short_load_full) \ + || !defined(AO_HAVE_short_load_read) + MISSING(AO_short_load); +# endif +# if defined(AO_HAVE_short_fetch_and_add_acquire) + TA_assert(AO_short_fetch_and_add_acquire(&s, 42) == 13); + TA_assert(AO_short_fetch_and_add_acquire(&s, (unsigned short)-42) == 55); +# else + MISSING(AO_short_fetch_and_add); +# endif +# if defined(AO_HAVE_short_fetch_and_add1_acquire) + TA_assert(AO_short_fetch_and_add1_acquire(&s) == 13); +# else + MISSING(AO_short_fetch_and_add1); + ++s; +# endif +# if defined(AO_HAVE_short_fetch_and_sub1_acquire) + TA_assert(AO_short_fetch_and_sub1_acquire(&s) == 14); +# else + MISSING(AO_short_fetch_and_sub1); + --s; +# endif + TA_assert(*(volatile short *)&s == 13); +# if defined(AO_HAVE_char_store_acquire) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile char *)&b = 0; +# endif + AO_char_store_acquire(&b, 13); +# else +# if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \ + || !defined(AO_HAVE_char_store_release) \ + || !defined(AO_HAVE_char_store_release_write) \ + || !defined(AO_HAVE_char_store_write) + MISSING(AO_char_store); +# endif + b = 13; +# endif +# if defined(AO_HAVE_char_load_acquire) + TA_assert(AO_char_load(&b) == 13); +# elif !defined(AO_HAVE_char_load) || !defined(AO_HAVE_char_load_acquire) \ + || !defined(AO_HAVE_char_load_acquire_read) \ + || !defined(AO_HAVE_char_load_dd_acquire_read) \ + || !defined(AO_HAVE_char_load_full) || !defined(AO_HAVE_char_load_read) + MISSING(AO_char_load); +# endif +# if defined(AO_HAVE_char_fetch_and_add_acquire) + TA_assert(AO_char_fetch_and_add_acquire(&b, 42) == 13); + TA_assert(AO_char_fetch_and_add_acquire(&b, (unsigned char)-42) == 55); +# else + MISSING(AO_char_fetch_and_add); +# endif +# if defined(AO_HAVE_char_fetch_and_add1_acquire) + TA_assert(AO_char_fetch_and_add1_acquire(&b) == 13); +# else + MISSING(AO_char_fetch_and_add1); + ++b; +# endif +# if defined(AO_HAVE_char_fetch_and_sub1_acquire) + TA_assert(AO_char_fetch_and_sub1_acquire(&b) == 14); +# else + MISSING(AO_char_fetch_and_sub1); + --b; +# endif + TA_assert(*(volatile char *)&b == 13); +# if defined(AO_HAVE_int_store_acquire) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile int *)&zz = 0; +# endif + AO_int_store_acquire(&zz, 13); +# else +# if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \ + || !defined(AO_HAVE_int_store_release) \ + || !defined(AO_HAVE_int_store_release_write) \ + || !defined(AO_HAVE_int_store_write) + MISSING(AO_int_store); +# endif + zz = 13; +# endif +# if defined(AO_HAVE_int_load_acquire) + TA_assert(AO_int_load(&zz) == 13); +# elif !defined(AO_HAVE_int_load) || !defined(AO_HAVE_int_load_acquire) \ + || !defined(AO_HAVE_int_load_acquire_read) \ + || !defined(AO_HAVE_int_load_dd_acquire_read) \ + || !defined(AO_HAVE_int_load_full) || !defined(AO_HAVE_int_load_read) + MISSING(AO_int_load); +# endif +# if defined(AO_HAVE_int_fetch_and_add_acquire) + TA_assert(AO_int_fetch_and_add_acquire(&zz, 42) == 13); + TA_assert(AO_int_fetch_and_add_acquire(&zz, (unsigned int)-42) == 55); +# else + MISSING(AO_int_fetch_and_add); +# endif +# if defined(AO_HAVE_int_fetch_and_add1_acquire) + TA_assert(AO_int_fetch_and_add1_acquire(&zz) == 13); +# else + MISSING(AO_int_fetch_and_add1); + ++zz; +# endif +# if defined(AO_HAVE_int_fetch_and_sub1_acquire) + TA_assert(AO_int_fetch_and_sub1_acquire(&zz) == 14); +# else + MISSING(AO_int_fetch_and_sub1); + --zz; +# endif + TA_assert(*(volatile int *)&zz == 13); +# if defined(AO_HAVE_compare_and_swap_acquire) + TA_assert(!AO_compare_and_swap_acquire(&x, 14, 42)); + TA_assert(x == 13); + TA_assert(AO_compare_and_swap_acquire(&x, 13, 42)); + TA_assert(x == 42); +# else + MISSING(AO_compare_and_swap); + if (*(volatile AO_t *)&x == 13) x = 42; +# endif +# if defined(AO_HAVE_or_acquire) + AO_or_acquire(&x, 66); + TA_assert(x == 106); +# else +# if !defined(AO_HAVE_or) || !defined(AO_HAVE_or_acquire) \ + || !defined(AO_HAVE_or_acquire_read) || !defined(AO_HAVE_or_full) \ + || !defined(AO_HAVE_or_read) || !defined(AO_HAVE_or_release) \ + || !defined(AO_HAVE_or_release_write) || !defined(AO_HAVE_or_write) + MISSING(AO_or); +# endif + x |= 66; +# endif +# if defined(AO_HAVE_xor_acquire) + AO_xor_acquire(&x, 181); + TA_assert(x == 223); +# else +# if !defined(AO_HAVE_xor) || !defined(AO_HAVE_xor_acquire) \ + || !defined(AO_HAVE_xor_acquire_read) || !defined(AO_HAVE_xor_full) \ + || !defined(AO_HAVE_xor_read) || !defined(AO_HAVE_xor_release) \ + || !defined(AO_HAVE_xor_release_write) || !defined(AO_HAVE_xor_write) + MISSING(AO_xor); +# endif + x ^= 181; +# endif +# if defined(AO_HAVE_and_acquire) + AO_and_acquire(&x, 57); + TA_assert(x == 25); +# else +# if !defined(AO_HAVE_and) || !defined(AO_HAVE_and_acquire) \ + || !defined(AO_HAVE_and_acquire_read) || !defined(AO_HAVE_and_full) \ + || !defined(AO_HAVE_and_read) || !defined(AO_HAVE_and_release) \ + || !defined(AO_HAVE_and_release_write) || !defined(AO_HAVE_and_write) + MISSING(AO_and); +# endif + x &= 57; +# endif +# if defined(AO_HAVE_fetch_compare_and_swap_acquire) + TA_assert(AO_fetch_compare_and_swap_acquire(&x, 14, 117) == 25); + TA_assert(x == 25); + TA_assert(AO_fetch_compare_and_swap_acquire(&x, 25, 117) == 25); +# else + MISSING(AO_fetch_compare_and_swap); + if (x == 25) x = 117; +# endif + TA_assert(x == 117); +# if defined(AO_HAVE_short_compare_and_swap_acquire) + TA_assert(!AO_short_compare_and_swap_acquire(&s, 14, 42)); + TA_assert(s == 13); + TA_assert(AO_short_compare_and_swap_acquire(&s, 13, 42)); + TA_assert(s == 42); +# else + MISSING(AO_short_compare_and_swap); + if (*(volatile short *)&s == 13) s = 42; +# endif +# if defined(AO_HAVE_short_or_acquire) + AO_short_or_acquire(&s, 66); + TA_assert(s == 106); +# else +# if !defined(AO_HAVE_short_or) || !defined(AO_HAVE_short_or_acquire) \ + || !defined(AO_HAVE_short_or_acquire_read) \ + || !defined(AO_HAVE_short_or_full) || !defined(AO_HAVE_short_or_read) \ + || !defined(AO_HAVE_short_or_release) \ + || !defined(AO_HAVE_short_or_release_write) \ + || !defined(AO_HAVE_short_or_write) + MISSING(AO_short_or); +# endif + s |= 66; +# endif +# if defined(AO_HAVE_short_xor_acquire) + AO_short_xor_acquire(&s, 181); + TA_assert(s == 223); +# else +# if !defined(AO_HAVE_short_xor) || !defined(AO_HAVE_short_xor_acquire) \ + || !defined(AO_HAVE_short_xor_acquire_read) \ + || !defined(AO_HAVE_short_xor_full) \ + || !defined(AO_HAVE_short_xor_read) \ + || !defined(AO_HAVE_short_xor_release) \ + || !defined(AO_HAVE_short_xor_release_write) \ + || !defined(AO_HAVE_short_xor_write) + MISSING(AO_short_xor); +# endif + s ^= 181; +# endif +# if defined(AO_HAVE_short_and_acquire) + AO_short_and_acquire(&s, 57); + TA_assert(s == 25); +# else +# if !defined(AO_HAVE_short_and) || !defined(AO_HAVE_short_and_acquire) \ + || !defined(AO_HAVE_short_and_acquire_read) \ + || !defined(AO_HAVE_short_and_full) \ + || !defined(AO_HAVE_short_and_read) \ + || !defined(AO_HAVE_short_and_release) \ + || !defined(AO_HAVE_short_and_release_write) \ + || !defined(AO_HAVE_short_and_write) + MISSING(AO_short_and); +# endif + s &= 57; +# endif +# if defined(AO_HAVE_short_fetch_compare_and_swap_acquire) + TA_assert(AO_short_fetch_compare_and_swap_acquire(&s, 14, 117) == 25); + TA_assert(s == 25); + TA_assert(AO_short_fetch_compare_and_swap_acquire(&s, 25, 117) == 25); +# else + MISSING(AO_short_fetch_compare_and_swap); + if (s == 25) s = 117; +# endif + TA_assert(s == 117); +# if defined(AO_HAVE_char_compare_and_swap_acquire) + TA_assert(!AO_char_compare_and_swap_acquire(&b, 14, 42)); + TA_assert(b == 13); + TA_assert(AO_char_compare_and_swap_acquire(&b, 13, 42)); + TA_assert(b == 42); +# else + MISSING(AO_char_compare_and_swap); + if (*(volatile char *)&b == 13) b = 42; +# endif +# if defined(AO_HAVE_char_or_acquire) + AO_char_or_acquire(&b, 66); + TA_assert(b == 106); +# else +# if !defined(AO_HAVE_char_or) || !defined(AO_HAVE_char_or_acquire) \ + || !defined(AO_HAVE_char_or_acquire_read) \ + || !defined(AO_HAVE_char_or_full) || !defined(AO_HAVE_char_or_read) \ + || !defined(AO_HAVE_char_or_release) \ + || !defined(AO_HAVE_char_or_release_write) \ + || !defined(AO_HAVE_char_or_write) + MISSING(AO_char_or); +# endif + b |= 66; +# endif +# if defined(AO_HAVE_char_xor_acquire) + AO_char_xor_acquire(&b, 181); + TA_assert(b == 223); +# else +# if !defined(AO_HAVE_char_xor) || !defined(AO_HAVE_char_xor_acquire) \ + || !defined(AO_HAVE_char_xor_acquire_read) \ + || !defined(AO_HAVE_char_xor_full) || !defined(AO_HAVE_char_xor_read) \ + || !defined(AO_HAVE_char_xor_release) \ + || !defined(AO_HAVE_char_xor_release_write) \ + || !defined(AO_HAVE_char_xor_write) + MISSING(AO_char_xor); +# endif + b ^= 181; +# endif +# if defined(AO_HAVE_char_and_acquire) + AO_char_and_acquire(&b, 57); + TA_assert(b == 25); +# else +# if !defined(AO_HAVE_char_and) || !defined(AO_HAVE_char_and_acquire) \ + || !defined(AO_HAVE_char_and_acquire_read) \ + || !defined(AO_HAVE_char_and_full) || !defined(AO_HAVE_char_and_read) \ + || !defined(AO_HAVE_char_and_release) \ + || !defined(AO_HAVE_char_and_release_write) \ + || !defined(AO_HAVE_char_and_write) + MISSING(AO_char_and); +# endif + b &= 57; +# endif +# if defined(AO_HAVE_char_fetch_compare_and_swap_acquire) + TA_assert(AO_char_fetch_compare_and_swap_acquire(&b, 14, 117) == 25); + TA_assert(b == 25); + TA_assert(AO_char_fetch_compare_and_swap_acquire(&b, 25, 117) == 25); +# else + MISSING(AO_char_fetch_compare_and_swap); + if (b == 25) b = 117; +# endif + TA_assert(b == 117); +# if defined(AO_HAVE_int_compare_and_swap_acquire) + TA_assert(!AO_int_compare_and_swap_acquire(&zz, 14, 42)); + TA_assert(zz == 13); + TA_assert(AO_int_compare_and_swap_acquire(&zz, 13, 42)); + TA_assert(zz == 42); +# else + MISSING(AO_int_compare_and_swap); + if (*(volatile int *)&zz == 13) zz = 42; +# endif +# if defined(AO_HAVE_int_or_acquire) + AO_int_or_acquire(&zz, 66); + TA_assert(zz == 106); +# else +# if !defined(AO_HAVE_int_or) || !defined(AO_HAVE_int_or_acquire) \ + || !defined(AO_HAVE_int_or_acquire_read) \ + || !defined(AO_HAVE_int_or_full) || !defined(AO_HAVE_int_or_read) \ + || !defined(AO_HAVE_int_or_release) \ + || !defined(AO_HAVE_int_or_release_write) \ + || !defined(AO_HAVE_int_or_write) + MISSING(AO_int_or); +# endif + zz |= 66; +# endif +# if defined(AO_HAVE_int_xor_acquire) + AO_int_xor_acquire(&zz, 181); + TA_assert(zz == 223); +# else +# if !defined(AO_HAVE_int_xor) || !defined(AO_HAVE_int_xor_acquire) \ + || !defined(AO_HAVE_int_xor_acquire_read) \ + || !defined(AO_HAVE_int_xor_full) || !defined(AO_HAVE_int_xor_read) \ + || !defined(AO_HAVE_int_xor_release) \ + || !defined(AO_HAVE_int_xor_release_write) \ + || !defined(AO_HAVE_int_xor_write) + MISSING(AO_int_xor); +# endif + zz ^= 181; +# endif +# if defined(AO_HAVE_int_and_acquire) + AO_int_and_acquire(&zz, 57); + TA_assert(zz == 25); +# else +# if !defined(AO_HAVE_int_and) || !defined(AO_HAVE_int_and_acquire) \ + || !defined(AO_HAVE_int_and_acquire_read) \ + || !defined(AO_HAVE_int_and_full) || !defined(AO_HAVE_int_and_read) \ + || !defined(AO_HAVE_int_and_release) \ + || !defined(AO_HAVE_int_and_release_write) \ + || !defined(AO_HAVE_int_and_write) + MISSING(AO_int_and); +# endif + zz &= 57; +# endif +# if defined(AO_HAVE_int_fetch_compare_and_swap_acquire) + TA_assert(AO_int_fetch_compare_and_swap_acquire(&zz, 14, 117) == 25); + TA_assert(zz == 25); + TA_assert(AO_int_fetch_compare_and_swap_acquire(&zz, 25, 117) == 25); +# else + MISSING(AO_int_fetch_compare_and_swap); + if (zz == 25) zz = 117; +# endif + TA_assert(zz == 117); +# if defined(AO_HAVE_double_load_acquire) || defined(AO_HAVE_double_store_acquire) + /* Initialize old_w even for store to workaround MSan warning. */ + old_w.AO_val1 = 3316; + old_w.AO_val2 = 2921; +# endif +# if defined(AO_HAVE_double_load_acquire) + new_w = AO_double_load_acquire(&old_w); + TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921); +# elif !defined(AO_HAVE_double_load) \ + || !defined(AO_HAVE_double_load_acquire) \ + || !defined(AO_HAVE_double_load_acquire_read) \ + || !defined(AO_HAVE_double_load_dd_acquire_read) \ + || !defined(AO_HAVE_double_load_full) \ + || !defined(AO_HAVE_double_load_read) + MISSING(AO_double_load); +# endif +# if defined(AO_HAVE_double_store_acquire) + new_w.AO_val1 = 1375; + new_w.AO_val2 = 8243; + AO_double_store_acquire(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + AO_double_store_acquire(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + new_w.AO_val1 ^= old_w.AO_val1; + new_w.AO_val2 ^= old_w.AO_val2; + AO_double_store_acquire(&old_w, new_w); + TA_assert(old_w.AO_val1 == 0 && old_w.AO_val2 == 0); +# elif !defined(AO_HAVE_double_store) \ + || !defined(AO_HAVE_double_store_full) \ + || !defined(AO_HAVE_double_store_release) \ + || !defined(AO_HAVE_double_store_release_write) \ + || !defined(AO_HAVE_double_store_write) + MISSING(AO_double_store); +# endif +# if defined(AO_HAVE_compare_double_and_swap_double_acquire) + TA_assert(!AO_compare_double_and_swap_double_acquire(&w, 17, 42, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_double_and_swap_double_acquire(&w, 0, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_acquire(&w, 12, 14, 64, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_acquire(&w, 11, 13, 85, 82)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_acquire(&w, 13, 12, 17, 42)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_double_and_swap_double_acquire(&w, 12, 13, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_double_and_swap_double_acquire(&w, 17, 42, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_double_and_swap_double); +# endif +# if defined(AO_HAVE_compare_and_swap_double_acquire) + TA_assert(!AO_compare_and_swap_double_acquire(&w, 17, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_and_swap_double_acquire(&w, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_acquire(&w, 13, 12, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_acquire(&w, 1213, 48, 86)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_and_swap_double_acquire(&w, 12, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_and_swap_double_acquire(&w, 17, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_and_swap_double); +# endif +# if defined(AO_HAVE_double_compare_and_swap_acquire) + old_w.AO_val1 = 4116; + old_w.AO_val2 = 2121; + new_w.AO_val1 = 8537; + new_w.AO_val2 = 6410; + TA_assert(!AO_double_compare_and_swap_acquire(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_double_compare_and_swap_acquire(&w, w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = 29; + new_w.AO_val1 = 820; + new_w.AO_val2 = 5917; + TA_assert(!AO_double_compare_and_swap_acquire(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = 11; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 3552; + new_w.AO_val2 = 1746; + TA_assert(!AO_double_compare_and_swap_acquire(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 8537; + new_w.AO_val1 = 4116; + new_w.AO_val2 = 2121; + TA_assert(!AO_double_compare_and_swap_acquire(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 1; + TA_assert(AO_double_compare_and_swap_acquire(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 1 && w.AO_val2 == 2121); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = w.AO_val2; + new_w.AO_val1--; + new_w.AO_val2 = 0; + TA_assert(AO_double_compare_and_swap_acquire(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_double_compare_and_swap); +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* Some basic sanity tests. These do not test the barrier semantics. */ + +#undef TA_assert +#define TA_assert(e) \ + if (!(e)) { fprintf(stderr, "Assertion failed %s:%d (barrier: _read)\n", \ + __FILE__, __LINE__), exit(1); } + +#undef MISSING +#define MISSING(name) \ + printf("Missing: %s\n", #name "_read") + +#if defined(CPPCHECK) + void list_atomic_read(void); + void char_list_atomic_read(void); + void short_list_atomic_read(void); + void int_list_atomic_read(void); + void double_list_atomic_read(void); +#endif + +void test_atomic_read(void) +{ + AO_t x; + unsigned char b; + unsigned short s; + unsigned int zz; +# if defined(AO_HAVE_test_and_set_read) + AO_TS_t z = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_compare_and_swap_read) \ + || defined(AO_HAVE_double_load_read) \ + || defined(AO_HAVE_double_store_read) + static AO_double_t old_w; /* static to avoid misalignment */ + AO_double_t new_w; +# endif +# if defined(AO_HAVE_compare_and_swap_double_read) \ + || defined(AO_HAVE_compare_double_and_swap_double_read) \ + || defined(AO_HAVE_double_compare_and_swap_read) + static AO_double_t w; /* static to avoid misalignment */ + w.AO_val1 = 0; + w.AO_val2 = 0; +# endif + +# if defined(CPPCHECK) + list_atomic_read(); + char_list_atomic_read(); + short_list_atomic_read(); + int_list_atomic_read(); + double_list_atomic_read(); +# endif +# if defined(AO_HAVE_nop_read) + AO_nop_read(); +# elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \ + || !defined(AO_HAVE_nop_read) || !defined(AO_HAVE_nop_write) + MISSING(AO_nop); +# endif +# if defined(AO_HAVE_store_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile AO_t *)&x = 0; /* initialize to avoid false warning */ +# endif + AO_store_read(&x, 13); + TA_assert(x == 13); +# else +# if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \ + || !defined(AO_HAVE_store_release) \ + || !defined(AO_HAVE_store_release_write) \ + || !defined(AO_HAVE_store_write) + MISSING(AO_store); +# endif + x = 13; +# endif +# if defined(AO_HAVE_load_read) + TA_assert(AO_load_read(&x) == 13); +# elif !defined(AO_HAVE_load) || !defined(AO_HAVE_load_acquire) \ + || !defined(AO_HAVE_load_acquire_read) \ + || !defined(AO_HAVE_load_dd_acquire_read) \ + || !defined(AO_HAVE_load_full) || !defined(AO_HAVE_load_read) + MISSING(AO_load); +# endif +# if defined(AO_HAVE_test_and_set_read) + TA_assert(AO_test_and_set_read(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_set_read(&z) == AO_TS_SET); + TA_assert(AO_test_and_set_read(&z) == AO_TS_SET); + AO_CLEAR(&z); +# else + MISSING(AO_test_and_set); +# endif +# if defined(AO_HAVE_fetch_and_add_read) + TA_assert(AO_fetch_and_add_read(&x, 42) == 13); + TA_assert(AO_fetch_and_add_read(&x, (AO_t)(-42)) == 55); +# else + MISSING(AO_fetch_and_add); +# endif +# if defined(AO_HAVE_fetch_and_add1_read) + TA_assert(AO_fetch_and_add1_read(&x) == 13); +# else + MISSING(AO_fetch_and_add1); + ++x; +# endif +# if defined(AO_HAVE_fetch_and_sub1_read) + TA_assert(AO_fetch_and_sub1_read(&x) == 14); +# else + MISSING(AO_fetch_and_sub1); + --x; +# endif +# if defined(AO_HAVE_short_store_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile short *)&s = 0; +# endif + AO_short_store_read(&s, 13); +# else +# if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \ + || !defined(AO_HAVE_short_store_release) \ + || !defined(AO_HAVE_short_store_release_write) \ + || !defined(AO_HAVE_short_store_write) + MISSING(AO_short_store); +# endif + s = 13; +# endif +# if defined(AO_HAVE_short_load_read) + TA_assert(AO_short_load(&s) == 13); +# elif !defined(AO_HAVE_short_load) || !defined(AO_HAVE_short_load_acquire) \ + || !defined(AO_HAVE_short_load_acquire_read) \ + || !defined(AO_HAVE_short_load_dd_acquire_read) \ + || !defined(AO_HAVE_short_load_full) \ + || !defined(AO_HAVE_short_load_read) + MISSING(AO_short_load); +# endif +# if defined(AO_HAVE_short_fetch_and_add_read) + TA_assert(AO_short_fetch_and_add_read(&s, 42) == 13); + TA_assert(AO_short_fetch_and_add_read(&s, (unsigned short)-42) == 55); +# else + MISSING(AO_short_fetch_and_add); +# endif +# if defined(AO_HAVE_short_fetch_and_add1_read) + TA_assert(AO_short_fetch_and_add1_read(&s) == 13); +# else + MISSING(AO_short_fetch_and_add1); + ++s; +# endif +# if defined(AO_HAVE_short_fetch_and_sub1_read) + TA_assert(AO_short_fetch_and_sub1_read(&s) == 14); +# else + MISSING(AO_short_fetch_and_sub1); + --s; +# endif + TA_assert(*(volatile short *)&s == 13); +# if defined(AO_HAVE_char_store_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile char *)&b = 0; +# endif + AO_char_store_read(&b, 13); +# else +# if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \ + || !defined(AO_HAVE_char_store_release) \ + || !defined(AO_HAVE_char_store_release_write) \ + || !defined(AO_HAVE_char_store_write) + MISSING(AO_char_store); +# endif + b = 13; +# endif +# if defined(AO_HAVE_char_load_read) + TA_assert(AO_char_load(&b) == 13); +# elif !defined(AO_HAVE_char_load) || !defined(AO_HAVE_char_load_acquire) \ + || !defined(AO_HAVE_char_load_acquire_read) \ + || !defined(AO_HAVE_char_load_dd_acquire_read) \ + || !defined(AO_HAVE_char_load_full) || !defined(AO_HAVE_char_load_read) + MISSING(AO_char_load); +# endif +# if defined(AO_HAVE_char_fetch_and_add_read) + TA_assert(AO_char_fetch_and_add_read(&b, 42) == 13); + TA_assert(AO_char_fetch_and_add_read(&b, (unsigned char)-42) == 55); +# else + MISSING(AO_char_fetch_and_add); +# endif +# if defined(AO_HAVE_char_fetch_and_add1_read) + TA_assert(AO_char_fetch_and_add1_read(&b) == 13); +# else + MISSING(AO_char_fetch_and_add1); + ++b; +# endif +# if defined(AO_HAVE_char_fetch_and_sub1_read) + TA_assert(AO_char_fetch_and_sub1_read(&b) == 14); +# else + MISSING(AO_char_fetch_and_sub1); + --b; +# endif + TA_assert(*(volatile char *)&b == 13); +# if defined(AO_HAVE_int_store_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile int *)&zz = 0; +# endif + AO_int_store_read(&zz, 13); +# else +# if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \ + || !defined(AO_HAVE_int_store_release) \ + || !defined(AO_HAVE_int_store_release_write) \ + || !defined(AO_HAVE_int_store_write) + MISSING(AO_int_store); +# endif + zz = 13; +# endif +# if defined(AO_HAVE_int_load_read) + TA_assert(AO_int_load(&zz) == 13); +# elif !defined(AO_HAVE_int_load) || !defined(AO_HAVE_int_load_acquire) \ + || !defined(AO_HAVE_int_load_acquire_read) \ + || !defined(AO_HAVE_int_load_dd_acquire_read) \ + || !defined(AO_HAVE_int_load_full) || !defined(AO_HAVE_int_load_read) + MISSING(AO_int_load); +# endif +# if defined(AO_HAVE_int_fetch_and_add_read) + TA_assert(AO_int_fetch_and_add_read(&zz, 42) == 13); + TA_assert(AO_int_fetch_and_add_read(&zz, (unsigned int)-42) == 55); +# else + MISSING(AO_int_fetch_and_add); +# endif +# if defined(AO_HAVE_int_fetch_and_add1_read) + TA_assert(AO_int_fetch_and_add1_read(&zz) == 13); +# else + MISSING(AO_int_fetch_and_add1); + ++zz; +# endif +# if defined(AO_HAVE_int_fetch_and_sub1_read) + TA_assert(AO_int_fetch_and_sub1_read(&zz) == 14); +# else + MISSING(AO_int_fetch_and_sub1); + --zz; +# endif + TA_assert(*(volatile int *)&zz == 13); +# if defined(AO_HAVE_compare_and_swap_read) + TA_assert(!AO_compare_and_swap_read(&x, 14, 42)); + TA_assert(x == 13); + TA_assert(AO_compare_and_swap_read(&x, 13, 42)); + TA_assert(x == 42); +# else + MISSING(AO_compare_and_swap); + if (*(volatile AO_t *)&x == 13) x = 42; +# endif +# if defined(AO_HAVE_or_read) + AO_or_read(&x, 66); + TA_assert(x == 106); +# else +# if !defined(AO_HAVE_or) || !defined(AO_HAVE_or_acquire) \ + || !defined(AO_HAVE_or_acquire_read) || !defined(AO_HAVE_or_full) \ + || !defined(AO_HAVE_or_read) || !defined(AO_HAVE_or_release) \ + || !defined(AO_HAVE_or_release_write) || !defined(AO_HAVE_or_write) + MISSING(AO_or); +# endif + x |= 66; +# endif +# if defined(AO_HAVE_xor_read) + AO_xor_read(&x, 181); + TA_assert(x == 223); +# else +# if !defined(AO_HAVE_xor) || !defined(AO_HAVE_xor_acquire) \ + || !defined(AO_HAVE_xor_acquire_read) || !defined(AO_HAVE_xor_full) \ + || !defined(AO_HAVE_xor_read) || !defined(AO_HAVE_xor_release) \ + || !defined(AO_HAVE_xor_release_write) || !defined(AO_HAVE_xor_write) + MISSING(AO_xor); +# endif + x ^= 181; +# endif +# if defined(AO_HAVE_and_read) + AO_and_read(&x, 57); + TA_assert(x == 25); +# else +# if !defined(AO_HAVE_and) || !defined(AO_HAVE_and_acquire) \ + || !defined(AO_HAVE_and_acquire_read) || !defined(AO_HAVE_and_full) \ + || !defined(AO_HAVE_and_read) || !defined(AO_HAVE_and_release) \ + || !defined(AO_HAVE_and_release_write) || !defined(AO_HAVE_and_write) + MISSING(AO_and); +# endif + x &= 57; +# endif +# if defined(AO_HAVE_fetch_compare_and_swap_read) + TA_assert(AO_fetch_compare_and_swap_read(&x, 14, 117) == 25); + TA_assert(x == 25); + TA_assert(AO_fetch_compare_and_swap_read(&x, 25, 117) == 25); +# else + MISSING(AO_fetch_compare_and_swap); + if (x == 25) x = 117; +# endif + TA_assert(x == 117); +# if defined(AO_HAVE_short_compare_and_swap_read) + TA_assert(!AO_short_compare_and_swap_read(&s, 14, 42)); + TA_assert(s == 13); + TA_assert(AO_short_compare_and_swap_read(&s, 13, 42)); + TA_assert(s == 42); +# else + MISSING(AO_short_compare_and_swap); + if (*(volatile short *)&s == 13) s = 42; +# endif +# if defined(AO_HAVE_short_or_read) + AO_short_or_read(&s, 66); + TA_assert(s == 106); +# else +# if !defined(AO_HAVE_short_or) || !defined(AO_HAVE_short_or_acquire) \ + || !defined(AO_HAVE_short_or_acquire_read) \ + || !defined(AO_HAVE_short_or_full) || !defined(AO_HAVE_short_or_read) \ + || !defined(AO_HAVE_short_or_release) \ + || !defined(AO_HAVE_short_or_release_write) \ + || !defined(AO_HAVE_short_or_write) + MISSING(AO_short_or); +# endif + s |= 66; +# endif +# if defined(AO_HAVE_short_xor_read) + AO_short_xor_read(&s, 181); + TA_assert(s == 223); +# else +# if !defined(AO_HAVE_short_xor) || !defined(AO_HAVE_short_xor_acquire) \ + || !defined(AO_HAVE_short_xor_acquire_read) \ + || !defined(AO_HAVE_short_xor_full) \ + || !defined(AO_HAVE_short_xor_read) \ + || !defined(AO_HAVE_short_xor_release) \ + || !defined(AO_HAVE_short_xor_release_write) \ + || !defined(AO_HAVE_short_xor_write) + MISSING(AO_short_xor); +# endif + s ^= 181; +# endif +# if defined(AO_HAVE_short_and_read) + AO_short_and_read(&s, 57); + TA_assert(s == 25); +# else +# if !defined(AO_HAVE_short_and) || !defined(AO_HAVE_short_and_acquire) \ + || !defined(AO_HAVE_short_and_acquire_read) \ + || !defined(AO_HAVE_short_and_full) \ + || !defined(AO_HAVE_short_and_read) \ + || !defined(AO_HAVE_short_and_release) \ + || !defined(AO_HAVE_short_and_release_write) \ + || !defined(AO_HAVE_short_and_write) + MISSING(AO_short_and); +# endif + s &= 57; +# endif +# if defined(AO_HAVE_short_fetch_compare_and_swap_read) + TA_assert(AO_short_fetch_compare_and_swap_read(&s, 14, 117) == 25); + TA_assert(s == 25); + TA_assert(AO_short_fetch_compare_and_swap_read(&s, 25, 117) == 25); +# else + MISSING(AO_short_fetch_compare_and_swap); + if (s == 25) s = 117; +# endif + TA_assert(s == 117); +# if defined(AO_HAVE_char_compare_and_swap_read) + TA_assert(!AO_char_compare_and_swap_read(&b, 14, 42)); + TA_assert(b == 13); + TA_assert(AO_char_compare_and_swap_read(&b, 13, 42)); + TA_assert(b == 42); +# else + MISSING(AO_char_compare_and_swap); + if (*(volatile char *)&b == 13) b = 42; +# endif +# if defined(AO_HAVE_char_or_read) + AO_char_or_read(&b, 66); + TA_assert(b == 106); +# else +# if !defined(AO_HAVE_char_or) || !defined(AO_HAVE_char_or_acquire) \ + || !defined(AO_HAVE_char_or_acquire_read) \ + || !defined(AO_HAVE_char_or_full) || !defined(AO_HAVE_char_or_read) \ + || !defined(AO_HAVE_char_or_release) \ + || !defined(AO_HAVE_char_or_release_write) \ + || !defined(AO_HAVE_char_or_write) + MISSING(AO_char_or); +# endif + b |= 66; +# endif +# if defined(AO_HAVE_char_xor_read) + AO_char_xor_read(&b, 181); + TA_assert(b == 223); +# else +# if !defined(AO_HAVE_char_xor) || !defined(AO_HAVE_char_xor_acquire) \ + || !defined(AO_HAVE_char_xor_acquire_read) \ + || !defined(AO_HAVE_char_xor_full) || !defined(AO_HAVE_char_xor_read) \ + || !defined(AO_HAVE_char_xor_release) \ + || !defined(AO_HAVE_char_xor_release_write) \ + || !defined(AO_HAVE_char_xor_write) + MISSING(AO_char_xor); +# endif + b ^= 181; +# endif +# if defined(AO_HAVE_char_and_read) + AO_char_and_read(&b, 57); + TA_assert(b == 25); +# else +# if !defined(AO_HAVE_char_and) || !defined(AO_HAVE_char_and_acquire) \ + || !defined(AO_HAVE_char_and_acquire_read) \ + || !defined(AO_HAVE_char_and_full) || !defined(AO_HAVE_char_and_read) \ + || !defined(AO_HAVE_char_and_release) \ + || !defined(AO_HAVE_char_and_release_write) \ + || !defined(AO_HAVE_char_and_write) + MISSING(AO_char_and); +# endif + b &= 57; +# endif +# if defined(AO_HAVE_char_fetch_compare_and_swap_read) + TA_assert(AO_char_fetch_compare_and_swap_read(&b, 14, 117) == 25); + TA_assert(b == 25); + TA_assert(AO_char_fetch_compare_and_swap_read(&b, 25, 117) == 25); +# else + MISSING(AO_char_fetch_compare_and_swap); + if (b == 25) b = 117; +# endif + TA_assert(b == 117); +# if defined(AO_HAVE_int_compare_and_swap_read) + TA_assert(!AO_int_compare_and_swap_read(&zz, 14, 42)); + TA_assert(zz == 13); + TA_assert(AO_int_compare_and_swap_read(&zz, 13, 42)); + TA_assert(zz == 42); +# else + MISSING(AO_int_compare_and_swap); + if (*(volatile int *)&zz == 13) zz = 42; +# endif +# if defined(AO_HAVE_int_or_read) + AO_int_or_read(&zz, 66); + TA_assert(zz == 106); +# else +# if !defined(AO_HAVE_int_or) || !defined(AO_HAVE_int_or_acquire) \ + || !defined(AO_HAVE_int_or_acquire_read) \ + || !defined(AO_HAVE_int_or_full) || !defined(AO_HAVE_int_or_read) \ + || !defined(AO_HAVE_int_or_release) \ + || !defined(AO_HAVE_int_or_release_write) \ + || !defined(AO_HAVE_int_or_write) + MISSING(AO_int_or); +# endif + zz |= 66; +# endif +# if defined(AO_HAVE_int_xor_read) + AO_int_xor_read(&zz, 181); + TA_assert(zz == 223); +# else +# if !defined(AO_HAVE_int_xor) || !defined(AO_HAVE_int_xor_acquire) \ + || !defined(AO_HAVE_int_xor_acquire_read) \ + || !defined(AO_HAVE_int_xor_full) || !defined(AO_HAVE_int_xor_read) \ + || !defined(AO_HAVE_int_xor_release) \ + || !defined(AO_HAVE_int_xor_release_write) \ + || !defined(AO_HAVE_int_xor_write) + MISSING(AO_int_xor); +# endif + zz ^= 181; +# endif +# if defined(AO_HAVE_int_and_read) + AO_int_and_read(&zz, 57); + TA_assert(zz == 25); +# else +# if !defined(AO_HAVE_int_and) || !defined(AO_HAVE_int_and_acquire) \ + || !defined(AO_HAVE_int_and_acquire_read) \ + || !defined(AO_HAVE_int_and_full) || !defined(AO_HAVE_int_and_read) \ + || !defined(AO_HAVE_int_and_release) \ + || !defined(AO_HAVE_int_and_release_write) \ + || !defined(AO_HAVE_int_and_write) + MISSING(AO_int_and); +# endif + zz &= 57; +# endif +# if defined(AO_HAVE_int_fetch_compare_and_swap_read) + TA_assert(AO_int_fetch_compare_and_swap_read(&zz, 14, 117) == 25); + TA_assert(zz == 25); + TA_assert(AO_int_fetch_compare_and_swap_read(&zz, 25, 117) == 25); +# else + MISSING(AO_int_fetch_compare_and_swap); + if (zz == 25) zz = 117; +# endif + TA_assert(zz == 117); +# if defined(AO_HAVE_double_load_read) || defined(AO_HAVE_double_store_read) + /* Initialize old_w even for store to workaround MSan warning. */ + old_w.AO_val1 = 3316; + old_w.AO_val2 = 2921; +# endif +# if defined(AO_HAVE_double_load_read) + new_w = AO_double_load_read(&old_w); + TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921); +# elif !defined(AO_HAVE_double_load) \ + || !defined(AO_HAVE_double_load_acquire) \ + || !defined(AO_HAVE_double_load_acquire_read) \ + || !defined(AO_HAVE_double_load_dd_acquire_read) \ + || !defined(AO_HAVE_double_load_full) \ + || !defined(AO_HAVE_double_load_read) + MISSING(AO_double_load); +# endif +# if defined(AO_HAVE_double_store_read) + new_w.AO_val1 = 1375; + new_w.AO_val2 = 8243; + AO_double_store_read(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + AO_double_store_read(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + new_w.AO_val1 ^= old_w.AO_val1; + new_w.AO_val2 ^= old_w.AO_val2; + AO_double_store_read(&old_w, new_w); + TA_assert(old_w.AO_val1 == 0 && old_w.AO_val2 == 0); +# elif !defined(AO_HAVE_double_store) \ + || !defined(AO_HAVE_double_store_full) \ + || !defined(AO_HAVE_double_store_release) \ + || !defined(AO_HAVE_double_store_release_write) \ + || !defined(AO_HAVE_double_store_write) + MISSING(AO_double_store); +# endif +# if defined(AO_HAVE_compare_double_and_swap_double_read) + TA_assert(!AO_compare_double_and_swap_double_read(&w, 17, 42, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_double_and_swap_double_read(&w, 0, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_read(&w, 12, 14, 64, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_read(&w, 11, 13, 85, 82)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_read(&w, 13, 12, 17, 42)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_double_and_swap_double_read(&w, 12, 13, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_double_and_swap_double_read(&w, 17, 42, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_double_and_swap_double); +# endif +# if defined(AO_HAVE_compare_and_swap_double_read) + TA_assert(!AO_compare_and_swap_double_read(&w, 17, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_and_swap_double_read(&w, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_read(&w, 13, 12, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_read(&w, 1213, 48, 86)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_and_swap_double_read(&w, 12, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_and_swap_double_read(&w, 17, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_and_swap_double); +# endif +# if defined(AO_HAVE_double_compare_and_swap_read) + old_w.AO_val1 = 4116; + old_w.AO_val2 = 2121; + new_w.AO_val1 = 8537; + new_w.AO_val2 = 6410; + TA_assert(!AO_double_compare_and_swap_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_double_compare_and_swap_read(&w, w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = 29; + new_w.AO_val1 = 820; + new_w.AO_val2 = 5917; + TA_assert(!AO_double_compare_and_swap_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = 11; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 3552; + new_w.AO_val2 = 1746; + TA_assert(!AO_double_compare_and_swap_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 8537; + new_w.AO_val1 = 4116; + new_w.AO_val2 = 2121; + TA_assert(!AO_double_compare_and_swap_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 1; + TA_assert(AO_double_compare_and_swap_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 1 && w.AO_val2 == 2121); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = w.AO_val2; + new_w.AO_val1--; + new_w.AO_val2 = 0; + TA_assert(AO_double_compare_and_swap_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_double_compare_and_swap); +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* Some basic sanity tests. These do not test the barrier semantics. */ + +#undef TA_assert +#define TA_assert(e) \ + if (!(e)) { fprintf(stderr, "Assertion failed %s:%d (barrier: _write)\n", \ + __FILE__, __LINE__), exit(1); } + +#undef MISSING +#define MISSING(name) \ + printf("Missing: %s\n", #name "_write") + +#if defined(CPPCHECK) + void list_atomic_write(void); + void char_list_atomic_write(void); + void short_list_atomic_write(void); + void int_list_atomic_write(void); + void double_list_atomic_write(void); +#endif + +void test_atomic_write(void) +{ + AO_t x; + unsigned char b; + unsigned short s; + unsigned int zz; +# if defined(AO_HAVE_test_and_set_write) + AO_TS_t z = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_compare_and_swap_write) \ + || defined(AO_HAVE_double_load_write) \ + || defined(AO_HAVE_double_store_write) + static AO_double_t old_w; /* static to avoid misalignment */ + AO_double_t new_w; +# endif +# if defined(AO_HAVE_compare_and_swap_double_write) \ + || defined(AO_HAVE_compare_double_and_swap_double_write) \ + || defined(AO_HAVE_double_compare_and_swap_write) + static AO_double_t w; /* static to avoid misalignment */ + w.AO_val1 = 0; + w.AO_val2 = 0; +# endif + +# if defined(CPPCHECK) + list_atomic_write(); + char_list_atomic_write(); + short_list_atomic_write(); + int_list_atomic_write(); + double_list_atomic_write(); +# endif +# if defined(AO_HAVE_nop_write) + AO_nop_write(); +# elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \ + || !defined(AO_HAVE_nop_read) || !defined(AO_HAVE_nop_write) + MISSING(AO_nop); +# endif +# if defined(AO_HAVE_store_write) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile AO_t *)&x = 0; /* initialize to avoid false warning */ +# endif + AO_store_write(&x, 13); + TA_assert(x == 13); +# else +# if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \ + || !defined(AO_HAVE_store_release) \ + || !defined(AO_HAVE_store_release_write) \ + || !defined(AO_HAVE_store_write) + MISSING(AO_store); +# endif + x = 13; +# endif +# if defined(AO_HAVE_load_write) + TA_assert(AO_load_write(&x) == 13); +# elif !defined(AO_HAVE_load) || !defined(AO_HAVE_load_acquire) \ + || !defined(AO_HAVE_load_acquire_read) \ + || !defined(AO_HAVE_load_dd_acquire_read) \ + || !defined(AO_HAVE_load_full) || !defined(AO_HAVE_load_read) + MISSING(AO_load); +# endif +# if defined(AO_HAVE_test_and_set_write) + TA_assert(AO_test_and_set_write(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_set_write(&z) == AO_TS_SET); + TA_assert(AO_test_and_set_write(&z) == AO_TS_SET); + AO_CLEAR(&z); +# else + MISSING(AO_test_and_set); +# endif +# if defined(AO_HAVE_fetch_and_add_write) + TA_assert(AO_fetch_and_add_write(&x, 42) == 13); + TA_assert(AO_fetch_and_add_write(&x, (AO_t)(-42)) == 55); +# else + MISSING(AO_fetch_and_add); +# endif +# if defined(AO_HAVE_fetch_and_add1_write) + TA_assert(AO_fetch_and_add1_write(&x) == 13); +# else + MISSING(AO_fetch_and_add1); + ++x; +# endif +# if defined(AO_HAVE_fetch_and_sub1_write) + TA_assert(AO_fetch_and_sub1_write(&x) == 14); +# else + MISSING(AO_fetch_and_sub1); + --x; +# endif +# if defined(AO_HAVE_short_store_write) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile short *)&s = 0; +# endif + AO_short_store_write(&s, 13); +# else +# if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \ + || !defined(AO_HAVE_short_store_release) \ + || !defined(AO_HAVE_short_store_release_write) \ + || !defined(AO_HAVE_short_store_write) + MISSING(AO_short_store); +# endif + s = 13; +# endif +# if defined(AO_HAVE_short_load_write) + TA_assert(AO_short_load(&s) == 13); +# elif !defined(AO_HAVE_short_load) || !defined(AO_HAVE_short_load_acquire) \ + || !defined(AO_HAVE_short_load_acquire_read) \ + || !defined(AO_HAVE_short_load_dd_acquire_read) \ + || !defined(AO_HAVE_short_load_full) \ + || !defined(AO_HAVE_short_load_read) + MISSING(AO_short_load); +# endif +# if defined(AO_HAVE_short_fetch_and_add_write) + TA_assert(AO_short_fetch_and_add_write(&s, 42) == 13); + TA_assert(AO_short_fetch_and_add_write(&s, (unsigned short)-42) == 55); +# else + MISSING(AO_short_fetch_and_add); +# endif +# if defined(AO_HAVE_short_fetch_and_add1_write) + TA_assert(AO_short_fetch_and_add1_write(&s) == 13); +# else + MISSING(AO_short_fetch_and_add1); + ++s; +# endif +# if defined(AO_HAVE_short_fetch_and_sub1_write) + TA_assert(AO_short_fetch_and_sub1_write(&s) == 14); +# else + MISSING(AO_short_fetch_and_sub1); + --s; +# endif + TA_assert(*(volatile short *)&s == 13); +# if defined(AO_HAVE_char_store_write) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile char *)&b = 0; +# endif + AO_char_store_write(&b, 13); +# else +# if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \ + || !defined(AO_HAVE_char_store_release) \ + || !defined(AO_HAVE_char_store_release_write) \ + || !defined(AO_HAVE_char_store_write) + MISSING(AO_char_store); +# endif + b = 13; +# endif +# if defined(AO_HAVE_char_load_write) + TA_assert(AO_char_load(&b) == 13); +# elif !defined(AO_HAVE_char_load) || !defined(AO_HAVE_char_load_acquire) \ + || !defined(AO_HAVE_char_load_acquire_read) \ + || !defined(AO_HAVE_char_load_dd_acquire_read) \ + || !defined(AO_HAVE_char_load_full) || !defined(AO_HAVE_char_load_read) + MISSING(AO_char_load); +# endif +# if defined(AO_HAVE_char_fetch_and_add_write) + TA_assert(AO_char_fetch_and_add_write(&b, 42) == 13); + TA_assert(AO_char_fetch_and_add_write(&b, (unsigned char)-42) == 55); +# else + MISSING(AO_char_fetch_and_add); +# endif +# if defined(AO_HAVE_char_fetch_and_add1_write) + TA_assert(AO_char_fetch_and_add1_write(&b) == 13); +# else + MISSING(AO_char_fetch_and_add1); + ++b; +# endif +# if defined(AO_HAVE_char_fetch_and_sub1_write) + TA_assert(AO_char_fetch_and_sub1_write(&b) == 14); +# else + MISSING(AO_char_fetch_and_sub1); + --b; +# endif + TA_assert(*(volatile char *)&b == 13); +# if defined(AO_HAVE_int_store_write) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile int *)&zz = 0; +# endif + AO_int_store_write(&zz, 13); +# else +# if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \ + || !defined(AO_HAVE_int_store_release) \ + || !defined(AO_HAVE_int_store_release_write) \ + || !defined(AO_HAVE_int_store_write) + MISSING(AO_int_store); +# endif + zz = 13; +# endif +# if defined(AO_HAVE_int_load_write) + TA_assert(AO_int_load(&zz) == 13); +# elif !defined(AO_HAVE_int_load) || !defined(AO_HAVE_int_load_acquire) \ + || !defined(AO_HAVE_int_load_acquire_read) \ + || !defined(AO_HAVE_int_load_dd_acquire_read) \ + || !defined(AO_HAVE_int_load_full) || !defined(AO_HAVE_int_load_read) + MISSING(AO_int_load); +# endif +# if defined(AO_HAVE_int_fetch_and_add_write) + TA_assert(AO_int_fetch_and_add_write(&zz, 42) == 13); + TA_assert(AO_int_fetch_and_add_write(&zz, (unsigned int)-42) == 55); +# else + MISSING(AO_int_fetch_and_add); +# endif +# if defined(AO_HAVE_int_fetch_and_add1_write) + TA_assert(AO_int_fetch_and_add1_write(&zz) == 13); +# else + MISSING(AO_int_fetch_and_add1); + ++zz; +# endif +# if defined(AO_HAVE_int_fetch_and_sub1_write) + TA_assert(AO_int_fetch_and_sub1_write(&zz) == 14); +# else + MISSING(AO_int_fetch_and_sub1); + --zz; +# endif + TA_assert(*(volatile int *)&zz == 13); +# if defined(AO_HAVE_compare_and_swap_write) + TA_assert(!AO_compare_and_swap_write(&x, 14, 42)); + TA_assert(x == 13); + TA_assert(AO_compare_and_swap_write(&x, 13, 42)); + TA_assert(x == 42); +# else + MISSING(AO_compare_and_swap); + if (*(volatile AO_t *)&x == 13) x = 42; +# endif +# if defined(AO_HAVE_or_write) + AO_or_write(&x, 66); + TA_assert(x == 106); +# else +# if !defined(AO_HAVE_or) || !defined(AO_HAVE_or_acquire) \ + || !defined(AO_HAVE_or_acquire_read) || !defined(AO_HAVE_or_full) \ + || !defined(AO_HAVE_or_read) || !defined(AO_HAVE_or_release) \ + || !defined(AO_HAVE_or_release_write) || !defined(AO_HAVE_or_write) + MISSING(AO_or); +# endif + x |= 66; +# endif +# if defined(AO_HAVE_xor_write) + AO_xor_write(&x, 181); + TA_assert(x == 223); +# else +# if !defined(AO_HAVE_xor) || !defined(AO_HAVE_xor_acquire) \ + || !defined(AO_HAVE_xor_acquire_read) || !defined(AO_HAVE_xor_full) \ + || !defined(AO_HAVE_xor_read) || !defined(AO_HAVE_xor_release) \ + || !defined(AO_HAVE_xor_release_write) || !defined(AO_HAVE_xor_write) + MISSING(AO_xor); +# endif + x ^= 181; +# endif +# if defined(AO_HAVE_and_write) + AO_and_write(&x, 57); + TA_assert(x == 25); +# else +# if !defined(AO_HAVE_and) || !defined(AO_HAVE_and_acquire) \ + || !defined(AO_HAVE_and_acquire_read) || !defined(AO_HAVE_and_full) \ + || !defined(AO_HAVE_and_read) || !defined(AO_HAVE_and_release) \ + || !defined(AO_HAVE_and_release_write) || !defined(AO_HAVE_and_write) + MISSING(AO_and); +# endif + x &= 57; +# endif +# if defined(AO_HAVE_fetch_compare_and_swap_write) + TA_assert(AO_fetch_compare_and_swap_write(&x, 14, 117) == 25); + TA_assert(x == 25); + TA_assert(AO_fetch_compare_and_swap_write(&x, 25, 117) == 25); +# else + MISSING(AO_fetch_compare_and_swap); + if (x == 25) x = 117; +# endif + TA_assert(x == 117); +# if defined(AO_HAVE_short_compare_and_swap_write) + TA_assert(!AO_short_compare_and_swap_write(&s, 14, 42)); + TA_assert(s == 13); + TA_assert(AO_short_compare_and_swap_write(&s, 13, 42)); + TA_assert(s == 42); +# else + MISSING(AO_short_compare_and_swap); + if (*(volatile short *)&s == 13) s = 42; +# endif +# if defined(AO_HAVE_short_or_write) + AO_short_or_write(&s, 66); + TA_assert(s == 106); +# else +# if !defined(AO_HAVE_short_or) || !defined(AO_HAVE_short_or_acquire) \ + || !defined(AO_HAVE_short_or_acquire_read) \ + || !defined(AO_HAVE_short_or_full) || !defined(AO_HAVE_short_or_read) \ + || !defined(AO_HAVE_short_or_release) \ + || !defined(AO_HAVE_short_or_release_write) \ + || !defined(AO_HAVE_short_or_write) + MISSING(AO_short_or); +# endif + s |= 66; +# endif +# if defined(AO_HAVE_short_xor_write) + AO_short_xor_write(&s, 181); + TA_assert(s == 223); +# else +# if !defined(AO_HAVE_short_xor) || !defined(AO_HAVE_short_xor_acquire) \ + || !defined(AO_HAVE_short_xor_acquire_read) \ + || !defined(AO_HAVE_short_xor_full) \ + || !defined(AO_HAVE_short_xor_read) \ + || !defined(AO_HAVE_short_xor_release) \ + || !defined(AO_HAVE_short_xor_release_write) \ + || !defined(AO_HAVE_short_xor_write) + MISSING(AO_short_xor); +# endif + s ^= 181; +# endif +# if defined(AO_HAVE_short_and_write) + AO_short_and_write(&s, 57); + TA_assert(s == 25); +# else +# if !defined(AO_HAVE_short_and) || !defined(AO_HAVE_short_and_acquire) \ + || !defined(AO_HAVE_short_and_acquire_read) \ + || !defined(AO_HAVE_short_and_full) \ + || !defined(AO_HAVE_short_and_read) \ + || !defined(AO_HAVE_short_and_release) \ + || !defined(AO_HAVE_short_and_release_write) \ + || !defined(AO_HAVE_short_and_write) + MISSING(AO_short_and); +# endif + s &= 57; +# endif +# if defined(AO_HAVE_short_fetch_compare_and_swap_write) + TA_assert(AO_short_fetch_compare_and_swap_write(&s, 14, 117) == 25); + TA_assert(s == 25); + TA_assert(AO_short_fetch_compare_and_swap_write(&s, 25, 117) == 25); +# else + MISSING(AO_short_fetch_compare_and_swap); + if (s == 25) s = 117; +# endif + TA_assert(s == 117); +# if defined(AO_HAVE_char_compare_and_swap_write) + TA_assert(!AO_char_compare_and_swap_write(&b, 14, 42)); + TA_assert(b == 13); + TA_assert(AO_char_compare_and_swap_write(&b, 13, 42)); + TA_assert(b == 42); +# else + MISSING(AO_char_compare_and_swap); + if (*(volatile char *)&b == 13) b = 42; +# endif +# if defined(AO_HAVE_char_or_write) + AO_char_or_write(&b, 66); + TA_assert(b == 106); +# else +# if !defined(AO_HAVE_char_or) || !defined(AO_HAVE_char_or_acquire) \ + || !defined(AO_HAVE_char_or_acquire_read) \ + || !defined(AO_HAVE_char_or_full) || !defined(AO_HAVE_char_or_read) \ + || !defined(AO_HAVE_char_or_release) \ + || !defined(AO_HAVE_char_or_release_write) \ + || !defined(AO_HAVE_char_or_write) + MISSING(AO_char_or); +# endif + b |= 66; +# endif +# if defined(AO_HAVE_char_xor_write) + AO_char_xor_write(&b, 181); + TA_assert(b == 223); +# else +# if !defined(AO_HAVE_char_xor) || !defined(AO_HAVE_char_xor_acquire) \ + || !defined(AO_HAVE_char_xor_acquire_read) \ + || !defined(AO_HAVE_char_xor_full) || !defined(AO_HAVE_char_xor_read) \ + || !defined(AO_HAVE_char_xor_release) \ + || !defined(AO_HAVE_char_xor_release_write) \ + || !defined(AO_HAVE_char_xor_write) + MISSING(AO_char_xor); +# endif + b ^= 181; +# endif +# if defined(AO_HAVE_char_and_write) + AO_char_and_write(&b, 57); + TA_assert(b == 25); +# else +# if !defined(AO_HAVE_char_and) || !defined(AO_HAVE_char_and_acquire) \ + || !defined(AO_HAVE_char_and_acquire_read) \ + || !defined(AO_HAVE_char_and_full) || !defined(AO_HAVE_char_and_read) \ + || !defined(AO_HAVE_char_and_release) \ + || !defined(AO_HAVE_char_and_release_write) \ + || !defined(AO_HAVE_char_and_write) + MISSING(AO_char_and); +# endif + b &= 57; +# endif +# if defined(AO_HAVE_char_fetch_compare_and_swap_write) + TA_assert(AO_char_fetch_compare_and_swap_write(&b, 14, 117) == 25); + TA_assert(b == 25); + TA_assert(AO_char_fetch_compare_and_swap_write(&b, 25, 117) == 25); +# else + MISSING(AO_char_fetch_compare_and_swap); + if (b == 25) b = 117; +# endif + TA_assert(b == 117); +# if defined(AO_HAVE_int_compare_and_swap_write) + TA_assert(!AO_int_compare_and_swap_write(&zz, 14, 42)); + TA_assert(zz == 13); + TA_assert(AO_int_compare_and_swap_write(&zz, 13, 42)); + TA_assert(zz == 42); +# else + MISSING(AO_int_compare_and_swap); + if (*(volatile int *)&zz == 13) zz = 42; +# endif +# if defined(AO_HAVE_int_or_write) + AO_int_or_write(&zz, 66); + TA_assert(zz == 106); +# else +# if !defined(AO_HAVE_int_or) || !defined(AO_HAVE_int_or_acquire) \ + || !defined(AO_HAVE_int_or_acquire_read) \ + || !defined(AO_HAVE_int_or_full) || !defined(AO_HAVE_int_or_read) \ + || !defined(AO_HAVE_int_or_release) \ + || !defined(AO_HAVE_int_or_release_write) \ + || !defined(AO_HAVE_int_or_write) + MISSING(AO_int_or); +# endif + zz |= 66; +# endif +# if defined(AO_HAVE_int_xor_write) + AO_int_xor_write(&zz, 181); + TA_assert(zz == 223); +# else +# if !defined(AO_HAVE_int_xor) || !defined(AO_HAVE_int_xor_acquire) \ + || !defined(AO_HAVE_int_xor_acquire_read) \ + || !defined(AO_HAVE_int_xor_full) || !defined(AO_HAVE_int_xor_read) \ + || !defined(AO_HAVE_int_xor_release) \ + || !defined(AO_HAVE_int_xor_release_write) \ + || !defined(AO_HAVE_int_xor_write) + MISSING(AO_int_xor); +# endif + zz ^= 181; +# endif +# if defined(AO_HAVE_int_and_write) + AO_int_and_write(&zz, 57); + TA_assert(zz == 25); +# else +# if !defined(AO_HAVE_int_and) || !defined(AO_HAVE_int_and_acquire) \ + || !defined(AO_HAVE_int_and_acquire_read) \ + || !defined(AO_HAVE_int_and_full) || !defined(AO_HAVE_int_and_read) \ + || !defined(AO_HAVE_int_and_release) \ + || !defined(AO_HAVE_int_and_release_write) \ + || !defined(AO_HAVE_int_and_write) + MISSING(AO_int_and); +# endif + zz &= 57; +# endif +# if defined(AO_HAVE_int_fetch_compare_and_swap_write) + TA_assert(AO_int_fetch_compare_and_swap_write(&zz, 14, 117) == 25); + TA_assert(zz == 25); + TA_assert(AO_int_fetch_compare_and_swap_write(&zz, 25, 117) == 25); +# else + MISSING(AO_int_fetch_compare_and_swap); + if (zz == 25) zz = 117; +# endif + TA_assert(zz == 117); +# if defined(AO_HAVE_double_load_write) || defined(AO_HAVE_double_store_write) + /* Initialize old_w even for store to workaround MSan warning. */ + old_w.AO_val1 = 3316; + old_w.AO_val2 = 2921; +# endif +# if defined(AO_HAVE_double_load_write) + new_w = AO_double_load_write(&old_w); + TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921); +# elif !defined(AO_HAVE_double_load) \ + || !defined(AO_HAVE_double_load_acquire) \ + || !defined(AO_HAVE_double_load_acquire_read) \ + || !defined(AO_HAVE_double_load_dd_acquire_read) \ + || !defined(AO_HAVE_double_load_full) \ + || !defined(AO_HAVE_double_load_read) + MISSING(AO_double_load); +# endif +# if defined(AO_HAVE_double_store_write) + new_w.AO_val1 = 1375; + new_w.AO_val2 = 8243; + AO_double_store_write(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + AO_double_store_write(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + new_w.AO_val1 ^= old_w.AO_val1; + new_w.AO_val2 ^= old_w.AO_val2; + AO_double_store_write(&old_w, new_w); + TA_assert(old_w.AO_val1 == 0 && old_w.AO_val2 == 0); +# elif !defined(AO_HAVE_double_store) \ + || !defined(AO_HAVE_double_store_full) \ + || !defined(AO_HAVE_double_store_release) \ + || !defined(AO_HAVE_double_store_release_write) \ + || !defined(AO_HAVE_double_store_write) + MISSING(AO_double_store); +# endif +# if defined(AO_HAVE_compare_double_and_swap_double_write) + TA_assert(!AO_compare_double_and_swap_double_write(&w, 17, 42, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_double_and_swap_double_write(&w, 0, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_write(&w, 12, 14, 64, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_write(&w, 11, 13, 85, 82)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_write(&w, 13, 12, 17, 42)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_double_and_swap_double_write(&w, 12, 13, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_double_and_swap_double_write(&w, 17, 42, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_double_and_swap_double); +# endif +# if defined(AO_HAVE_compare_and_swap_double_write) + TA_assert(!AO_compare_and_swap_double_write(&w, 17, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_and_swap_double_write(&w, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_write(&w, 13, 12, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_write(&w, 1213, 48, 86)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_and_swap_double_write(&w, 12, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_and_swap_double_write(&w, 17, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_and_swap_double); +# endif +# if defined(AO_HAVE_double_compare_and_swap_write) + old_w.AO_val1 = 4116; + old_w.AO_val2 = 2121; + new_w.AO_val1 = 8537; + new_w.AO_val2 = 6410; + TA_assert(!AO_double_compare_and_swap_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_double_compare_and_swap_write(&w, w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = 29; + new_w.AO_val1 = 820; + new_w.AO_val2 = 5917; + TA_assert(!AO_double_compare_and_swap_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = 11; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 3552; + new_w.AO_val2 = 1746; + TA_assert(!AO_double_compare_and_swap_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 8537; + new_w.AO_val1 = 4116; + new_w.AO_val2 = 2121; + TA_assert(!AO_double_compare_and_swap_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 1; + TA_assert(AO_double_compare_and_swap_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 1 && w.AO_val2 == 2121); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = w.AO_val2; + new_w.AO_val1--; + new_w.AO_val2 = 0; + TA_assert(AO_double_compare_and_swap_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_double_compare_and_swap); +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* Some basic sanity tests. These do not test the barrier semantics. */ + +#undef TA_assert +#define TA_assert(e) \ + if (!(e)) { fprintf(stderr, "Assertion failed %s:%d (barrier: _full)\n", \ + __FILE__, __LINE__), exit(1); } + +#undef MISSING +#define MISSING(name) \ + printf("Missing: %s\n", #name "_full") + +#if defined(CPPCHECK) + void list_atomic_full(void); + void char_list_atomic_full(void); + void short_list_atomic_full(void); + void int_list_atomic_full(void); + void double_list_atomic_full(void); +#endif + +void test_atomic_full(void) +{ + AO_t x; + unsigned char b; + unsigned short s; + unsigned int zz; +# if defined(AO_HAVE_test_and_set_full) + AO_TS_t z = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_compare_and_swap_full) \ + || defined(AO_HAVE_double_load_full) \ + || defined(AO_HAVE_double_store_full) + static AO_double_t old_w; /* static to avoid misalignment */ + AO_double_t new_w; +# endif +# if defined(AO_HAVE_compare_and_swap_double_full) \ + || defined(AO_HAVE_compare_double_and_swap_double_full) \ + || defined(AO_HAVE_double_compare_and_swap_full) + static AO_double_t w; /* static to avoid misalignment */ + w.AO_val1 = 0; + w.AO_val2 = 0; +# endif + +# if defined(CPPCHECK) + list_atomic_full(); + char_list_atomic_full(); + short_list_atomic_full(); + int_list_atomic_full(); + double_list_atomic_full(); +# endif +# if defined(AO_HAVE_nop_full) + AO_nop_full(); +# elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \ + || !defined(AO_HAVE_nop_read) || !defined(AO_HAVE_nop_write) + MISSING(AO_nop); +# endif +# if defined(AO_HAVE_store_full) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile AO_t *)&x = 0; /* initialize to avoid false warning */ +# endif + AO_store_full(&x, 13); + TA_assert(x == 13); +# else +# if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \ + || !defined(AO_HAVE_store_release) \ + || !defined(AO_HAVE_store_release_write) \ + || !defined(AO_HAVE_store_write) + MISSING(AO_store); +# endif + x = 13; +# endif +# if defined(AO_HAVE_load_full) + TA_assert(AO_load_full(&x) == 13); +# elif !defined(AO_HAVE_load) || !defined(AO_HAVE_load_acquire) \ + || !defined(AO_HAVE_load_acquire_read) \ + || !defined(AO_HAVE_load_dd_acquire_read) \ + || !defined(AO_HAVE_load_full) || !defined(AO_HAVE_load_read) + MISSING(AO_load); +# endif +# if defined(AO_HAVE_test_and_set_full) + TA_assert(AO_test_and_set_full(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_set_full(&z) == AO_TS_SET); + TA_assert(AO_test_and_set_full(&z) == AO_TS_SET); + AO_CLEAR(&z); +# else + MISSING(AO_test_and_set); +# endif +# if defined(AO_HAVE_fetch_and_add_full) + TA_assert(AO_fetch_and_add_full(&x, 42) == 13); + TA_assert(AO_fetch_and_add_full(&x, (AO_t)(-42)) == 55); +# else + MISSING(AO_fetch_and_add); +# endif +# if defined(AO_HAVE_fetch_and_add1_full) + TA_assert(AO_fetch_and_add1_full(&x) == 13); +# else + MISSING(AO_fetch_and_add1); + ++x; +# endif +# if defined(AO_HAVE_fetch_and_sub1_full) + TA_assert(AO_fetch_and_sub1_full(&x) == 14); +# else + MISSING(AO_fetch_and_sub1); + --x; +# endif +# if defined(AO_HAVE_short_store_full) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile short *)&s = 0; +# endif + AO_short_store_full(&s, 13); +# else +# if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \ + || !defined(AO_HAVE_short_store_release) \ + || !defined(AO_HAVE_short_store_release_write) \ + || !defined(AO_HAVE_short_store_write) + MISSING(AO_short_store); +# endif + s = 13; +# endif +# if defined(AO_HAVE_short_load_full) + TA_assert(AO_short_load(&s) == 13); +# elif !defined(AO_HAVE_short_load) || !defined(AO_HAVE_short_load_acquire) \ + || !defined(AO_HAVE_short_load_acquire_read) \ + || !defined(AO_HAVE_short_load_dd_acquire_read) \ + || !defined(AO_HAVE_short_load_full) \ + || !defined(AO_HAVE_short_load_read) + MISSING(AO_short_load); +# endif +# if defined(AO_HAVE_short_fetch_and_add_full) + TA_assert(AO_short_fetch_and_add_full(&s, 42) == 13); + TA_assert(AO_short_fetch_and_add_full(&s, (unsigned short)-42) == 55); +# else + MISSING(AO_short_fetch_and_add); +# endif +# if defined(AO_HAVE_short_fetch_and_add1_full) + TA_assert(AO_short_fetch_and_add1_full(&s) == 13); +# else + MISSING(AO_short_fetch_and_add1); + ++s; +# endif +# if defined(AO_HAVE_short_fetch_and_sub1_full) + TA_assert(AO_short_fetch_and_sub1_full(&s) == 14); +# else + MISSING(AO_short_fetch_and_sub1); + --s; +# endif + TA_assert(*(volatile short *)&s == 13); +# if defined(AO_HAVE_char_store_full) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile char *)&b = 0; +# endif + AO_char_store_full(&b, 13); +# else +# if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \ + || !defined(AO_HAVE_char_store_release) \ + || !defined(AO_HAVE_char_store_release_write) \ + || !defined(AO_HAVE_char_store_write) + MISSING(AO_char_store); +# endif + b = 13; +# endif +# if defined(AO_HAVE_char_load_full) + TA_assert(AO_char_load(&b) == 13); +# elif !defined(AO_HAVE_char_load) || !defined(AO_HAVE_char_load_acquire) \ + || !defined(AO_HAVE_char_load_acquire_read) \ + || !defined(AO_HAVE_char_load_dd_acquire_read) \ + || !defined(AO_HAVE_char_load_full) || !defined(AO_HAVE_char_load_read) + MISSING(AO_char_load); +# endif +# if defined(AO_HAVE_char_fetch_and_add_full) + TA_assert(AO_char_fetch_and_add_full(&b, 42) == 13); + TA_assert(AO_char_fetch_and_add_full(&b, (unsigned char)-42) == 55); +# else + MISSING(AO_char_fetch_and_add); +# endif +# if defined(AO_HAVE_char_fetch_and_add1_full) + TA_assert(AO_char_fetch_and_add1_full(&b) == 13); +# else + MISSING(AO_char_fetch_and_add1); + ++b; +# endif +# if defined(AO_HAVE_char_fetch_and_sub1_full) + TA_assert(AO_char_fetch_and_sub1_full(&b) == 14); +# else + MISSING(AO_char_fetch_and_sub1); + --b; +# endif + TA_assert(*(volatile char *)&b == 13); +# if defined(AO_HAVE_int_store_full) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile int *)&zz = 0; +# endif + AO_int_store_full(&zz, 13); +# else +# if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \ + || !defined(AO_HAVE_int_store_release) \ + || !defined(AO_HAVE_int_store_release_write) \ + || !defined(AO_HAVE_int_store_write) + MISSING(AO_int_store); +# endif + zz = 13; +# endif +# if defined(AO_HAVE_int_load_full) + TA_assert(AO_int_load(&zz) == 13); +# elif !defined(AO_HAVE_int_load) || !defined(AO_HAVE_int_load_acquire) \ + || !defined(AO_HAVE_int_load_acquire_read) \ + || !defined(AO_HAVE_int_load_dd_acquire_read) \ + || !defined(AO_HAVE_int_load_full) || !defined(AO_HAVE_int_load_read) + MISSING(AO_int_load); +# endif +# if defined(AO_HAVE_int_fetch_and_add_full) + TA_assert(AO_int_fetch_and_add_full(&zz, 42) == 13); + TA_assert(AO_int_fetch_and_add_full(&zz, (unsigned int)-42) == 55); +# else + MISSING(AO_int_fetch_and_add); +# endif +# if defined(AO_HAVE_int_fetch_and_add1_full) + TA_assert(AO_int_fetch_and_add1_full(&zz) == 13); +# else + MISSING(AO_int_fetch_and_add1); + ++zz; +# endif +# if defined(AO_HAVE_int_fetch_and_sub1_full) + TA_assert(AO_int_fetch_and_sub1_full(&zz) == 14); +# else + MISSING(AO_int_fetch_and_sub1); + --zz; +# endif + TA_assert(*(volatile int *)&zz == 13); +# if defined(AO_HAVE_compare_and_swap_full) + TA_assert(!AO_compare_and_swap_full(&x, 14, 42)); + TA_assert(x == 13); + TA_assert(AO_compare_and_swap_full(&x, 13, 42)); + TA_assert(x == 42); +# else + MISSING(AO_compare_and_swap); + if (*(volatile AO_t *)&x == 13) x = 42; +# endif +# if defined(AO_HAVE_or_full) + AO_or_full(&x, 66); + TA_assert(x == 106); +# else +# if !defined(AO_HAVE_or) || !defined(AO_HAVE_or_acquire) \ + || !defined(AO_HAVE_or_acquire_read) || !defined(AO_HAVE_or_full) \ + || !defined(AO_HAVE_or_read) || !defined(AO_HAVE_or_release) \ + || !defined(AO_HAVE_or_release_write) || !defined(AO_HAVE_or_write) + MISSING(AO_or); +# endif + x |= 66; +# endif +# if defined(AO_HAVE_xor_full) + AO_xor_full(&x, 181); + TA_assert(x == 223); +# else +# if !defined(AO_HAVE_xor) || !defined(AO_HAVE_xor_acquire) \ + || !defined(AO_HAVE_xor_acquire_read) || !defined(AO_HAVE_xor_full) \ + || !defined(AO_HAVE_xor_read) || !defined(AO_HAVE_xor_release) \ + || !defined(AO_HAVE_xor_release_write) || !defined(AO_HAVE_xor_write) + MISSING(AO_xor); +# endif + x ^= 181; +# endif +# if defined(AO_HAVE_and_full) + AO_and_full(&x, 57); + TA_assert(x == 25); +# else +# if !defined(AO_HAVE_and) || !defined(AO_HAVE_and_acquire) \ + || !defined(AO_HAVE_and_acquire_read) || !defined(AO_HAVE_and_full) \ + || !defined(AO_HAVE_and_read) || !defined(AO_HAVE_and_release) \ + || !defined(AO_HAVE_and_release_write) || !defined(AO_HAVE_and_write) + MISSING(AO_and); +# endif + x &= 57; +# endif +# if defined(AO_HAVE_fetch_compare_and_swap_full) + TA_assert(AO_fetch_compare_and_swap_full(&x, 14, 117) == 25); + TA_assert(x == 25); + TA_assert(AO_fetch_compare_and_swap_full(&x, 25, 117) == 25); +# else + MISSING(AO_fetch_compare_and_swap); + if (x == 25) x = 117; +# endif + TA_assert(x == 117); +# if defined(AO_HAVE_short_compare_and_swap_full) + TA_assert(!AO_short_compare_and_swap_full(&s, 14, 42)); + TA_assert(s == 13); + TA_assert(AO_short_compare_and_swap_full(&s, 13, 42)); + TA_assert(s == 42); +# else + MISSING(AO_short_compare_and_swap); + if (*(volatile short *)&s == 13) s = 42; +# endif +# if defined(AO_HAVE_short_or_full) + AO_short_or_full(&s, 66); + TA_assert(s == 106); +# else +# if !defined(AO_HAVE_short_or) || !defined(AO_HAVE_short_or_acquire) \ + || !defined(AO_HAVE_short_or_acquire_read) \ + || !defined(AO_HAVE_short_or_full) || !defined(AO_HAVE_short_or_read) \ + || !defined(AO_HAVE_short_or_release) \ + || !defined(AO_HAVE_short_or_release_write) \ + || !defined(AO_HAVE_short_or_write) + MISSING(AO_short_or); +# endif + s |= 66; +# endif +# if defined(AO_HAVE_short_xor_full) + AO_short_xor_full(&s, 181); + TA_assert(s == 223); +# else +# if !defined(AO_HAVE_short_xor) || !defined(AO_HAVE_short_xor_acquire) \ + || !defined(AO_HAVE_short_xor_acquire_read) \ + || !defined(AO_HAVE_short_xor_full) \ + || !defined(AO_HAVE_short_xor_read) \ + || !defined(AO_HAVE_short_xor_release) \ + || !defined(AO_HAVE_short_xor_release_write) \ + || !defined(AO_HAVE_short_xor_write) + MISSING(AO_short_xor); +# endif + s ^= 181; +# endif +# if defined(AO_HAVE_short_and_full) + AO_short_and_full(&s, 57); + TA_assert(s == 25); +# else +# if !defined(AO_HAVE_short_and) || !defined(AO_HAVE_short_and_acquire) \ + || !defined(AO_HAVE_short_and_acquire_read) \ + || !defined(AO_HAVE_short_and_full) \ + || !defined(AO_HAVE_short_and_read) \ + || !defined(AO_HAVE_short_and_release) \ + || !defined(AO_HAVE_short_and_release_write) \ + || !defined(AO_HAVE_short_and_write) + MISSING(AO_short_and); +# endif + s &= 57; +# endif +# if defined(AO_HAVE_short_fetch_compare_and_swap_full) + TA_assert(AO_short_fetch_compare_and_swap_full(&s, 14, 117) == 25); + TA_assert(s == 25); + TA_assert(AO_short_fetch_compare_and_swap_full(&s, 25, 117) == 25); +# else + MISSING(AO_short_fetch_compare_and_swap); + if (s == 25) s = 117; +# endif + TA_assert(s == 117); +# if defined(AO_HAVE_char_compare_and_swap_full) + TA_assert(!AO_char_compare_and_swap_full(&b, 14, 42)); + TA_assert(b == 13); + TA_assert(AO_char_compare_and_swap_full(&b, 13, 42)); + TA_assert(b == 42); +# else + MISSING(AO_char_compare_and_swap); + if (*(volatile char *)&b == 13) b = 42; +# endif +# if defined(AO_HAVE_char_or_full) + AO_char_or_full(&b, 66); + TA_assert(b == 106); +# else +# if !defined(AO_HAVE_char_or) || !defined(AO_HAVE_char_or_acquire) \ + || !defined(AO_HAVE_char_or_acquire_read) \ + || !defined(AO_HAVE_char_or_full) || !defined(AO_HAVE_char_or_read) \ + || !defined(AO_HAVE_char_or_release) \ + || !defined(AO_HAVE_char_or_release_write) \ + || !defined(AO_HAVE_char_or_write) + MISSING(AO_char_or); +# endif + b |= 66; +# endif +# if defined(AO_HAVE_char_xor_full) + AO_char_xor_full(&b, 181); + TA_assert(b == 223); +# else +# if !defined(AO_HAVE_char_xor) || !defined(AO_HAVE_char_xor_acquire) \ + || !defined(AO_HAVE_char_xor_acquire_read) \ + || !defined(AO_HAVE_char_xor_full) || !defined(AO_HAVE_char_xor_read) \ + || !defined(AO_HAVE_char_xor_release) \ + || !defined(AO_HAVE_char_xor_release_write) \ + || !defined(AO_HAVE_char_xor_write) + MISSING(AO_char_xor); +# endif + b ^= 181; +# endif +# if defined(AO_HAVE_char_and_full) + AO_char_and_full(&b, 57); + TA_assert(b == 25); +# else +# if !defined(AO_HAVE_char_and) || !defined(AO_HAVE_char_and_acquire) \ + || !defined(AO_HAVE_char_and_acquire_read) \ + || !defined(AO_HAVE_char_and_full) || !defined(AO_HAVE_char_and_read) \ + || !defined(AO_HAVE_char_and_release) \ + || !defined(AO_HAVE_char_and_release_write) \ + || !defined(AO_HAVE_char_and_write) + MISSING(AO_char_and); +# endif + b &= 57; +# endif +# if defined(AO_HAVE_char_fetch_compare_and_swap_full) + TA_assert(AO_char_fetch_compare_and_swap_full(&b, 14, 117) == 25); + TA_assert(b == 25); + TA_assert(AO_char_fetch_compare_and_swap_full(&b, 25, 117) == 25); +# else + MISSING(AO_char_fetch_compare_and_swap); + if (b == 25) b = 117; +# endif + TA_assert(b == 117); +# if defined(AO_HAVE_int_compare_and_swap_full) + TA_assert(!AO_int_compare_and_swap_full(&zz, 14, 42)); + TA_assert(zz == 13); + TA_assert(AO_int_compare_and_swap_full(&zz, 13, 42)); + TA_assert(zz == 42); +# else + MISSING(AO_int_compare_and_swap); + if (*(volatile int *)&zz == 13) zz = 42; +# endif +# if defined(AO_HAVE_int_or_full) + AO_int_or_full(&zz, 66); + TA_assert(zz == 106); +# else +# if !defined(AO_HAVE_int_or) || !defined(AO_HAVE_int_or_acquire) \ + || !defined(AO_HAVE_int_or_acquire_read) \ + || !defined(AO_HAVE_int_or_full) || !defined(AO_HAVE_int_or_read) \ + || !defined(AO_HAVE_int_or_release) \ + || !defined(AO_HAVE_int_or_release_write) \ + || !defined(AO_HAVE_int_or_write) + MISSING(AO_int_or); +# endif + zz |= 66; +# endif +# if defined(AO_HAVE_int_xor_full) + AO_int_xor_full(&zz, 181); + TA_assert(zz == 223); +# else +# if !defined(AO_HAVE_int_xor) || !defined(AO_HAVE_int_xor_acquire) \ + || !defined(AO_HAVE_int_xor_acquire_read) \ + || !defined(AO_HAVE_int_xor_full) || !defined(AO_HAVE_int_xor_read) \ + || !defined(AO_HAVE_int_xor_release) \ + || !defined(AO_HAVE_int_xor_release_write) \ + || !defined(AO_HAVE_int_xor_write) + MISSING(AO_int_xor); +# endif + zz ^= 181; +# endif +# if defined(AO_HAVE_int_and_full) + AO_int_and_full(&zz, 57); + TA_assert(zz == 25); +# else +# if !defined(AO_HAVE_int_and) || !defined(AO_HAVE_int_and_acquire) \ + || !defined(AO_HAVE_int_and_acquire_read) \ + || !defined(AO_HAVE_int_and_full) || !defined(AO_HAVE_int_and_read) \ + || !defined(AO_HAVE_int_and_release) \ + || !defined(AO_HAVE_int_and_release_write) \ + || !defined(AO_HAVE_int_and_write) + MISSING(AO_int_and); +# endif + zz &= 57; +# endif +# if defined(AO_HAVE_int_fetch_compare_and_swap_full) + TA_assert(AO_int_fetch_compare_and_swap_full(&zz, 14, 117) == 25); + TA_assert(zz == 25); + TA_assert(AO_int_fetch_compare_and_swap_full(&zz, 25, 117) == 25); +# else + MISSING(AO_int_fetch_compare_and_swap); + if (zz == 25) zz = 117; +# endif + TA_assert(zz == 117); +# if defined(AO_HAVE_double_load_full) || defined(AO_HAVE_double_store_full) + /* Initialize old_w even for store to workaround MSan warning. */ + old_w.AO_val1 = 3316; + old_w.AO_val2 = 2921; +# endif +# if defined(AO_HAVE_double_load_full) + new_w = AO_double_load_full(&old_w); + TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921); +# elif !defined(AO_HAVE_double_load) \ + || !defined(AO_HAVE_double_load_acquire) \ + || !defined(AO_HAVE_double_load_acquire_read) \ + || !defined(AO_HAVE_double_load_dd_acquire_read) \ + || !defined(AO_HAVE_double_load_full) \ + || !defined(AO_HAVE_double_load_read) + MISSING(AO_double_load); +# endif +# if defined(AO_HAVE_double_store_full) + new_w.AO_val1 = 1375; + new_w.AO_val2 = 8243; + AO_double_store_full(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + AO_double_store_full(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + new_w.AO_val1 ^= old_w.AO_val1; + new_w.AO_val2 ^= old_w.AO_val2; + AO_double_store_full(&old_w, new_w); + TA_assert(old_w.AO_val1 == 0 && old_w.AO_val2 == 0); +# elif !defined(AO_HAVE_double_store) \ + || !defined(AO_HAVE_double_store_full) \ + || !defined(AO_HAVE_double_store_release) \ + || !defined(AO_HAVE_double_store_release_write) \ + || !defined(AO_HAVE_double_store_write) + MISSING(AO_double_store); +# endif +# if defined(AO_HAVE_compare_double_and_swap_double_full) + TA_assert(!AO_compare_double_and_swap_double_full(&w, 17, 42, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_double_and_swap_double_full(&w, 0, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_full(&w, 12, 14, 64, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_full(&w, 11, 13, 85, 82)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_full(&w, 13, 12, 17, 42)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_double_and_swap_double_full(&w, 12, 13, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_double_and_swap_double_full(&w, 17, 42, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_double_and_swap_double); +# endif +# if defined(AO_HAVE_compare_and_swap_double_full) + TA_assert(!AO_compare_and_swap_double_full(&w, 17, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_and_swap_double_full(&w, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_full(&w, 13, 12, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_full(&w, 1213, 48, 86)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_and_swap_double_full(&w, 12, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_and_swap_double_full(&w, 17, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_and_swap_double); +# endif +# if defined(AO_HAVE_double_compare_and_swap_full) + old_w.AO_val1 = 4116; + old_w.AO_val2 = 2121; + new_w.AO_val1 = 8537; + new_w.AO_val2 = 6410; + TA_assert(!AO_double_compare_and_swap_full(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_double_compare_and_swap_full(&w, w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = 29; + new_w.AO_val1 = 820; + new_w.AO_val2 = 5917; + TA_assert(!AO_double_compare_and_swap_full(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = 11; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 3552; + new_w.AO_val2 = 1746; + TA_assert(!AO_double_compare_and_swap_full(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 8537; + new_w.AO_val1 = 4116; + new_w.AO_val2 = 2121; + TA_assert(!AO_double_compare_and_swap_full(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 1; + TA_assert(AO_double_compare_and_swap_full(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 1 && w.AO_val2 == 2121); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = w.AO_val2; + new_w.AO_val1--; + new_w.AO_val2 = 0; + TA_assert(AO_double_compare_and_swap_full(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_double_compare_and_swap); +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* Some basic sanity tests. These do not test the barrier semantics. */ + +#undef TA_assert +#define TA_assert(e) \ + if (!(e)) { fprintf(stderr, "Assertion failed %s:%d (barrier: _release_write)\n", \ + __FILE__, __LINE__), exit(1); } + +#undef MISSING +#define MISSING(name) \ + printf("Missing: %s\n", #name "_release_write") + +#if defined(CPPCHECK) + void list_atomic_release_write(void); + void char_list_atomic_release_write(void); + void short_list_atomic_release_write(void); + void int_list_atomic_release_write(void); + void double_list_atomic_release_write(void); +#endif + +void test_atomic_release_write(void) +{ + AO_t x; + unsigned char b; + unsigned short s; + unsigned int zz; +# if defined(AO_HAVE_test_and_set_release_write) + AO_TS_t z = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_compare_and_swap_release_write) \ + || defined(AO_HAVE_double_load_release_write) \ + || defined(AO_HAVE_double_store_release_write) + static AO_double_t old_w; /* static to avoid misalignment */ + AO_double_t new_w; +# endif +# if defined(AO_HAVE_compare_and_swap_double_release_write) \ + || defined(AO_HAVE_compare_double_and_swap_double_release_write) \ + || defined(AO_HAVE_double_compare_and_swap_release_write) + static AO_double_t w; /* static to avoid misalignment */ + w.AO_val1 = 0; + w.AO_val2 = 0; +# endif + +# if defined(CPPCHECK) + list_atomic_release_write(); + char_list_atomic_release_write(); + short_list_atomic_release_write(); + int_list_atomic_release_write(); + double_list_atomic_release_write(); +# endif +# if defined(AO_HAVE_nop_release_write) + AO_nop_release_write(); +# elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \ + || !defined(AO_HAVE_nop_read) || !defined(AO_HAVE_nop_write) + MISSING(AO_nop); +# endif +# if defined(AO_HAVE_store_release_write) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile AO_t *)&x = 0; /* initialize to avoid false warning */ +# endif + AO_store_release_write(&x, 13); + TA_assert(x == 13); +# else +# if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \ + || !defined(AO_HAVE_store_release) \ + || !defined(AO_HAVE_store_release_write) \ + || !defined(AO_HAVE_store_write) + MISSING(AO_store); +# endif + x = 13; +# endif +# if defined(AO_HAVE_load_release_write) + TA_assert(AO_load_release_write(&x) == 13); +# elif !defined(AO_HAVE_load) || !defined(AO_HAVE_load_acquire) \ + || !defined(AO_HAVE_load_acquire_read) \ + || !defined(AO_HAVE_load_dd_acquire_read) \ + || !defined(AO_HAVE_load_full) || !defined(AO_HAVE_load_read) + MISSING(AO_load); +# endif +# if defined(AO_HAVE_test_and_set_release_write) + TA_assert(AO_test_and_set_release_write(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_set_release_write(&z) == AO_TS_SET); + TA_assert(AO_test_and_set_release_write(&z) == AO_TS_SET); + AO_CLEAR(&z); +# else + MISSING(AO_test_and_set); +# endif +# if defined(AO_HAVE_fetch_and_add_release_write) + TA_assert(AO_fetch_and_add_release_write(&x, 42) == 13); + TA_assert(AO_fetch_and_add_release_write(&x, (AO_t)(-42)) == 55); +# else + MISSING(AO_fetch_and_add); +# endif +# if defined(AO_HAVE_fetch_and_add1_release_write) + TA_assert(AO_fetch_and_add1_release_write(&x) == 13); +# else + MISSING(AO_fetch_and_add1); + ++x; +# endif +# if defined(AO_HAVE_fetch_and_sub1_release_write) + TA_assert(AO_fetch_and_sub1_release_write(&x) == 14); +# else + MISSING(AO_fetch_and_sub1); + --x; +# endif +# if defined(AO_HAVE_short_store_release_write) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile short *)&s = 0; +# endif + AO_short_store_release_write(&s, 13); +# else +# if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \ + || !defined(AO_HAVE_short_store_release) \ + || !defined(AO_HAVE_short_store_release_write) \ + || !defined(AO_HAVE_short_store_write) + MISSING(AO_short_store); +# endif + s = 13; +# endif +# if defined(AO_HAVE_short_load_release_write) + TA_assert(AO_short_load(&s) == 13); +# elif !defined(AO_HAVE_short_load) || !defined(AO_HAVE_short_load_acquire) \ + || !defined(AO_HAVE_short_load_acquire_read) \ + || !defined(AO_HAVE_short_load_dd_acquire_read) \ + || !defined(AO_HAVE_short_load_full) \ + || !defined(AO_HAVE_short_load_read) + MISSING(AO_short_load); +# endif +# if defined(AO_HAVE_short_fetch_and_add_release_write) + TA_assert(AO_short_fetch_and_add_release_write(&s, 42) == 13); + TA_assert(AO_short_fetch_and_add_release_write(&s, (unsigned short)-42) == 55); +# else + MISSING(AO_short_fetch_and_add); +# endif +# if defined(AO_HAVE_short_fetch_and_add1_release_write) + TA_assert(AO_short_fetch_and_add1_release_write(&s) == 13); +# else + MISSING(AO_short_fetch_and_add1); + ++s; +# endif +# if defined(AO_HAVE_short_fetch_and_sub1_release_write) + TA_assert(AO_short_fetch_and_sub1_release_write(&s) == 14); +# else + MISSING(AO_short_fetch_and_sub1); + --s; +# endif + TA_assert(*(volatile short *)&s == 13); +# if defined(AO_HAVE_char_store_release_write) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile char *)&b = 0; +# endif + AO_char_store_release_write(&b, 13); +# else +# if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \ + || !defined(AO_HAVE_char_store_release) \ + || !defined(AO_HAVE_char_store_release_write) \ + || !defined(AO_HAVE_char_store_write) + MISSING(AO_char_store); +# endif + b = 13; +# endif +# if defined(AO_HAVE_char_load_release_write) + TA_assert(AO_char_load(&b) == 13); +# elif !defined(AO_HAVE_char_load) || !defined(AO_HAVE_char_load_acquire) \ + || !defined(AO_HAVE_char_load_acquire_read) \ + || !defined(AO_HAVE_char_load_dd_acquire_read) \ + || !defined(AO_HAVE_char_load_full) || !defined(AO_HAVE_char_load_read) + MISSING(AO_char_load); +# endif +# if defined(AO_HAVE_char_fetch_and_add_release_write) + TA_assert(AO_char_fetch_and_add_release_write(&b, 42) == 13); + TA_assert(AO_char_fetch_and_add_release_write(&b, (unsigned char)-42) == 55); +# else + MISSING(AO_char_fetch_and_add); +# endif +# if defined(AO_HAVE_char_fetch_and_add1_release_write) + TA_assert(AO_char_fetch_and_add1_release_write(&b) == 13); +# else + MISSING(AO_char_fetch_and_add1); + ++b; +# endif +# if defined(AO_HAVE_char_fetch_and_sub1_release_write) + TA_assert(AO_char_fetch_and_sub1_release_write(&b) == 14); +# else + MISSING(AO_char_fetch_and_sub1); + --b; +# endif + TA_assert(*(volatile char *)&b == 13); +# if defined(AO_HAVE_int_store_release_write) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile int *)&zz = 0; +# endif + AO_int_store_release_write(&zz, 13); +# else +# if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \ + || !defined(AO_HAVE_int_store_release) \ + || !defined(AO_HAVE_int_store_release_write) \ + || !defined(AO_HAVE_int_store_write) + MISSING(AO_int_store); +# endif + zz = 13; +# endif +# if defined(AO_HAVE_int_load_release_write) + TA_assert(AO_int_load(&zz) == 13); +# elif !defined(AO_HAVE_int_load) || !defined(AO_HAVE_int_load_acquire) \ + || !defined(AO_HAVE_int_load_acquire_read) \ + || !defined(AO_HAVE_int_load_dd_acquire_read) \ + || !defined(AO_HAVE_int_load_full) || !defined(AO_HAVE_int_load_read) + MISSING(AO_int_load); +# endif +# if defined(AO_HAVE_int_fetch_and_add_release_write) + TA_assert(AO_int_fetch_and_add_release_write(&zz, 42) == 13); + TA_assert(AO_int_fetch_and_add_release_write(&zz, (unsigned int)-42) == 55); +# else + MISSING(AO_int_fetch_and_add); +# endif +# if defined(AO_HAVE_int_fetch_and_add1_release_write) + TA_assert(AO_int_fetch_and_add1_release_write(&zz) == 13); +# else + MISSING(AO_int_fetch_and_add1); + ++zz; +# endif +# if defined(AO_HAVE_int_fetch_and_sub1_release_write) + TA_assert(AO_int_fetch_and_sub1_release_write(&zz) == 14); +# else + MISSING(AO_int_fetch_and_sub1); + --zz; +# endif + TA_assert(*(volatile int *)&zz == 13); +# if defined(AO_HAVE_compare_and_swap_release_write) + TA_assert(!AO_compare_and_swap_release_write(&x, 14, 42)); + TA_assert(x == 13); + TA_assert(AO_compare_and_swap_release_write(&x, 13, 42)); + TA_assert(x == 42); +# else + MISSING(AO_compare_and_swap); + if (*(volatile AO_t *)&x == 13) x = 42; +# endif +# if defined(AO_HAVE_or_release_write) + AO_or_release_write(&x, 66); + TA_assert(x == 106); +# else +# if !defined(AO_HAVE_or) || !defined(AO_HAVE_or_acquire) \ + || !defined(AO_HAVE_or_acquire_read) || !defined(AO_HAVE_or_full) \ + || !defined(AO_HAVE_or_read) || !defined(AO_HAVE_or_release) \ + || !defined(AO_HAVE_or_release_write) || !defined(AO_HAVE_or_write) + MISSING(AO_or); +# endif + x |= 66; +# endif +# if defined(AO_HAVE_xor_release_write) + AO_xor_release_write(&x, 181); + TA_assert(x == 223); +# else +# if !defined(AO_HAVE_xor) || !defined(AO_HAVE_xor_acquire) \ + || !defined(AO_HAVE_xor_acquire_read) || !defined(AO_HAVE_xor_full) \ + || !defined(AO_HAVE_xor_read) || !defined(AO_HAVE_xor_release) \ + || !defined(AO_HAVE_xor_release_write) || !defined(AO_HAVE_xor_write) + MISSING(AO_xor); +# endif + x ^= 181; +# endif +# if defined(AO_HAVE_and_release_write) + AO_and_release_write(&x, 57); + TA_assert(x == 25); +# else +# if !defined(AO_HAVE_and) || !defined(AO_HAVE_and_acquire) \ + || !defined(AO_HAVE_and_acquire_read) || !defined(AO_HAVE_and_full) \ + || !defined(AO_HAVE_and_read) || !defined(AO_HAVE_and_release) \ + || !defined(AO_HAVE_and_release_write) || !defined(AO_HAVE_and_write) + MISSING(AO_and); +# endif + x &= 57; +# endif +# if defined(AO_HAVE_fetch_compare_and_swap_release_write) + TA_assert(AO_fetch_compare_and_swap_release_write(&x, 14, 117) == 25); + TA_assert(x == 25); + TA_assert(AO_fetch_compare_and_swap_release_write(&x, 25, 117) == 25); +# else + MISSING(AO_fetch_compare_and_swap); + if (x == 25) x = 117; +# endif + TA_assert(x == 117); +# if defined(AO_HAVE_short_compare_and_swap_release_write) + TA_assert(!AO_short_compare_and_swap_release_write(&s, 14, 42)); + TA_assert(s == 13); + TA_assert(AO_short_compare_and_swap_release_write(&s, 13, 42)); + TA_assert(s == 42); +# else + MISSING(AO_short_compare_and_swap); + if (*(volatile short *)&s == 13) s = 42; +# endif +# if defined(AO_HAVE_short_or_release_write) + AO_short_or_release_write(&s, 66); + TA_assert(s == 106); +# else +# if !defined(AO_HAVE_short_or) || !defined(AO_HAVE_short_or_acquire) \ + || !defined(AO_HAVE_short_or_acquire_read) \ + || !defined(AO_HAVE_short_or_full) || !defined(AO_HAVE_short_or_read) \ + || !defined(AO_HAVE_short_or_release) \ + || !defined(AO_HAVE_short_or_release_write) \ + || !defined(AO_HAVE_short_or_write) + MISSING(AO_short_or); +# endif + s |= 66; +# endif +# if defined(AO_HAVE_short_xor_release_write) + AO_short_xor_release_write(&s, 181); + TA_assert(s == 223); +# else +# if !defined(AO_HAVE_short_xor) || !defined(AO_HAVE_short_xor_acquire) \ + || !defined(AO_HAVE_short_xor_acquire_read) \ + || !defined(AO_HAVE_short_xor_full) \ + || !defined(AO_HAVE_short_xor_read) \ + || !defined(AO_HAVE_short_xor_release) \ + || !defined(AO_HAVE_short_xor_release_write) \ + || !defined(AO_HAVE_short_xor_write) + MISSING(AO_short_xor); +# endif + s ^= 181; +# endif +# if defined(AO_HAVE_short_and_release_write) + AO_short_and_release_write(&s, 57); + TA_assert(s == 25); +# else +# if !defined(AO_HAVE_short_and) || !defined(AO_HAVE_short_and_acquire) \ + || !defined(AO_HAVE_short_and_acquire_read) \ + || !defined(AO_HAVE_short_and_full) \ + || !defined(AO_HAVE_short_and_read) \ + || !defined(AO_HAVE_short_and_release) \ + || !defined(AO_HAVE_short_and_release_write) \ + || !defined(AO_HAVE_short_and_write) + MISSING(AO_short_and); +# endif + s &= 57; +# endif +# if defined(AO_HAVE_short_fetch_compare_and_swap_release_write) + TA_assert(AO_short_fetch_compare_and_swap_release_write(&s, 14, 117) == 25); + TA_assert(s == 25); + TA_assert(AO_short_fetch_compare_and_swap_release_write(&s, 25, 117) == 25); +# else + MISSING(AO_short_fetch_compare_and_swap); + if (s == 25) s = 117; +# endif + TA_assert(s == 117); +# if defined(AO_HAVE_char_compare_and_swap_release_write) + TA_assert(!AO_char_compare_and_swap_release_write(&b, 14, 42)); + TA_assert(b == 13); + TA_assert(AO_char_compare_and_swap_release_write(&b, 13, 42)); + TA_assert(b == 42); +# else + MISSING(AO_char_compare_and_swap); + if (*(volatile char *)&b == 13) b = 42; +# endif +# if defined(AO_HAVE_char_or_release_write) + AO_char_or_release_write(&b, 66); + TA_assert(b == 106); +# else +# if !defined(AO_HAVE_char_or) || !defined(AO_HAVE_char_or_acquire) \ + || !defined(AO_HAVE_char_or_acquire_read) \ + || !defined(AO_HAVE_char_or_full) || !defined(AO_HAVE_char_or_read) \ + || !defined(AO_HAVE_char_or_release) \ + || !defined(AO_HAVE_char_or_release_write) \ + || !defined(AO_HAVE_char_or_write) + MISSING(AO_char_or); +# endif + b |= 66; +# endif +# if defined(AO_HAVE_char_xor_release_write) + AO_char_xor_release_write(&b, 181); + TA_assert(b == 223); +# else +# if !defined(AO_HAVE_char_xor) || !defined(AO_HAVE_char_xor_acquire) \ + || !defined(AO_HAVE_char_xor_acquire_read) \ + || !defined(AO_HAVE_char_xor_full) || !defined(AO_HAVE_char_xor_read) \ + || !defined(AO_HAVE_char_xor_release) \ + || !defined(AO_HAVE_char_xor_release_write) \ + || !defined(AO_HAVE_char_xor_write) + MISSING(AO_char_xor); +# endif + b ^= 181; +# endif +# if defined(AO_HAVE_char_and_release_write) + AO_char_and_release_write(&b, 57); + TA_assert(b == 25); +# else +# if !defined(AO_HAVE_char_and) || !defined(AO_HAVE_char_and_acquire) \ + || !defined(AO_HAVE_char_and_acquire_read) \ + || !defined(AO_HAVE_char_and_full) || !defined(AO_HAVE_char_and_read) \ + || !defined(AO_HAVE_char_and_release) \ + || !defined(AO_HAVE_char_and_release_write) \ + || !defined(AO_HAVE_char_and_write) + MISSING(AO_char_and); +# endif + b &= 57; +# endif +# if defined(AO_HAVE_char_fetch_compare_and_swap_release_write) + TA_assert(AO_char_fetch_compare_and_swap_release_write(&b, 14, 117) == 25); + TA_assert(b == 25); + TA_assert(AO_char_fetch_compare_and_swap_release_write(&b, 25, 117) == 25); +# else + MISSING(AO_char_fetch_compare_and_swap); + if (b == 25) b = 117; +# endif + TA_assert(b == 117); +# if defined(AO_HAVE_int_compare_and_swap_release_write) + TA_assert(!AO_int_compare_and_swap_release_write(&zz, 14, 42)); + TA_assert(zz == 13); + TA_assert(AO_int_compare_and_swap_release_write(&zz, 13, 42)); + TA_assert(zz == 42); +# else + MISSING(AO_int_compare_and_swap); + if (*(volatile int *)&zz == 13) zz = 42; +# endif +# if defined(AO_HAVE_int_or_release_write) + AO_int_or_release_write(&zz, 66); + TA_assert(zz == 106); +# else +# if !defined(AO_HAVE_int_or) || !defined(AO_HAVE_int_or_acquire) \ + || !defined(AO_HAVE_int_or_acquire_read) \ + || !defined(AO_HAVE_int_or_full) || !defined(AO_HAVE_int_or_read) \ + || !defined(AO_HAVE_int_or_release) \ + || !defined(AO_HAVE_int_or_release_write) \ + || !defined(AO_HAVE_int_or_write) + MISSING(AO_int_or); +# endif + zz |= 66; +# endif +# if defined(AO_HAVE_int_xor_release_write) + AO_int_xor_release_write(&zz, 181); + TA_assert(zz == 223); +# else +# if !defined(AO_HAVE_int_xor) || !defined(AO_HAVE_int_xor_acquire) \ + || !defined(AO_HAVE_int_xor_acquire_read) \ + || !defined(AO_HAVE_int_xor_full) || !defined(AO_HAVE_int_xor_read) \ + || !defined(AO_HAVE_int_xor_release) \ + || !defined(AO_HAVE_int_xor_release_write) \ + || !defined(AO_HAVE_int_xor_write) + MISSING(AO_int_xor); +# endif + zz ^= 181; +# endif +# if defined(AO_HAVE_int_and_release_write) + AO_int_and_release_write(&zz, 57); + TA_assert(zz == 25); +# else +# if !defined(AO_HAVE_int_and) || !defined(AO_HAVE_int_and_acquire) \ + || !defined(AO_HAVE_int_and_acquire_read) \ + || !defined(AO_HAVE_int_and_full) || !defined(AO_HAVE_int_and_read) \ + || !defined(AO_HAVE_int_and_release) \ + || !defined(AO_HAVE_int_and_release_write) \ + || !defined(AO_HAVE_int_and_write) + MISSING(AO_int_and); +# endif + zz &= 57; +# endif +# if defined(AO_HAVE_int_fetch_compare_and_swap_release_write) + TA_assert(AO_int_fetch_compare_and_swap_release_write(&zz, 14, 117) == 25); + TA_assert(zz == 25); + TA_assert(AO_int_fetch_compare_and_swap_release_write(&zz, 25, 117) == 25); +# else + MISSING(AO_int_fetch_compare_and_swap); + if (zz == 25) zz = 117; +# endif + TA_assert(zz == 117); +# if defined(AO_HAVE_double_load_release_write) || defined(AO_HAVE_double_store_release_write) + /* Initialize old_w even for store to workaround MSan warning. */ + old_w.AO_val1 = 3316; + old_w.AO_val2 = 2921; +# endif +# if defined(AO_HAVE_double_load_release_write) + new_w = AO_double_load_release_write(&old_w); + TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921); +# elif !defined(AO_HAVE_double_load) \ + || !defined(AO_HAVE_double_load_acquire) \ + || !defined(AO_HAVE_double_load_acquire_read) \ + || !defined(AO_HAVE_double_load_dd_acquire_read) \ + || !defined(AO_HAVE_double_load_full) \ + || !defined(AO_HAVE_double_load_read) + MISSING(AO_double_load); +# endif +# if defined(AO_HAVE_double_store_release_write) + new_w.AO_val1 = 1375; + new_w.AO_val2 = 8243; + AO_double_store_release_write(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + AO_double_store_release_write(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + new_w.AO_val1 ^= old_w.AO_val1; + new_w.AO_val2 ^= old_w.AO_val2; + AO_double_store_release_write(&old_w, new_w); + TA_assert(old_w.AO_val1 == 0 && old_w.AO_val2 == 0); +# elif !defined(AO_HAVE_double_store) \ + || !defined(AO_HAVE_double_store_full) \ + || !defined(AO_HAVE_double_store_release) \ + || !defined(AO_HAVE_double_store_release_write) \ + || !defined(AO_HAVE_double_store_write) + MISSING(AO_double_store); +# endif +# if defined(AO_HAVE_compare_double_and_swap_double_release_write) + TA_assert(!AO_compare_double_and_swap_double_release_write(&w, 17, 42, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_double_and_swap_double_release_write(&w, 0, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_release_write(&w, 12, 14, 64, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_release_write(&w, 11, 13, 85, 82)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_release_write(&w, 13, 12, 17, 42)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_double_and_swap_double_release_write(&w, 12, 13, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_double_and_swap_double_release_write(&w, 17, 42, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_double_and_swap_double); +# endif +# if defined(AO_HAVE_compare_and_swap_double_release_write) + TA_assert(!AO_compare_and_swap_double_release_write(&w, 17, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_and_swap_double_release_write(&w, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_release_write(&w, 13, 12, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_release_write(&w, 1213, 48, 86)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_and_swap_double_release_write(&w, 12, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_and_swap_double_release_write(&w, 17, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_and_swap_double); +# endif +# if defined(AO_HAVE_double_compare_and_swap_release_write) + old_w.AO_val1 = 4116; + old_w.AO_val2 = 2121; + new_w.AO_val1 = 8537; + new_w.AO_val2 = 6410; + TA_assert(!AO_double_compare_and_swap_release_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_double_compare_and_swap_release_write(&w, w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = 29; + new_w.AO_val1 = 820; + new_w.AO_val2 = 5917; + TA_assert(!AO_double_compare_and_swap_release_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = 11; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 3552; + new_w.AO_val2 = 1746; + TA_assert(!AO_double_compare_and_swap_release_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 8537; + new_w.AO_val1 = 4116; + new_w.AO_val2 = 2121; + TA_assert(!AO_double_compare_and_swap_release_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 1; + TA_assert(AO_double_compare_and_swap_release_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 1 && w.AO_val2 == 2121); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = w.AO_val2; + new_w.AO_val1--; + new_w.AO_val2 = 0; + TA_assert(AO_double_compare_and_swap_release_write(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_double_compare_and_swap); +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* Some basic sanity tests. These do not test the barrier semantics. */ + +#undef TA_assert +#define TA_assert(e) \ + if (!(e)) { fprintf(stderr, "Assertion failed %s:%d (barrier: _acquire_read)\n", \ + __FILE__, __LINE__), exit(1); } + +#undef MISSING +#define MISSING(name) \ + printf("Missing: %s\n", #name "_acquire_read") + +#if defined(CPPCHECK) + void list_atomic_acquire_read(void); + void char_list_atomic_acquire_read(void); + void short_list_atomic_acquire_read(void); + void int_list_atomic_acquire_read(void); + void double_list_atomic_acquire_read(void); +#endif + +void test_atomic_acquire_read(void) +{ + AO_t x; + unsigned char b; + unsigned short s; + unsigned int zz; +# if defined(AO_HAVE_test_and_set_acquire_read) + AO_TS_t z = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_compare_and_swap_acquire_read) \ + || defined(AO_HAVE_double_load_acquire_read) \ + || defined(AO_HAVE_double_store_acquire_read) + static AO_double_t old_w; /* static to avoid misalignment */ + AO_double_t new_w; +# endif +# if defined(AO_HAVE_compare_and_swap_double_acquire_read) \ + || defined(AO_HAVE_compare_double_and_swap_double_acquire_read) \ + || defined(AO_HAVE_double_compare_and_swap_acquire_read) + static AO_double_t w; /* static to avoid misalignment */ + w.AO_val1 = 0; + w.AO_val2 = 0; +# endif + +# if defined(CPPCHECK) + list_atomic_acquire_read(); + char_list_atomic_acquire_read(); + short_list_atomic_acquire_read(); + int_list_atomic_acquire_read(); + double_list_atomic_acquire_read(); +# endif +# if defined(AO_HAVE_nop_acquire_read) + AO_nop_acquire_read(); +# elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \ + || !defined(AO_HAVE_nop_read) || !defined(AO_HAVE_nop_write) + MISSING(AO_nop); +# endif +# if defined(AO_HAVE_store_acquire_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile AO_t *)&x = 0; /* initialize to avoid false warning */ +# endif + AO_store_acquire_read(&x, 13); + TA_assert(x == 13); +# else +# if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \ + || !defined(AO_HAVE_store_release) \ + || !defined(AO_HAVE_store_release_write) \ + || !defined(AO_HAVE_store_write) + MISSING(AO_store); +# endif + x = 13; +# endif +# if defined(AO_HAVE_load_acquire_read) + TA_assert(AO_load_acquire_read(&x) == 13); +# elif !defined(AO_HAVE_load) || !defined(AO_HAVE_load_acquire) \ + || !defined(AO_HAVE_load_acquire_read) \ + || !defined(AO_HAVE_load_dd_acquire_read) \ + || !defined(AO_HAVE_load_full) || !defined(AO_HAVE_load_read) + MISSING(AO_load); +# endif +# if defined(AO_HAVE_test_and_set_acquire_read) + TA_assert(AO_test_and_set_acquire_read(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_set_acquire_read(&z) == AO_TS_SET); + TA_assert(AO_test_and_set_acquire_read(&z) == AO_TS_SET); + AO_CLEAR(&z); +# else + MISSING(AO_test_and_set); +# endif +# if defined(AO_HAVE_fetch_and_add_acquire_read) + TA_assert(AO_fetch_and_add_acquire_read(&x, 42) == 13); + TA_assert(AO_fetch_and_add_acquire_read(&x, (AO_t)(-42)) == 55); +# else + MISSING(AO_fetch_and_add); +# endif +# if defined(AO_HAVE_fetch_and_add1_acquire_read) + TA_assert(AO_fetch_and_add1_acquire_read(&x) == 13); +# else + MISSING(AO_fetch_and_add1); + ++x; +# endif +# if defined(AO_HAVE_fetch_and_sub1_acquire_read) + TA_assert(AO_fetch_and_sub1_acquire_read(&x) == 14); +# else + MISSING(AO_fetch_and_sub1); + --x; +# endif +# if defined(AO_HAVE_short_store_acquire_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile short *)&s = 0; +# endif + AO_short_store_acquire_read(&s, 13); +# else +# if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \ + || !defined(AO_HAVE_short_store_release) \ + || !defined(AO_HAVE_short_store_release_write) \ + || !defined(AO_HAVE_short_store_write) + MISSING(AO_short_store); +# endif + s = 13; +# endif +# if defined(AO_HAVE_short_load_acquire_read) + TA_assert(AO_short_load(&s) == 13); +# elif !defined(AO_HAVE_short_load) || !defined(AO_HAVE_short_load_acquire) \ + || !defined(AO_HAVE_short_load_acquire_read) \ + || !defined(AO_HAVE_short_load_dd_acquire_read) \ + || !defined(AO_HAVE_short_load_full) \ + || !defined(AO_HAVE_short_load_read) + MISSING(AO_short_load); +# endif +# if defined(AO_HAVE_short_fetch_and_add_acquire_read) + TA_assert(AO_short_fetch_and_add_acquire_read(&s, 42) == 13); + TA_assert(AO_short_fetch_and_add_acquire_read(&s, (unsigned short)-42) == 55); +# else + MISSING(AO_short_fetch_and_add); +# endif +# if defined(AO_HAVE_short_fetch_and_add1_acquire_read) + TA_assert(AO_short_fetch_and_add1_acquire_read(&s) == 13); +# else + MISSING(AO_short_fetch_and_add1); + ++s; +# endif +# if defined(AO_HAVE_short_fetch_and_sub1_acquire_read) + TA_assert(AO_short_fetch_and_sub1_acquire_read(&s) == 14); +# else + MISSING(AO_short_fetch_and_sub1); + --s; +# endif + TA_assert(*(volatile short *)&s == 13); +# if defined(AO_HAVE_char_store_acquire_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile char *)&b = 0; +# endif + AO_char_store_acquire_read(&b, 13); +# else +# if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \ + || !defined(AO_HAVE_char_store_release) \ + || !defined(AO_HAVE_char_store_release_write) \ + || !defined(AO_HAVE_char_store_write) + MISSING(AO_char_store); +# endif + b = 13; +# endif +# if defined(AO_HAVE_char_load_acquire_read) + TA_assert(AO_char_load(&b) == 13); +# elif !defined(AO_HAVE_char_load) || !defined(AO_HAVE_char_load_acquire) \ + || !defined(AO_HAVE_char_load_acquire_read) \ + || !defined(AO_HAVE_char_load_dd_acquire_read) \ + || !defined(AO_HAVE_char_load_full) || !defined(AO_HAVE_char_load_read) + MISSING(AO_char_load); +# endif +# if defined(AO_HAVE_char_fetch_and_add_acquire_read) + TA_assert(AO_char_fetch_and_add_acquire_read(&b, 42) == 13); + TA_assert(AO_char_fetch_and_add_acquire_read(&b, (unsigned char)-42) == 55); +# else + MISSING(AO_char_fetch_and_add); +# endif +# if defined(AO_HAVE_char_fetch_and_add1_acquire_read) + TA_assert(AO_char_fetch_and_add1_acquire_read(&b) == 13); +# else + MISSING(AO_char_fetch_and_add1); + ++b; +# endif +# if defined(AO_HAVE_char_fetch_and_sub1_acquire_read) + TA_assert(AO_char_fetch_and_sub1_acquire_read(&b) == 14); +# else + MISSING(AO_char_fetch_and_sub1); + --b; +# endif + TA_assert(*(volatile char *)&b == 13); +# if defined(AO_HAVE_int_store_acquire_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile int *)&zz = 0; +# endif + AO_int_store_acquire_read(&zz, 13); +# else +# if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \ + || !defined(AO_HAVE_int_store_release) \ + || !defined(AO_HAVE_int_store_release_write) \ + || !defined(AO_HAVE_int_store_write) + MISSING(AO_int_store); +# endif + zz = 13; +# endif +# if defined(AO_HAVE_int_load_acquire_read) + TA_assert(AO_int_load(&zz) == 13); +# elif !defined(AO_HAVE_int_load) || !defined(AO_HAVE_int_load_acquire) \ + || !defined(AO_HAVE_int_load_acquire_read) \ + || !defined(AO_HAVE_int_load_dd_acquire_read) \ + || !defined(AO_HAVE_int_load_full) || !defined(AO_HAVE_int_load_read) + MISSING(AO_int_load); +# endif +# if defined(AO_HAVE_int_fetch_and_add_acquire_read) + TA_assert(AO_int_fetch_and_add_acquire_read(&zz, 42) == 13); + TA_assert(AO_int_fetch_and_add_acquire_read(&zz, (unsigned int)-42) == 55); +# else + MISSING(AO_int_fetch_and_add); +# endif +# if defined(AO_HAVE_int_fetch_and_add1_acquire_read) + TA_assert(AO_int_fetch_and_add1_acquire_read(&zz) == 13); +# else + MISSING(AO_int_fetch_and_add1); + ++zz; +# endif +# if defined(AO_HAVE_int_fetch_and_sub1_acquire_read) + TA_assert(AO_int_fetch_and_sub1_acquire_read(&zz) == 14); +# else + MISSING(AO_int_fetch_and_sub1); + --zz; +# endif + TA_assert(*(volatile int *)&zz == 13); +# if defined(AO_HAVE_compare_and_swap_acquire_read) + TA_assert(!AO_compare_and_swap_acquire_read(&x, 14, 42)); + TA_assert(x == 13); + TA_assert(AO_compare_and_swap_acquire_read(&x, 13, 42)); + TA_assert(x == 42); +# else + MISSING(AO_compare_and_swap); + if (*(volatile AO_t *)&x == 13) x = 42; +# endif +# if defined(AO_HAVE_or_acquire_read) + AO_or_acquire_read(&x, 66); + TA_assert(x == 106); +# else +# if !defined(AO_HAVE_or) || !defined(AO_HAVE_or_acquire) \ + || !defined(AO_HAVE_or_acquire_read) || !defined(AO_HAVE_or_full) \ + || !defined(AO_HAVE_or_read) || !defined(AO_HAVE_or_release) \ + || !defined(AO_HAVE_or_release_write) || !defined(AO_HAVE_or_write) + MISSING(AO_or); +# endif + x |= 66; +# endif +# if defined(AO_HAVE_xor_acquire_read) + AO_xor_acquire_read(&x, 181); + TA_assert(x == 223); +# else +# if !defined(AO_HAVE_xor) || !defined(AO_HAVE_xor_acquire) \ + || !defined(AO_HAVE_xor_acquire_read) || !defined(AO_HAVE_xor_full) \ + || !defined(AO_HAVE_xor_read) || !defined(AO_HAVE_xor_release) \ + || !defined(AO_HAVE_xor_release_write) || !defined(AO_HAVE_xor_write) + MISSING(AO_xor); +# endif + x ^= 181; +# endif +# if defined(AO_HAVE_and_acquire_read) + AO_and_acquire_read(&x, 57); + TA_assert(x == 25); +# else +# if !defined(AO_HAVE_and) || !defined(AO_HAVE_and_acquire) \ + || !defined(AO_HAVE_and_acquire_read) || !defined(AO_HAVE_and_full) \ + || !defined(AO_HAVE_and_read) || !defined(AO_HAVE_and_release) \ + || !defined(AO_HAVE_and_release_write) || !defined(AO_HAVE_and_write) + MISSING(AO_and); +# endif + x &= 57; +# endif +# if defined(AO_HAVE_fetch_compare_and_swap_acquire_read) + TA_assert(AO_fetch_compare_and_swap_acquire_read(&x, 14, 117) == 25); + TA_assert(x == 25); + TA_assert(AO_fetch_compare_and_swap_acquire_read(&x, 25, 117) == 25); +# else + MISSING(AO_fetch_compare_and_swap); + if (x == 25) x = 117; +# endif + TA_assert(x == 117); +# if defined(AO_HAVE_short_compare_and_swap_acquire_read) + TA_assert(!AO_short_compare_and_swap_acquire_read(&s, 14, 42)); + TA_assert(s == 13); + TA_assert(AO_short_compare_and_swap_acquire_read(&s, 13, 42)); + TA_assert(s == 42); +# else + MISSING(AO_short_compare_and_swap); + if (*(volatile short *)&s == 13) s = 42; +# endif +# if defined(AO_HAVE_short_or_acquire_read) + AO_short_or_acquire_read(&s, 66); + TA_assert(s == 106); +# else +# if !defined(AO_HAVE_short_or) || !defined(AO_HAVE_short_or_acquire) \ + || !defined(AO_HAVE_short_or_acquire_read) \ + || !defined(AO_HAVE_short_or_full) || !defined(AO_HAVE_short_or_read) \ + || !defined(AO_HAVE_short_or_release) \ + || !defined(AO_HAVE_short_or_release_write) \ + || !defined(AO_HAVE_short_or_write) + MISSING(AO_short_or); +# endif + s |= 66; +# endif +# if defined(AO_HAVE_short_xor_acquire_read) + AO_short_xor_acquire_read(&s, 181); + TA_assert(s == 223); +# else +# if !defined(AO_HAVE_short_xor) || !defined(AO_HAVE_short_xor_acquire) \ + || !defined(AO_HAVE_short_xor_acquire_read) \ + || !defined(AO_HAVE_short_xor_full) \ + || !defined(AO_HAVE_short_xor_read) \ + || !defined(AO_HAVE_short_xor_release) \ + || !defined(AO_HAVE_short_xor_release_write) \ + || !defined(AO_HAVE_short_xor_write) + MISSING(AO_short_xor); +# endif + s ^= 181; +# endif +# if defined(AO_HAVE_short_and_acquire_read) + AO_short_and_acquire_read(&s, 57); + TA_assert(s == 25); +# else +# if !defined(AO_HAVE_short_and) || !defined(AO_HAVE_short_and_acquire) \ + || !defined(AO_HAVE_short_and_acquire_read) \ + || !defined(AO_HAVE_short_and_full) \ + || !defined(AO_HAVE_short_and_read) \ + || !defined(AO_HAVE_short_and_release) \ + || !defined(AO_HAVE_short_and_release_write) \ + || !defined(AO_HAVE_short_and_write) + MISSING(AO_short_and); +# endif + s &= 57; +# endif +# if defined(AO_HAVE_short_fetch_compare_and_swap_acquire_read) + TA_assert(AO_short_fetch_compare_and_swap_acquire_read(&s, 14, 117) == 25); + TA_assert(s == 25); + TA_assert(AO_short_fetch_compare_and_swap_acquire_read(&s, 25, 117) == 25); +# else + MISSING(AO_short_fetch_compare_and_swap); + if (s == 25) s = 117; +# endif + TA_assert(s == 117); +# if defined(AO_HAVE_char_compare_and_swap_acquire_read) + TA_assert(!AO_char_compare_and_swap_acquire_read(&b, 14, 42)); + TA_assert(b == 13); + TA_assert(AO_char_compare_and_swap_acquire_read(&b, 13, 42)); + TA_assert(b == 42); +# else + MISSING(AO_char_compare_and_swap); + if (*(volatile char *)&b == 13) b = 42; +# endif +# if defined(AO_HAVE_char_or_acquire_read) + AO_char_or_acquire_read(&b, 66); + TA_assert(b == 106); +# else +# if !defined(AO_HAVE_char_or) || !defined(AO_HAVE_char_or_acquire) \ + || !defined(AO_HAVE_char_or_acquire_read) \ + || !defined(AO_HAVE_char_or_full) || !defined(AO_HAVE_char_or_read) \ + || !defined(AO_HAVE_char_or_release) \ + || !defined(AO_HAVE_char_or_release_write) \ + || !defined(AO_HAVE_char_or_write) + MISSING(AO_char_or); +# endif + b |= 66; +# endif +# if defined(AO_HAVE_char_xor_acquire_read) + AO_char_xor_acquire_read(&b, 181); + TA_assert(b == 223); +# else +# if !defined(AO_HAVE_char_xor) || !defined(AO_HAVE_char_xor_acquire) \ + || !defined(AO_HAVE_char_xor_acquire_read) \ + || !defined(AO_HAVE_char_xor_full) || !defined(AO_HAVE_char_xor_read) \ + || !defined(AO_HAVE_char_xor_release) \ + || !defined(AO_HAVE_char_xor_release_write) \ + || !defined(AO_HAVE_char_xor_write) + MISSING(AO_char_xor); +# endif + b ^= 181; +# endif +# if defined(AO_HAVE_char_and_acquire_read) + AO_char_and_acquire_read(&b, 57); + TA_assert(b == 25); +# else +# if !defined(AO_HAVE_char_and) || !defined(AO_HAVE_char_and_acquire) \ + || !defined(AO_HAVE_char_and_acquire_read) \ + || !defined(AO_HAVE_char_and_full) || !defined(AO_HAVE_char_and_read) \ + || !defined(AO_HAVE_char_and_release) \ + || !defined(AO_HAVE_char_and_release_write) \ + || !defined(AO_HAVE_char_and_write) + MISSING(AO_char_and); +# endif + b &= 57; +# endif +# if defined(AO_HAVE_char_fetch_compare_and_swap_acquire_read) + TA_assert(AO_char_fetch_compare_and_swap_acquire_read(&b, 14, 117) == 25); + TA_assert(b == 25); + TA_assert(AO_char_fetch_compare_and_swap_acquire_read(&b, 25, 117) == 25); +# else + MISSING(AO_char_fetch_compare_and_swap); + if (b == 25) b = 117; +# endif + TA_assert(b == 117); +# if defined(AO_HAVE_int_compare_and_swap_acquire_read) + TA_assert(!AO_int_compare_and_swap_acquire_read(&zz, 14, 42)); + TA_assert(zz == 13); + TA_assert(AO_int_compare_and_swap_acquire_read(&zz, 13, 42)); + TA_assert(zz == 42); +# else + MISSING(AO_int_compare_and_swap); + if (*(volatile int *)&zz == 13) zz = 42; +# endif +# if defined(AO_HAVE_int_or_acquire_read) + AO_int_or_acquire_read(&zz, 66); + TA_assert(zz == 106); +# else +# if !defined(AO_HAVE_int_or) || !defined(AO_HAVE_int_or_acquire) \ + || !defined(AO_HAVE_int_or_acquire_read) \ + || !defined(AO_HAVE_int_or_full) || !defined(AO_HAVE_int_or_read) \ + || !defined(AO_HAVE_int_or_release) \ + || !defined(AO_HAVE_int_or_release_write) \ + || !defined(AO_HAVE_int_or_write) + MISSING(AO_int_or); +# endif + zz |= 66; +# endif +# if defined(AO_HAVE_int_xor_acquire_read) + AO_int_xor_acquire_read(&zz, 181); + TA_assert(zz == 223); +# else +# if !defined(AO_HAVE_int_xor) || !defined(AO_HAVE_int_xor_acquire) \ + || !defined(AO_HAVE_int_xor_acquire_read) \ + || !defined(AO_HAVE_int_xor_full) || !defined(AO_HAVE_int_xor_read) \ + || !defined(AO_HAVE_int_xor_release) \ + || !defined(AO_HAVE_int_xor_release_write) \ + || !defined(AO_HAVE_int_xor_write) + MISSING(AO_int_xor); +# endif + zz ^= 181; +# endif +# if defined(AO_HAVE_int_and_acquire_read) + AO_int_and_acquire_read(&zz, 57); + TA_assert(zz == 25); +# else +# if !defined(AO_HAVE_int_and) || !defined(AO_HAVE_int_and_acquire) \ + || !defined(AO_HAVE_int_and_acquire_read) \ + || !defined(AO_HAVE_int_and_full) || !defined(AO_HAVE_int_and_read) \ + || !defined(AO_HAVE_int_and_release) \ + || !defined(AO_HAVE_int_and_release_write) \ + || !defined(AO_HAVE_int_and_write) + MISSING(AO_int_and); +# endif + zz &= 57; +# endif +# if defined(AO_HAVE_int_fetch_compare_and_swap_acquire_read) + TA_assert(AO_int_fetch_compare_and_swap_acquire_read(&zz, 14, 117) == 25); + TA_assert(zz == 25); + TA_assert(AO_int_fetch_compare_and_swap_acquire_read(&zz, 25, 117) == 25); +# else + MISSING(AO_int_fetch_compare_and_swap); + if (zz == 25) zz = 117; +# endif + TA_assert(zz == 117); +# if defined(AO_HAVE_double_load_acquire_read) || defined(AO_HAVE_double_store_acquire_read) + /* Initialize old_w even for store to workaround MSan warning. */ + old_w.AO_val1 = 3316; + old_w.AO_val2 = 2921; +# endif +# if defined(AO_HAVE_double_load_acquire_read) + new_w = AO_double_load_acquire_read(&old_w); + TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921); +# elif !defined(AO_HAVE_double_load) \ + || !defined(AO_HAVE_double_load_acquire) \ + || !defined(AO_HAVE_double_load_acquire_read) \ + || !defined(AO_HAVE_double_load_dd_acquire_read) \ + || !defined(AO_HAVE_double_load_full) \ + || !defined(AO_HAVE_double_load_read) + MISSING(AO_double_load); +# endif +# if defined(AO_HAVE_double_store_acquire_read) + new_w.AO_val1 = 1375; + new_w.AO_val2 = 8243; + AO_double_store_acquire_read(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + AO_double_store_acquire_read(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + new_w.AO_val1 ^= old_w.AO_val1; + new_w.AO_val2 ^= old_w.AO_val2; + AO_double_store_acquire_read(&old_w, new_w); + TA_assert(old_w.AO_val1 == 0 && old_w.AO_val2 == 0); +# elif !defined(AO_HAVE_double_store) \ + || !defined(AO_HAVE_double_store_full) \ + || !defined(AO_HAVE_double_store_release) \ + || !defined(AO_HAVE_double_store_release_write) \ + || !defined(AO_HAVE_double_store_write) + MISSING(AO_double_store); +# endif +# if defined(AO_HAVE_compare_double_and_swap_double_acquire_read) + TA_assert(!AO_compare_double_and_swap_double_acquire_read(&w, 17, 42, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_double_and_swap_double_acquire_read(&w, 0, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_acquire_read(&w, 12, 14, 64, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_acquire_read(&w, 11, 13, 85, 82)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_acquire_read(&w, 13, 12, 17, 42)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_double_and_swap_double_acquire_read(&w, 12, 13, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_double_and_swap_double_acquire_read(&w, 17, 42, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_double_and_swap_double); +# endif +# if defined(AO_HAVE_compare_and_swap_double_acquire_read) + TA_assert(!AO_compare_and_swap_double_acquire_read(&w, 17, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_and_swap_double_acquire_read(&w, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_acquire_read(&w, 13, 12, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_acquire_read(&w, 1213, 48, 86)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_and_swap_double_acquire_read(&w, 12, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_and_swap_double_acquire_read(&w, 17, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_and_swap_double); +# endif +# if defined(AO_HAVE_double_compare_and_swap_acquire_read) + old_w.AO_val1 = 4116; + old_w.AO_val2 = 2121; + new_w.AO_val1 = 8537; + new_w.AO_val2 = 6410; + TA_assert(!AO_double_compare_and_swap_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_double_compare_and_swap_acquire_read(&w, w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = 29; + new_w.AO_val1 = 820; + new_w.AO_val2 = 5917; + TA_assert(!AO_double_compare_and_swap_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = 11; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 3552; + new_w.AO_val2 = 1746; + TA_assert(!AO_double_compare_and_swap_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 8537; + new_w.AO_val1 = 4116; + new_w.AO_val2 = 2121; + TA_assert(!AO_double_compare_and_swap_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 1; + TA_assert(AO_double_compare_and_swap_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 1 && w.AO_val2 == 2121); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = w.AO_val2; + new_w.AO_val1--; + new_w.AO_val2 = 0; + TA_assert(AO_double_compare_and_swap_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_double_compare_and_swap); +# endif +} +/* + * Copyright (c) 2003 by Hewlett-Packard Company. All rights reserved. + * + * This file is covered by the GNU general public license, version 2. + * see COPYING for details. + */ + +/* Some basic sanity tests. These do not test the barrier semantics. */ + +#undef TA_assert +#define TA_assert(e) \ + if (!(e)) { fprintf(stderr, "Assertion failed %s:%d (barrier: _dd_acquire_read)\n", \ + __FILE__, __LINE__), exit(1); } + +#undef MISSING +#define MISSING(name) \ + printf("Missing: %s\n", #name "_dd_acquire_read") + +#if defined(CPPCHECK) + void list_atomic_dd_acquire_read(void); + void char_list_atomic_dd_acquire_read(void); + void short_list_atomic_dd_acquire_read(void); + void int_list_atomic_dd_acquire_read(void); + void double_list_atomic_dd_acquire_read(void); +#endif + +void test_atomic_dd_acquire_read(void) +{ + AO_t x; + unsigned char b; + unsigned short s; + unsigned int zz; +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + AO_TS_t z = AO_TS_INITIALIZER; +# endif +# if defined(AO_HAVE_double_compare_and_swap_dd_acquire_read) \ + || defined(AO_HAVE_double_load_dd_acquire_read) \ + || defined(AO_HAVE_double_store_dd_acquire_read) + static AO_double_t old_w; /* static to avoid misalignment */ + AO_double_t new_w; +# endif +# if defined(AO_HAVE_compare_and_swap_double_dd_acquire_read) \ + || defined(AO_HAVE_compare_double_and_swap_double_dd_acquire_read) \ + || defined(AO_HAVE_double_compare_and_swap_dd_acquire_read) + static AO_double_t w; /* static to avoid misalignment */ + w.AO_val1 = 0; + w.AO_val2 = 0; +# endif + +# if defined(CPPCHECK) + list_atomic_dd_acquire_read(); + char_list_atomic_dd_acquire_read(); + short_list_atomic_dd_acquire_read(); + int_list_atomic_dd_acquire_read(); + double_list_atomic_dd_acquire_read(); +# endif +# if defined(AO_HAVE_nop_dd_acquire_read) + AO_nop_dd_acquire_read(); +# elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \ + || !defined(AO_HAVE_nop_read) || !defined(AO_HAVE_nop_write) + MISSING(AO_nop); +# endif +# if defined(AO_HAVE_store_dd_acquire_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile AO_t *)&x = 0; /* initialize to avoid false warning */ +# endif + AO_store_dd_acquire_read(&x, 13); + TA_assert(x == 13); +# else +# if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \ + || !defined(AO_HAVE_store_release) \ + || !defined(AO_HAVE_store_release_write) \ + || !defined(AO_HAVE_store_write) + MISSING(AO_store); +# endif + x = 13; +# endif +# if defined(AO_HAVE_load_dd_acquire_read) + TA_assert(AO_load_dd_acquire_read(&x) == 13); +# elif !defined(AO_HAVE_load) || !defined(AO_HAVE_load_acquire) \ + || !defined(AO_HAVE_load_acquire_read) \ + || !defined(AO_HAVE_load_dd_acquire_read) \ + || !defined(AO_HAVE_load_full) || !defined(AO_HAVE_load_read) + MISSING(AO_load); +# endif +# if defined(AO_HAVE_test_and_set_dd_acquire_read) + TA_assert(AO_test_and_set_dd_acquire_read(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_set_dd_acquire_read(&z) == AO_TS_SET); + TA_assert(AO_test_and_set_dd_acquire_read(&z) == AO_TS_SET); + AO_CLEAR(&z); +# else + MISSING(AO_test_and_set); +# endif +# if defined(AO_HAVE_fetch_and_add_dd_acquire_read) + TA_assert(AO_fetch_and_add_dd_acquire_read(&x, 42) == 13); + TA_assert(AO_fetch_and_add_dd_acquire_read(&x, (AO_t)(-42)) == 55); +# else + MISSING(AO_fetch_and_add); +# endif +# if defined(AO_HAVE_fetch_and_add1_dd_acquire_read) + TA_assert(AO_fetch_and_add1_dd_acquire_read(&x) == 13); +# else + MISSING(AO_fetch_and_add1); + ++x; +# endif +# if defined(AO_HAVE_fetch_and_sub1_dd_acquire_read) + TA_assert(AO_fetch_and_sub1_dd_acquire_read(&x) == 14); +# else + MISSING(AO_fetch_and_sub1); + --x; +# endif +# if defined(AO_HAVE_short_store_dd_acquire_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile short *)&s = 0; +# endif + AO_short_store_dd_acquire_read(&s, 13); +# else +# if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \ + || !defined(AO_HAVE_short_store_release) \ + || !defined(AO_HAVE_short_store_release_write) \ + || !defined(AO_HAVE_short_store_write) + MISSING(AO_short_store); +# endif + s = 13; +# endif +# if defined(AO_HAVE_short_load_dd_acquire_read) + TA_assert(AO_short_load(&s) == 13); +# elif !defined(AO_HAVE_short_load) || !defined(AO_HAVE_short_load_acquire) \ + || !defined(AO_HAVE_short_load_acquire_read) \ + || !defined(AO_HAVE_short_load_dd_acquire_read) \ + || !defined(AO_HAVE_short_load_full) \ + || !defined(AO_HAVE_short_load_read) + MISSING(AO_short_load); +# endif +# if defined(AO_HAVE_short_fetch_and_add_dd_acquire_read) + TA_assert(AO_short_fetch_and_add_dd_acquire_read(&s, 42) == 13); + TA_assert(AO_short_fetch_and_add_dd_acquire_read(&s, (unsigned short)-42) == 55); +# else + MISSING(AO_short_fetch_and_add); +# endif +# if defined(AO_HAVE_short_fetch_and_add1_dd_acquire_read) + TA_assert(AO_short_fetch_and_add1_dd_acquire_read(&s) == 13); +# else + MISSING(AO_short_fetch_and_add1); + ++s; +# endif +# if defined(AO_HAVE_short_fetch_and_sub1_dd_acquire_read) + TA_assert(AO_short_fetch_and_sub1_dd_acquire_read(&s) == 14); +# else + MISSING(AO_short_fetch_and_sub1); + --s; +# endif + TA_assert(*(volatile short *)&s == 13); +# if defined(AO_HAVE_char_store_dd_acquire_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile char *)&b = 0; +# endif + AO_char_store_dd_acquire_read(&b, 13); +# else +# if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \ + || !defined(AO_HAVE_char_store_release) \ + || !defined(AO_HAVE_char_store_release_write) \ + || !defined(AO_HAVE_char_store_write) + MISSING(AO_char_store); +# endif + b = 13; +# endif +# if defined(AO_HAVE_char_load_dd_acquire_read) + TA_assert(AO_char_load(&b) == 13); +# elif !defined(AO_HAVE_char_load) || !defined(AO_HAVE_char_load_acquire) \ + || !defined(AO_HAVE_char_load_acquire_read) \ + || !defined(AO_HAVE_char_load_dd_acquire_read) \ + || !defined(AO_HAVE_char_load_full) || !defined(AO_HAVE_char_load_read) + MISSING(AO_char_load); +# endif +# if defined(AO_HAVE_char_fetch_and_add_dd_acquire_read) + TA_assert(AO_char_fetch_and_add_dd_acquire_read(&b, 42) == 13); + TA_assert(AO_char_fetch_and_add_dd_acquire_read(&b, (unsigned char)-42) == 55); +# else + MISSING(AO_char_fetch_and_add); +# endif +# if defined(AO_HAVE_char_fetch_and_add1_dd_acquire_read) + TA_assert(AO_char_fetch_and_add1_dd_acquire_read(&b) == 13); +# else + MISSING(AO_char_fetch_and_add1); + ++b; +# endif +# if defined(AO_HAVE_char_fetch_and_sub1_dd_acquire_read) + TA_assert(AO_char_fetch_and_sub1_dd_acquire_read(&b) == 14); +# else + MISSING(AO_char_fetch_and_sub1); + --b; +# endif + TA_assert(*(volatile char *)&b == 13); +# if defined(AO_HAVE_int_store_dd_acquire_read) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile int *)&zz = 0; +# endif + AO_int_store_dd_acquire_read(&zz, 13); +# else +# if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \ + || !defined(AO_HAVE_int_store_release) \ + || !defined(AO_HAVE_int_store_release_write) \ + || !defined(AO_HAVE_int_store_write) + MISSING(AO_int_store); +# endif + zz = 13; +# endif +# if defined(AO_HAVE_int_load_dd_acquire_read) + TA_assert(AO_int_load(&zz) == 13); +# elif !defined(AO_HAVE_int_load) || !defined(AO_HAVE_int_load_acquire) \ + || !defined(AO_HAVE_int_load_acquire_read) \ + || !defined(AO_HAVE_int_load_dd_acquire_read) \ + || !defined(AO_HAVE_int_load_full) || !defined(AO_HAVE_int_load_read) + MISSING(AO_int_load); +# endif +# if defined(AO_HAVE_int_fetch_and_add_dd_acquire_read) + TA_assert(AO_int_fetch_and_add_dd_acquire_read(&zz, 42) == 13); + TA_assert(AO_int_fetch_and_add_dd_acquire_read(&zz, (unsigned int)-42) == 55); +# else + MISSING(AO_int_fetch_and_add); +# endif +# if defined(AO_HAVE_int_fetch_and_add1_dd_acquire_read) + TA_assert(AO_int_fetch_and_add1_dd_acquire_read(&zz) == 13); +# else + MISSING(AO_int_fetch_and_add1); + ++zz; +# endif +# if defined(AO_HAVE_int_fetch_and_sub1_dd_acquire_read) + TA_assert(AO_int_fetch_and_sub1_dd_acquire_read(&zz) == 14); +# else + MISSING(AO_int_fetch_and_sub1); + --zz; +# endif + TA_assert(*(volatile int *)&zz == 13); +# if defined(AO_HAVE_compare_and_swap_dd_acquire_read) + TA_assert(!AO_compare_and_swap_dd_acquire_read(&x, 14, 42)); + TA_assert(x == 13); + TA_assert(AO_compare_and_swap_dd_acquire_read(&x, 13, 42)); + TA_assert(x == 42); +# else + MISSING(AO_compare_and_swap); + if (*(volatile AO_t *)&x == 13) x = 42; +# endif +# if defined(AO_HAVE_or_dd_acquire_read) + AO_or_dd_acquire_read(&x, 66); + TA_assert(x == 106); +# else +# if !defined(AO_HAVE_or) || !defined(AO_HAVE_or_acquire) \ + || !defined(AO_HAVE_or_acquire_read) || !defined(AO_HAVE_or_full) \ + || !defined(AO_HAVE_or_read) || !defined(AO_HAVE_or_release) \ + || !defined(AO_HAVE_or_release_write) || !defined(AO_HAVE_or_write) + MISSING(AO_or); +# endif + x |= 66; +# endif +# if defined(AO_HAVE_xor_dd_acquire_read) + AO_xor_dd_acquire_read(&x, 181); + TA_assert(x == 223); +# else +# if !defined(AO_HAVE_xor) || !defined(AO_HAVE_xor_acquire) \ + || !defined(AO_HAVE_xor_acquire_read) || !defined(AO_HAVE_xor_full) \ + || !defined(AO_HAVE_xor_read) || !defined(AO_HAVE_xor_release) \ + || !defined(AO_HAVE_xor_release_write) || !defined(AO_HAVE_xor_write) + MISSING(AO_xor); +# endif + x ^= 181; +# endif +# if defined(AO_HAVE_and_dd_acquire_read) + AO_and_dd_acquire_read(&x, 57); + TA_assert(x == 25); +# else +# if !defined(AO_HAVE_and) || !defined(AO_HAVE_and_acquire) \ + || !defined(AO_HAVE_and_acquire_read) || !defined(AO_HAVE_and_full) \ + || !defined(AO_HAVE_and_read) || !defined(AO_HAVE_and_release) \ + || !defined(AO_HAVE_and_release_write) || !defined(AO_HAVE_and_write) + MISSING(AO_and); +# endif + x &= 57; +# endif +# if defined(AO_HAVE_fetch_compare_and_swap_dd_acquire_read) + TA_assert(AO_fetch_compare_and_swap_dd_acquire_read(&x, 14, 117) == 25); + TA_assert(x == 25); + TA_assert(AO_fetch_compare_and_swap_dd_acquire_read(&x, 25, 117) == 25); +# else + MISSING(AO_fetch_compare_and_swap); + if (x == 25) x = 117; +# endif + TA_assert(x == 117); +# if defined(AO_HAVE_short_compare_and_swap_dd_acquire_read) + TA_assert(!AO_short_compare_and_swap_dd_acquire_read(&s, 14, 42)); + TA_assert(s == 13); + TA_assert(AO_short_compare_and_swap_dd_acquire_read(&s, 13, 42)); + TA_assert(s == 42); +# else + MISSING(AO_short_compare_and_swap); + if (*(volatile short *)&s == 13) s = 42; +# endif +# if defined(AO_HAVE_short_or_dd_acquire_read) + AO_short_or_dd_acquire_read(&s, 66); + TA_assert(s == 106); +# else +# if !defined(AO_HAVE_short_or) || !defined(AO_HAVE_short_or_acquire) \ + || !defined(AO_HAVE_short_or_acquire_read) \ + || !defined(AO_HAVE_short_or_full) || !defined(AO_HAVE_short_or_read) \ + || !defined(AO_HAVE_short_or_release) \ + || !defined(AO_HAVE_short_or_release_write) \ + || !defined(AO_HAVE_short_or_write) + MISSING(AO_short_or); +# endif + s |= 66; +# endif +# if defined(AO_HAVE_short_xor_dd_acquire_read) + AO_short_xor_dd_acquire_read(&s, 181); + TA_assert(s == 223); +# else +# if !defined(AO_HAVE_short_xor) || !defined(AO_HAVE_short_xor_acquire) \ + || !defined(AO_HAVE_short_xor_acquire_read) \ + || !defined(AO_HAVE_short_xor_full) \ + || !defined(AO_HAVE_short_xor_read) \ + || !defined(AO_HAVE_short_xor_release) \ + || !defined(AO_HAVE_short_xor_release_write) \ + || !defined(AO_HAVE_short_xor_write) + MISSING(AO_short_xor); +# endif + s ^= 181; +# endif +# if defined(AO_HAVE_short_and_dd_acquire_read) + AO_short_and_dd_acquire_read(&s, 57); + TA_assert(s == 25); +# else +# if !defined(AO_HAVE_short_and) || !defined(AO_HAVE_short_and_acquire) \ + || !defined(AO_HAVE_short_and_acquire_read) \ + || !defined(AO_HAVE_short_and_full) \ + || !defined(AO_HAVE_short_and_read) \ + || !defined(AO_HAVE_short_and_release) \ + || !defined(AO_HAVE_short_and_release_write) \ + || !defined(AO_HAVE_short_and_write) + MISSING(AO_short_and); +# endif + s &= 57; +# endif +# if defined(AO_HAVE_short_fetch_compare_and_swap_dd_acquire_read) + TA_assert(AO_short_fetch_compare_and_swap_dd_acquire_read(&s, 14, 117) == 25); + TA_assert(s == 25); + TA_assert(AO_short_fetch_compare_and_swap_dd_acquire_read(&s, 25, 117) == 25); +# else + MISSING(AO_short_fetch_compare_and_swap); + if (s == 25) s = 117; +# endif + TA_assert(s == 117); +# if defined(AO_HAVE_char_compare_and_swap_dd_acquire_read) + TA_assert(!AO_char_compare_and_swap_dd_acquire_read(&b, 14, 42)); + TA_assert(b == 13); + TA_assert(AO_char_compare_and_swap_dd_acquire_read(&b, 13, 42)); + TA_assert(b == 42); +# else + MISSING(AO_char_compare_and_swap); + if (*(volatile char *)&b == 13) b = 42; +# endif +# if defined(AO_HAVE_char_or_dd_acquire_read) + AO_char_or_dd_acquire_read(&b, 66); + TA_assert(b == 106); +# else +# if !defined(AO_HAVE_char_or) || !defined(AO_HAVE_char_or_acquire) \ + || !defined(AO_HAVE_char_or_acquire_read) \ + || !defined(AO_HAVE_char_or_full) || !defined(AO_HAVE_char_or_read) \ + || !defined(AO_HAVE_char_or_release) \ + || !defined(AO_HAVE_char_or_release_write) \ + || !defined(AO_HAVE_char_or_write) + MISSING(AO_char_or); +# endif + b |= 66; +# endif +# if defined(AO_HAVE_char_xor_dd_acquire_read) + AO_char_xor_dd_acquire_read(&b, 181); + TA_assert(b == 223); +# else +# if !defined(AO_HAVE_char_xor) || !defined(AO_HAVE_char_xor_acquire) \ + || !defined(AO_HAVE_char_xor_acquire_read) \ + || !defined(AO_HAVE_char_xor_full) || !defined(AO_HAVE_char_xor_read) \ + || !defined(AO_HAVE_char_xor_release) \ + || !defined(AO_HAVE_char_xor_release_write) \ + || !defined(AO_HAVE_char_xor_write) + MISSING(AO_char_xor); +# endif + b ^= 181; +# endif +# if defined(AO_HAVE_char_and_dd_acquire_read) + AO_char_and_dd_acquire_read(&b, 57); + TA_assert(b == 25); +# else +# if !defined(AO_HAVE_char_and) || !defined(AO_HAVE_char_and_acquire) \ + || !defined(AO_HAVE_char_and_acquire_read) \ + || !defined(AO_HAVE_char_and_full) || !defined(AO_HAVE_char_and_read) \ + || !defined(AO_HAVE_char_and_release) \ + || !defined(AO_HAVE_char_and_release_write) \ + || !defined(AO_HAVE_char_and_write) + MISSING(AO_char_and); +# endif + b &= 57; +# endif +# if defined(AO_HAVE_char_fetch_compare_and_swap_dd_acquire_read) + TA_assert(AO_char_fetch_compare_and_swap_dd_acquire_read(&b, 14, 117) == 25); + TA_assert(b == 25); + TA_assert(AO_char_fetch_compare_and_swap_dd_acquire_read(&b, 25, 117) == 25); +# else + MISSING(AO_char_fetch_compare_and_swap); + if (b == 25) b = 117; +# endif + TA_assert(b == 117); +# if defined(AO_HAVE_int_compare_and_swap_dd_acquire_read) + TA_assert(!AO_int_compare_and_swap_dd_acquire_read(&zz, 14, 42)); + TA_assert(zz == 13); + TA_assert(AO_int_compare_and_swap_dd_acquire_read(&zz, 13, 42)); + TA_assert(zz == 42); +# else + MISSING(AO_int_compare_and_swap); + if (*(volatile int *)&zz == 13) zz = 42; +# endif +# if defined(AO_HAVE_int_or_dd_acquire_read) + AO_int_or_dd_acquire_read(&zz, 66); + TA_assert(zz == 106); +# else +# if !defined(AO_HAVE_int_or) || !defined(AO_HAVE_int_or_acquire) \ + || !defined(AO_HAVE_int_or_acquire_read) \ + || !defined(AO_HAVE_int_or_full) || !defined(AO_HAVE_int_or_read) \ + || !defined(AO_HAVE_int_or_release) \ + || !defined(AO_HAVE_int_or_release_write) \ + || !defined(AO_HAVE_int_or_write) + MISSING(AO_int_or); +# endif + zz |= 66; +# endif +# if defined(AO_HAVE_int_xor_dd_acquire_read) + AO_int_xor_dd_acquire_read(&zz, 181); + TA_assert(zz == 223); +# else +# if !defined(AO_HAVE_int_xor) || !defined(AO_HAVE_int_xor_acquire) \ + || !defined(AO_HAVE_int_xor_acquire_read) \ + || !defined(AO_HAVE_int_xor_full) || !defined(AO_HAVE_int_xor_read) \ + || !defined(AO_HAVE_int_xor_release) \ + || !defined(AO_HAVE_int_xor_release_write) \ + || !defined(AO_HAVE_int_xor_write) + MISSING(AO_int_xor); +# endif + zz ^= 181; +# endif +# if defined(AO_HAVE_int_and_dd_acquire_read) + AO_int_and_dd_acquire_read(&zz, 57); + TA_assert(zz == 25); +# else +# if !defined(AO_HAVE_int_and) || !defined(AO_HAVE_int_and_acquire) \ + || !defined(AO_HAVE_int_and_acquire_read) \ + || !defined(AO_HAVE_int_and_full) || !defined(AO_HAVE_int_and_read) \ + || !defined(AO_HAVE_int_and_release) \ + || !defined(AO_HAVE_int_and_release_write) \ + || !defined(AO_HAVE_int_and_write) + MISSING(AO_int_and); +# endif + zz &= 57; +# endif +# if defined(AO_HAVE_int_fetch_compare_and_swap_dd_acquire_read) + TA_assert(AO_int_fetch_compare_and_swap_dd_acquire_read(&zz, 14, 117) == 25); + TA_assert(zz == 25); + TA_assert(AO_int_fetch_compare_and_swap_dd_acquire_read(&zz, 25, 117) == 25); +# else + MISSING(AO_int_fetch_compare_and_swap); + if (zz == 25) zz = 117; +# endif + TA_assert(zz == 117); +# if defined(AO_HAVE_double_load_dd_acquire_read) || defined(AO_HAVE_double_store_dd_acquire_read) + /* Initialize old_w even for store to workaround MSan warning. */ + old_w.AO_val1 = 3316; + old_w.AO_val2 = 2921; +# endif +# if defined(AO_HAVE_double_load_dd_acquire_read) + new_w = AO_double_load_dd_acquire_read(&old_w); + TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921); +# elif !defined(AO_HAVE_double_load) \ + || !defined(AO_HAVE_double_load_acquire) \ + || !defined(AO_HAVE_double_load_acquire_read) \ + || !defined(AO_HAVE_double_load_dd_acquire_read) \ + || !defined(AO_HAVE_double_load_full) \ + || !defined(AO_HAVE_double_load_read) + MISSING(AO_double_load); +# endif +# if defined(AO_HAVE_double_store_dd_acquire_read) + new_w.AO_val1 = 1375; + new_w.AO_val2 = 8243; + AO_double_store_dd_acquire_read(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + AO_double_store_dd_acquire_read(&old_w, new_w); + TA_assert(old_w.AO_val1 == 1375 && old_w.AO_val2 == 8243); + new_w.AO_val1 ^= old_w.AO_val1; + new_w.AO_val2 ^= old_w.AO_val2; + AO_double_store_dd_acquire_read(&old_w, new_w); + TA_assert(old_w.AO_val1 == 0 && old_w.AO_val2 == 0); +# elif !defined(AO_HAVE_double_store) \ + || !defined(AO_HAVE_double_store_full) \ + || !defined(AO_HAVE_double_store_release) \ + || !defined(AO_HAVE_double_store_release_write) \ + || !defined(AO_HAVE_double_store_write) + MISSING(AO_double_store); +# endif +# if defined(AO_HAVE_compare_double_and_swap_double_dd_acquire_read) + TA_assert(!AO_compare_double_and_swap_double_dd_acquire_read(&w, 17, 42, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_double_and_swap_double_dd_acquire_read(&w, 0, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_dd_acquire_read(&w, 12, 14, 64, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_dd_acquire_read(&w, 11, 13, 85, 82)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_double_and_swap_double_dd_acquire_read(&w, 13, 12, 17, 42)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_double_and_swap_double_dd_acquire_read(&w, 12, 13, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_double_and_swap_double_dd_acquire_read(&w, 17, 42, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_double_and_swap_double); +# endif +# if defined(AO_HAVE_compare_and_swap_double_dd_acquire_read) + TA_assert(!AO_compare_and_swap_double_dd_acquire_read(&w, 17, 12, 13)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_compare_and_swap_double_dd_acquire_read(&w, 0, 12, 13)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_dd_acquire_read(&w, 13, 12, 33)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(!AO_compare_and_swap_double_dd_acquire_read(&w, 1213, 48, 86)); + TA_assert(w.AO_val1 == 12 && w.AO_val2 == 13); + TA_assert(AO_compare_and_swap_double_dd_acquire_read(&w, 12, 17, 42)); + TA_assert(w.AO_val1 == 17 && w.AO_val2 == 42); + TA_assert(AO_compare_and_swap_double_dd_acquire_read(&w, 17, 0, 0)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_compare_and_swap_double); +# endif +# if defined(AO_HAVE_double_compare_and_swap_dd_acquire_read) + old_w.AO_val1 = 4116; + old_w.AO_val2 = 2121; + new_w.AO_val1 = 8537; + new_w.AO_val2 = 6410; + TA_assert(!AO_double_compare_and_swap_dd_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); + TA_assert(AO_double_compare_and_swap_dd_acquire_read(&w, w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = 29; + new_w.AO_val1 = 820; + new_w.AO_val2 = 5917; + TA_assert(!AO_double_compare_and_swap_dd_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = 11; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 3552; + new_w.AO_val2 = 1746; + TA_assert(!AO_double_compare_and_swap_dd_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 8537; + new_w.AO_val1 = 4116; + new_w.AO_val2 = 2121; + TA_assert(!AO_double_compare_and_swap_dd_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 8537 && w.AO_val2 == 6410); + old_w.AO_val1 = old_w.AO_val2; + old_w.AO_val2 = 6410; + new_w.AO_val1 = 1; + TA_assert(AO_double_compare_and_swap_dd_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 1 && w.AO_val2 == 2121); + old_w.AO_val1 = new_w.AO_val1; + old_w.AO_val2 = w.AO_val2; + new_w.AO_val1--; + new_w.AO_val2 = 0; + TA_assert(AO_double_compare_and_swap_dd_acquire_read(&w, old_w, new_w)); + TA_assert(w.AO_val1 == 0 && w.AO_val2 == 0); +# else + MISSING(AO_double_compare_and_swap); +# endif +} diff --git a/src/bdwgc/libatomic_ops/tests/test_atomic_include.template b/src/bdwgc/libatomic_ops/tests/test_atomic_include.template index 60068b5b2..e246b6671 100644 --- a/src/bdwgc/libatomic_ops/tests/test_atomic_include.template +++ b/src/bdwgc/libatomic_ops/tests/test_atomic_include.template @@ -16,6 +16,14 @@ #define MISSING(name) \ printf("Missing: %s\n", #name "XX") +#if defined(CPPCHECK) + void list_atomicXX(void); + void char_list_atomicXX(void); + void short_list_atomicXX(void); + void int_list_atomicXX(void); + void double_list_atomicXX(void); +#endif + void test_atomicXX(void) { AO_t x; @@ -28,17 +36,24 @@ void test_atomicXX(void) # if defined(AO_HAVE_double_compare_and_swapXX) \ || defined(AO_HAVE_double_loadXX) \ || defined(AO_HAVE_double_storeXX) - AO_double_t old_w; + static AO_double_t old_w; /* static to avoid misalignment */ AO_double_t new_w; # endif # if defined(AO_HAVE_compare_and_swap_doubleXX) \ || defined(AO_HAVE_compare_double_and_swap_doubleXX) \ || defined(AO_HAVE_double_compare_and_swapXX) - AO_double_t w; + static AO_double_t w; /* static to avoid misalignment */ w.AO_val1 = 0; w.AO_val2 = 0; # endif +# if defined(CPPCHECK) + list_atomicXX(); + char_list_atomicXX(); + short_list_atomicXX(); + int_list_atomicXX(); + double_list_atomicXX(); +# endif # if defined(AO_HAVE_nopXX) AO_nopXX(); # elif !defined(AO_HAVE_nop) || !defined(AO_HAVE_nop_full) \ @@ -46,8 +61,12 @@ void test_atomicXX(void) MISSING(AO_nop); # endif # if defined(AO_HAVE_storeXX) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile AO_t *)&x = 0; /* initialize to avoid false warning */ +# endif AO_storeXX(&x, 13); - TA_assert (x == 13); + TA_assert(x == 13); # else # if !defined(AO_HAVE_store) || !defined(AO_HAVE_store_full) \ || !defined(AO_HAVE_store_release) \ @@ -66,9 +85,9 @@ void test_atomicXX(void) MISSING(AO_load); # endif # if defined(AO_HAVE_test_and_setXX) - assert(AO_test_and_setXX(&z) == AO_TS_CLEAR); - assert(AO_test_and_setXX(&z) == AO_TS_SET); - assert(AO_test_and_setXX(&z) == AO_TS_SET); + TA_assert(AO_test_and_setXX(&z) == AO_TS_CLEAR); + TA_assert(AO_test_and_setXX(&z) == AO_TS_SET); + TA_assert(AO_test_and_setXX(&z) == AO_TS_SET); AO_CLEAR(&z); # else MISSING(AO_test_and_set); @@ -92,6 +111,10 @@ void test_atomicXX(void) --x; # endif # if defined(AO_HAVE_short_storeXX) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile short *)&s = 0; +# endif AO_short_storeXX(&s, 13); # else # if !defined(AO_HAVE_short_store) || !defined(AO_HAVE_short_store_full) \ @@ -129,7 +152,12 @@ void test_atomicXX(void) MISSING(AO_short_fetch_and_sub1); --s; # endif + TA_assert(*(volatile short *)&s == 13); # if defined(AO_HAVE_char_storeXX) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile char *)&b = 0; +# endif AO_char_storeXX(&b, 13); # else # if !defined(AO_HAVE_char_store) || !defined(AO_HAVE_char_store_full) \ @@ -166,7 +194,12 @@ void test_atomicXX(void) MISSING(AO_char_fetch_and_sub1); --b; # endif + TA_assert(*(volatile char *)&b == 13); # if defined(AO_HAVE_int_storeXX) +# if (defined(AO_MEMORY_SANITIZER) || defined(LINT2)) \ + && defined(AO_PREFER_GENERALIZED) + *(volatile int *)&zz = 0; +# endif AO_int_storeXX(&zz, 13); # else # if !defined(AO_HAVE_int_store) || !defined(AO_HAVE_int_store_full) \ @@ -203,6 +236,7 @@ void test_atomicXX(void) MISSING(AO_int_fetch_and_sub1); --zz; # endif + TA_assert(*(volatile int *)&zz == 13); # if defined(AO_HAVE_compare_and_swapXX) TA_assert(!AO_compare_and_swapXX(&x, 14, 42)); TA_assert(x == 13); @@ -210,41 +244,241 @@ void test_atomicXX(void) TA_assert(x == 42); # else MISSING(AO_compare_and_swap); - if (x == 13) x = 42; + if (*(volatile AO_t *)&x == 13) x = 42; # endif # if defined(AO_HAVE_orXX) AO_orXX(&x, 66); TA_assert(x == 106); # else - MISSING(AO_or); +# if !defined(AO_HAVE_or) || !defined(AO_HAVE_or_acquire) \ + || !defined(AO_HAVE_or_acquire_read) || !defined(AO_HAVE_or_full) \ + || !defined(AO_HAVE_or_read) || !defined(AO_HAVE_or_release) \ + || !defined(AO_HAVE_or_release_write) || !defined(AO_HAVE_or_write) + MISSING(AO_or); +# endif x |= 66; # endif # if defined(AO_HAVE_xorXX) AO_xorXX(&x, 181); TA_assert(x == 223); # else - MISSING(AO_xor); +# if !defined(AO_HAVE_xor) || !defined(AO_HAVE_xor_acquire) \ + || !defined(AO_HAVE_xor_acquire_read) || !defined(AO_HAVE_xor_full) \ + || !defined(AO_HAVE_xor_read) || !defined(AO_HAVE_xor_release) \ + || !defined(AO_HAVE_xor_release_write) || !defined(AO_HAVE_xor_write) + MISSING(AO_xor); +# endif x ^= 181; # endif # if defined(AO_HAVE_andXX) AO_andXX(&x, 57); TA_assert(x == 25); # else - MISSING(AO_and); +# if !defined(AO_HAVE_and) || !defined(AO_HAVE_and_acquire) \ + || !defined(AO_HAVE_and_acquire_read) || !defined(AO_HAVE_and_full) \ + || !defined(AO_HAVE_and_read) || !defined(AO_HAVE_and_release) \ + || !defined(AO_HAVE_and_release_write) || !defined(AO_HAVE_and_write) + MISSING(AO_and); +# endif x &= 57; # endif # if defined(AO_HAVE_fetch_compare_and_swapXX) TA_assert(AO_fetch_compare_and_swapXX(&x, 14, 117) == 25); TA_assert(x == 25); TA_assert(AO_fetch_compare_and_swapXX(&x, 25, 117) == 25); - TA_assert(x == 117); # else MISSING(AO_fetch_compare_and_swap); if (x == 25) x = 117; # endif -# if defined(AO_HAVE_double_loadXX) + TA_assert(x == 117); +# if defined(AO_HAVE_short_compare_and_swapXX) + TA_assert(!AO_short_compare_and_swapXX(&s, 14, 42)); + TA_assert(s == 13); + TA_assert(AO_short_compare_and_swapXX(&s, 13, 42)); + TA_assert(s == 42); +# else + MISSING(AO_short_compare_and_swap); + if (*(volatile short *)&s == 13) s = 42; +# endif +# if defined(AO_HAVE_short_orXX) + AO_short_orXX(&s, 66); + TA_assert(s == 106); +# else +# if !defined(AO_HAVE_short_or) || !defined(AO_HAVE_short_or_acquire) \ + || !defined(AO_HAVE_short_or_acquire_read) \ + || !defined(AO_HAVE_short_or_full) || !defined(AO_HAVE_short_or_read) \ + || !defined(AO_HAVE_short_or_release) \ + || !defined(AO_HAVE_short_or_release_write) \ + || !defined(AO_HAVE_short_or_write) + MISSING(AO_short_or); +# endif + s |= 66; +# endif +# if defined(AO_HAVE_short_xorXX) + AO_short_xorXX(&s, 181); + TA_assert(s == 223); +# else +# if !defined(AO_HAVE_short_xor) || !defined(AO_HAVE_short_xor_acquire) \ + || !defined(AO_HAVE_short_xor_acquire_read) \ + || !defined(AO_HAVE_short_xor_full) \ + || !defined(AO_HAVE_short_xor_read) \ + || !defined(AO_HAVE_short_xor_release) \ + || !defined(AO_HAVE_short_xor_release_write) \ + || !defined(AO_HAVE_short_xor_write) + MISSING(AO_short_xor); +# endif + s ^= 181; +# endif +# if defined(AO_HAVE_short_andXX) + AO_short_andXX(&s, 57); + TA_assert(s == 25); +# else +# if !defined(AO_HAVE_short_and) || !defined(AO_HAVE_short_and_acquire) \ + || !defined(AO_HAVE_short_and_acquire_read) \ + || !defined(AO_HAVE_short_and_full) \ + || !defined(AO_HAVE_short_and_read) \ + || !defined(AO_HAVE_short_and_release) \ + || !defined(AO_HAVE_short_and_release_write) \ + || !defined(AO_HAVE_short_and_write) + MISSING(AO_short_and); +# endif + s &= 57; +# endif +# if defined(AO_HAVE_short_fetch_compare_and_swapXX) + TA_assert(AO_short_fetch_compare_and_swapXX(&s, 14, 117) == 25); + TA_assert(s == 25); + TA_assert(AO_short_fetch_compare_and_swapXX(&s, 25, 117) == 25); +# else + MISSING(AO_short_fetch_compare_and_swap); + if (s == 25) s = 117; +# endif + TA_assert(s == 117); +# if defined(AO_HAVE_char_compare_and_swapXX) + TA_assert(!AO_char_compare_and_swapXX(&b, 14, 42)); + TA_assert(b == 13); + TA_assert(AO_char_compare_and_swapXX(&b, 13, 42)); + TA_assert(b == 42); +# else + MISSING(AO_char_compare_and_swap); + if (*(volatile char *)&b == 13) b = 42; +# endif +# if defined(AO_HAVE_char_orXX) + AO_char_orXX(&b, 66); + TA_assert(b == 106); +# else +# if !defined(AO_HAVE_char_or) || !defined(AO_HAVE_char_or_acquire) \ + || !defined(AO_HAVE_char_or_acquire_read) \ + || !defined(AO_HAVE_char_or_full) || !defined(AO_HAVE_char_or_read) \ + || !defined(AO_HAVE_char_or_release) \ + || !defined(AO_HAVE_char_or_release_write) \ + || !defined(AO_HAVE_char_or_write) + MISSING(AO_char_or); +# endif + b |= 66; +# endif +# if defined(AO_HAVE_char_xorXX) + AO_char_xorXX(&b, 181); + TA_assert(b == 223); +# else +# if !defined(AO_HAVE_char_xor) || !defined(AO_HAVE_char_xor_acquire) \ + || !defined(AO_HAVE_char_xor_acquire_read) \ + || !defined(AO_HAVE_char_xor_full) || !defined(AO_HAVE_char_xor_read) \ + || !defined(AO_HAVE_char_xor_release) \ + || !defined(AO_HAVE_char_xor_release_write) \ + || !defined(AO_HAVE_char_xor_write) + MISSING(AO_char_xor); +# endif + b ^= 181; +# endif +# if defined(AO_HAVE_char_andXX) + AO_char_andXX(&b, 57); + TA_assert(b == 25); +# else +# if !defined(AO_HAVE_char_and) || !defined(AO_HAVE_char_and_acquire) \ + || !defined(AO_HAVE_char_and_acquire_read) \ + || !defined(AO_HAVE_char_and_full) || !defined(AO_HAVE_char_and_read) \ + || !defined(AO_HAVE_char_and_release) \ + || !defined(AO_HAVE_char_and_release_write) \ + || !defined(AO_HAVE_char_and_write) + MISSING(AO_char_and); +# endif + b &= 57; +# endif +# if defined(AO_HAVE_char_fetch_compare_and_swapXX) + TA_assert(AO_char_fetch_compare_and_swapXX(&b, 14, 117) == 25); + TA_assert(b == 25); + TA_assert(AO_char_fetch_compare_and_swapXX(&b, 25, 117) == 25); +# else + MISSING(AO_char_fetch_compare_and_swap); + if (b == 25) b = 117; +# endif + TA_assert(b == 117); +# if defined(AO_HAVE_int_compare_and_swapXX) + TA_assert(!AO_int_compare_and_swapXX(&zz, 14, 42)); + TA_assert(zz == 13); + TA_assert(AO_int_compare_and_swapXX(&zz, 13, 42)); + TA_assert(zz == 42); +# else + MISSING(AO_int_compare_and_swap); + if (*(volatile int *)&zz == 13) zz = 42; +# endif +# if defined(AO_HAVE_int_orXX) + AO_int_orXX(&zz, 66); + TA_assert(zz == 106); +# else +# if !defined(AO_HAVE_int_or) || !defined(AO_HAVE_int_or_acquire) \ + || !defined(AO_HAVE_int_or_acquire_read) \ + || !defined(AO_HAVE_int_or_full) || !defined(AO_HAVE_int_or_read) \ + || !defined(AO_HAVE_int_or_release) \ + || !defined(AO_HAVE_int_or_release_write) \ + || !defined(AO_HAVE_int_or_write) + MISSING(AO_int_or); +# endif + zz |= 66; +# endif +# if defined(AO_HAVE_int_xorXX) + AO_int_xorXX(&zz, 181); + TA_assert(zz == 223); +# else +# if !defined(AO_HAVE_int_xor) || !defined(AO_HAVE_int_xor_acquire) \ + || !defined(AO_HAVE_int_xor_acquire_read) \ + || !defined(AO_HAVE_int_xor_full) || !defined(AO_HAVE_int_xor_read) \ + || !defined(AO_HAVE_int_xor_release) \ + || !defined(AO_HAVE_int_xor_release_write) \ + || !defined(AO_HAVE_int_xor_write) + MISSING(AO_int_xor); +# endif + zz ^= 181; +# endif +# if defined(AO_HAVE_int_andXX) + AO_int_andXX(&zz, 57); + TA_assert(zz == 25); +# else +# if !defined(AO_HAVE_int_and) || !defined(AO_HAVE_int_and_acquire) \ + || !defined(AO_HAVE_int_and_acquire_read) \ + || !defined(AO_HAVE_int_and_full) || !defined(AO_HAVE_int_and_read) \ + || !defined(AO_HAVE_int_and_release) \ + || !defined(AO_HAVE_int_and_release_write) \ + || !defined(AO_HAVE_int_and_write) + MISSING(AO_int_and); +# endif + zz &= 57; +# endif +# if defined(AO_HAVE_int_fetch_compare_and_swapXX) + TA_assert(AO_int_fetch_compare_and_swapXX(&zz, 14, 117) == 25); + TA_assert(zz == 25); + TA_assert(AO_int_fetch_compare_and_swapXX(&zz, 25, 117) == 25); +# else + MISSING(AO_int_fetch_compare_and_swap); + if (zz == 25) zz = 117; +# endif + TA_assert(zz == 117); +# if defined(AO_HAVE_double_loadXX) || defined(AO_HAVE_double_storeXX) + /* Initialize old_w even for store to workaround MSan warning. */ old_w.AO_val1 = 3316; old_w.AO_val2 = 2921; +# endif +# if defined(AO_HAVE_double_loadXX) new_w = AO_double_loadXX(&old_w); TA_assert(new_w.AO_val1 == 3316 && new_w.AO_val2 == 2921); # elif !defined(AO_HAVE_double_load) \ diff --git a/src/bdwgc/libatomic_ops/tests/test_malloc.c b/src/bdwgc/libatomic_ops/tests/test_malloc.c index dca06da94..fd95a8fa8 100644 --- a/src/bdwgc/libatomic_ops/tests/test_malloc.c +++ b/src/bdwgc/libatomic_ops/tests/test_malloc.c @@ -15,19 +15,19 @@ # include "config.h" #endif +#ifdef DONT_USE_MMAP +# undef HAVE_MMAP +#endif + #include "run_parallel.h" #include #include #include "atomic_ops_malloc.h" -#ifndef MAX_NTHREADS -# define MAX_NTHREADS 100 -#endif - #ifndef DEFAULT_NTHREADS # ifdef HAVE_MMAP -# define DEFAULT_NTHREADS 10 +# define DEFAULT_NTHREADS 16 # else # define DEFAULT_NTHREADS 3 # endif @@ -70,17 +70,18 @@ typedef struct list_node { ln *cons(int d, ln *tail) { - static size_t extra = 0; - size_t my_extra = extra; +# ifdef AO_HAVE_fetch_and_add1 + static volatile AO_t extra = 0; + size_t my_extra = (size_t)AO_fetch_and_add1(&extra) % 101; +# else + static size_t extra = 0; /* data race in extra is OK */ + size_t my_extra = (extra++) % 101; +# endif ln *result; int * extras; unsigned i; - if (my_extra > 100) - extra = my_extra = 0; - else - ++extra; - result = AO_malloc(sizeof(ln) + sizeof(int)*my_extra); + result = (ln *)AO_malloc(sizeof(ln) + sizeof(int)*my_extra); if (result == 0) { fprintf(stderr, "Out of memory\n"); @@ -95,6 +96,7 @@ ln *cons(int d, ln *tail) return result; } +#ifdef DEBUG_RUN_ONE_TEST void print_list(ln *l) { ln *p; @@ -105,6 +107,7 @@ void print_list(ln *l) } printf("\n"); } +#endif /* DEBUG_RUN_ONE_TEST */ /* Check that l contains numbers from m to n inclusive in ascending order */ void check_list(ln *l, int m, int n) @@ -140,6 +143,15 @@ make_list(int m, int n) return cons(m, make_list(m+1, n)); } +void free_list(ln *x) +{ + while (x != NULL) { + ln *next = x -> next; + AO_free(x); + x = next; + } +} + /* Reverse list x, and concatenate it to y, deallocating no longer needed */ /* nodes in x. */ ln * @@ -158,8 +170,10 @@ int dummy_test(void) { return 1; } void * run_one_test(void * arg) { ln * x = make_list(1, LIST_LENGTH); int i; - char *p = AO_malloc(LARGE_OBJ_SIZE); + char *p = (char *)AO_malloc(LARGE_OBJ_SIZE); char *q; + char a = 'a' + ((int)((AO_PTRDIFF_T)arg) * 2) % ('z' - 'a' + 1); + char b = a + 1; if (0 == p) { # ifdef HAVE_MMAP @@ -170,23 +184,21 @@ void * run_one_test(void * arg) { LARGE_OBJ_SIZE); # endif } else { - p[0] = p[LARGE_OBJ_SIZE/2] = p[LARGE_OBJ_SIZE-1] = 'a'; - q = AO_malloc(LARGE_OBJ_SIZE); + p[0] = p[LARGE_OBJ_SIZE/2] = p[LARGE_OBJ_SIZE-1] = a; + q = (char *)AO_malloc(LARGE_OBJ_SIZE); if (q == 0) { fprintf(stderr, "Out of memory\n"); /* Normal for more than about 10 threads without mmap? */ exit(2); } - q[0] = q[LARGE_OBJ_SIZE/2] = q[LARGE_OBJ_SIZE-1] = 'b'; - if (p[0] != 'a' || p[LARGE_OBJ_SIZE/2] != 'a' - || p[LARGE_OBJ_SIZE-1] != 'a') { + q[0] = q[LARGE_OBJ_SIZE/2] = q[LARGE_OBJ_SIZE-1] = b; + if (p[0] != a || p[LARGE_OBJ_SIZE/2] != a || p[LARGE_OBJ_SIZE-1] != a) { fprintf(stderr, "First large allocation smashed\n"); abort(); } AO_free(p); - if (q[0] != 'b' || q[LARGE_OBJ_SIZE/2] != 'b' - || q[LARGE_OBJ_SIZE-1] != 'b') { + if (q[0] != b || q[LARGE_OBJ_SIZE/2] != b || q[LARGE_OBJ_SIZE-1] != b) { fprintf(stderr, "Second large allocation smashed\n"); abort(); } @@ -202,14 +214,22 @@ void * run_one_test(void * arg) { x = reverse(x, 0); } check_list(x, 1, LIST_LENGTH); - return arg; /* use arg to suppress compiler warning */ + free_list(x); + return NULL; } +#ifndef LOG_MAX_SIZE +# define LOG_MAX_SIZE 16 +#endif + +#define CHUNK_SIZE (1 << LOG_MAX_SIZE) + int main(int argc, char **argv) { int nthreads; if (1 == argc) { nthreads = DEFAULT_NTHREADS; + assert(nthreads <= MAX_NTHREADS); } else if (2 == argc) { nthreads = atoi(argv[1]); if (nthreads < 1 || nthreads > MAX_NTHREADS) { @@ -223,6 +243,14 @@ int main(int argc, char **argv) { printf("Performing %d reversals of %d element lists in %d threads\n", N_REVERSALS, LIST_LENGTH, nthreads); AO_malloc_enable_mmap(); + + /* Test various corner cases. */ + AO_free(NULL); + AO_free(AO_malloc(0)); +# ifdef HAVE_MMAP + AO_free(AO_malloc(CHUNK_SIZE - (sizeof(AO_t)-1))); /* large alloc */ +# endif + run_parallel(nthreads, run_one_test, dummy_test, "AO_malloc/AO_free"); return 0; } diff --git a/src/bdwgc/libatomic_ops/tests/test_stack.c b/src/bdwgc/libatomic_ops/tests/test_stack.c index a3c5c30a0..4edc88bb6 100644 --- a/src/bdwgc/libatomic_ops/tests/test_stack.c +++ b/src/bdwgc/libatomic_ops/tests/test_stack.c @@ -43,7 +43,7 @@ #include "atomic_ops_stack.h" /* includes atomic_ops.h as well */ -#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(abort) +#if (defined(_WIN32_WCE) || defined(__MINGW32CE__)) && !defined(AO_HAVE_abort) # define abort() _exit(-1) /* there is no abort() in WinCE */ #endif @@ -51,27 +51,31 @@ # define MAX_NTHREADS 100 #endif +#ifndef DEFAULT_NTHREADS +# define DEFAULT_NTHREADS 16 /* must be <= MAX_NTHREADS */ +#endif + #ifdef NO_TIMES # define get_msecs() 0 -#elif defined(USE_WINTHREADS) || defined(AO_USE_WIN32_PTHREADS) +#elif (defined(USE_WINTHREADS) || defined(AO_USE_WIN32_PTHREADS)) \ + && !defined(CPPCHECK) # include - long long get_msecs(void) + unsigned long get_msecs(void) { struct timeb tb; ftime(&tb); - return (long long)tb.time * 1000 + tb.millitm; + return (unsigned long)tb.time * 1000 + tb.millitm; } #else /* Unix */ # include # include - /* Need 64-bit long long support */ - long long get_msecs(void) + unsigned long get_msecs(void) { struct timeval tv; gettimeofday(&tv, 0); - return (long long)tv.tv_sec * 1000 + tv.tv_usec/1000; + return (unsigned long)tv.tv_sec * 1000 + tv.tv_usec/1000; } #endif /* !NO_TIMES */ @@ -87,7 +91,7 @@ void add_elements(int n) list_element * le; if (n == 0) return; add_elements(n-1); - le = malloc(sizeof(list_element)); + le = (list_element *)malloc(sizeof(list_element)); if (le == 0) { fprintf(stderr, "Out of memory\n"); @@ -97,6 +101,7 @@ void add_elements(int n) AO_stack_push(&the_list, (AO_t *)le); } +#ifdef VERBOSE void print_list(void) { list_element *p; @@ -106,6 +111,7 @@ void print_list(void) p = (list_element *)AO_REAL_NEXT_PTR(p -> next)) printf("%d\n", p -> data); } +#endif /* VERBOSE */ static char marks[MAX_NTHREADS * (MAX_NTHREADS + 1) / 2 + 1]; @@ -218,7 +224,10 @@ int main(int argc, char **argv) int exper_n; if (1 == argc) - max_nthreads = 4; + { + max_nthreads = DEFAULT_NTHREADS; + assert(max_nthreads <= MAX_NTHREADS); + } else if (2 == argc) { max_nthreads = atoi(argv[1]); @@ -244,7 +253,7 @@ int main(int argc, char **argv) pthread_t thread[MAX_NTHREADS]; # endif int list_length = nthreads*(nthreads+1)/2; - long long start_time; + unsigned long start_time; list_element * le; # ifdef VERBOSE @@ -292,10 +301,10 @@ int main(int argc, char **argv) abort(); } } - times[nthreads][exper_n] = (unsigned long)(get_msecs() - start_time); + times[nthreads][exper_n] = get_msecs() - start_time; # ifdef VERBOSE - printf("%d %lu\n", nthreads, - (unsigned long)(get_msecs() - start_time)); + printf("nthreads=%d, time_ms=%lu\n", + nthreads, times[nthreads][exper_n]); printf("final list (should be reordered initial list):\n"); print_list(); # endif @@ -313,8 +322,8 @@ int main(int argc, char **argv) LIMIT, LIMIT, nthreads); # ifndef NO_TIMES for (exper_n = 0; exper_n < N_EXPERIMENTS; ++exper_n) { -# if defined(VERBOSE) - printf(" [%lu]", times[nthreads][exper_n]); +# ifdef VERBOSE + printf(" [%lums]", times[nthreads][exper_n]); # endif sum += times[nthreads][exper_n]; } diff --git a/src/bdwgc/m4/gc_set_version.m4 b/src/bdwgc/m4/gc_set_version.m4 new file mode 100644 index 000000000..465e4f0f9 --- /dev/null +++ b/src/bdwgc/m4/gc_set_version.m4 @@ -0,0 +1,40 @@ +# +# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED +# OR IMPLIED. ANY USE IS AT YOUR OWN RISK. +# +# Permission is hereby granted to use or copy this program +# for any purpose, provided the above notices are retained on all copies. +# Permission to modify the code and to distribute modified code is granted, +# provided the above notices are retained, and a notice that the code was +# modified is included with the above copyright notice. + +# GC_SET_VERSION +# sets and AC_DEFINEs GC_VERSION_MAJOR, GC_VERSION_MINOR and GC_VERSION_MICRO +# based on the contents of PACKAGE_VERSION; PACKAGE_VERSION must conform to +# [0-9]+[.][0-9]+[.][0-9]+ +# +AC_DEFUN([GC_SET_VERSION], [ + AC_MSG_CHECKING(GC version numbers) + GC_VERSION_MAJOR=`echo $PACKAGE_VERSION | sed 's/^\([[0-9]][[0-9]]*\)[[.]].*$/\1/g'` + GC_VERSION_MINOR=`echo $PACKAGE_VERSION | sed 's/^[[^.]]*[[.]]\([[0-9]][[0-9]]*\).*$/\1/g'` + GC_VERSION_MICRO=`echo $PACKAGE_VERSION | sed 's/^[[^.]]*[[.]][[^.]]*[[.]]\([[0-9]][[0-9]]*\)$/\1/g'` + + if test :$GC_VERSION_MAJOR: = :: \ + -o :$GC_VERSION_MINOR: = :: \ + -o :$GC_VERSION_MICRO: = :: ; + then + AC_MSG_RESULT(invalid) + AC_MSG_ERROR([nonconforming PACKAGE_VERSION='$PACKAGE_VERSION']) + fi + + AC_DEFINE_UNQUOTED([GC_VERSION_MAJOR], $GC_VERSION_MAJOR, + [The major version number of this GC release.]) + AC_DEFINE_UNQUOTED([GC_VERSION_MINOR], $GC_VERSION_MINOR, + [The minor version number of this GC release.]) + AC_DEFINE_UNQUOTED([GC_VERSION_MICRO], $GC_VERSION_MICRO, + [The micro version number of this GC release.]) + AC_MSG_RESULT(major=$GC_VERSION_MAJOR minor=$GC_VERSION_MINOR \ + micro=$GC_VERSION_MICRO) +]) + +sinclude(libtool.m4) diff --git a/src/bdwgc/mach_dep.c b/src/bdwgc/mach_dep.c index 29e0b8a72..14b4c9dbe 100644 --- a/src/bdwgc/mach_dep.c +++ b/src/bdwgc/mach_dep.c @@ -34,11 +34,15 @@ }; typedef struct ppc_registers ppc_registers; - asm static void getRegisters(register ppc_registers* regs) - { +# if defined(CPPCHECK) + void getRegisters(ppc_registers* regs); +# else + asm static void getRegisters(register ppc_registers* regs) + { stmw r13,regs->gprs /* save R13-R31 */ blr - } + } +# endif static void PushMacRegisters(void) { @@ -158,7 +162,7 @@ # elif defined(MACOS) -# if defined(M68K) && defined(THINK_C) +# if defined(M68K) && defined(THINK_C) && !defined(CPPCHECK) # define PushMacReg(reg) \ move.l reg,(sp) \ jsr GC_push_one @@ -217,18 +221,21 @@ /* Ensure that either registers are pushed, or callee-save registers */ /* are somewhere on the stack, and then call fn(arg, ctxt). */ /* ctxt is either a pointer to a ucontext_t we generated, or NULL. */ +GC_ATTR_NO_SANITIZE_ADDR GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), - ptr_t arg) + volatile ptr_t arg) { - volatile int dummy; - void * context = 0; + volatile int dummy; + void * volatile context = 0; -# if defined(HAVE_PUSH_REGS) - GC_push_regs(); -# elif defined(UNIX_LIKE) && !defined(NO_GETCONTEXT) - /* Older versions of Darwin seem to lack getcontext(). */ - /* ARM and MIPS Linux often doesn't support a real */ - /* getcontext(). */ +# if defined(HAVE_PUSH_REGS) + GC_push_regs(); +# else +# if defined(UNIX_LIKE) && !defined(NO_GETCONTEXT) + /* Older versions of Darwin seem to lack getcontext(). */ + /* ARM and MIPS Linux often doesn't support a real */ + /* getcontext(). */ + static signed char getcontext_works = 0; /* (-1) - broken, 1 - works */ ucontext_t ctxt; # ifdef GETCONTEXT_FPU_EXCMASK_BUG /* Workaround a bug (clearing the FPU exception mask) in */ @@ -237,13 +244,28 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), /* We manipulate FPU control word here just not to force the */ /* client application to use -lm linker option. */ unsigned short old_fcw; + +# if defined(CPPCHECK) + GC_noop1((word)&old_fcw); +# endif __asm__ __volatile__ ("fstcw %0" : "=m" (*&old_fcw)); # else int except_mask = fegetexcept(); # endif # endif - if (getcontext(&ctxt) < 0) - ABORT ("getcontext failed: Use another register retrieval method?"); + + if (getcontext_works >= 0) { + if (getcontext(&ctxt) < 0) { + WARN("getcontext failed:" + " using another register retrieval method...\n", 0); + /* getcontext() is broken, do not try again. */ + /* E.g., to workaround a bug in Docker ubuntu_32bit. */ + } else { + context = &ctxt; + } + if (EXPECT(0 == getcontext_works, FALSE)) + getcontext_works = context != NULL ? 1 : -1; + } # ifdef GETCONTEXT_FPU_EXCMASK_BUG # ifdef X86_64 __asm__ __volatile__ ("fldcw %0" : : "m" (*&old_fcw)); @@ -259,28 +281,29 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), if (feenableexcept(except_mask) < 0) ABORT("feenableexcept failed"); # endif -# endif - context = &ctxt; +# endif /* GETCONTEXT_FPU_EXCMASK_BUG */ # if defined(SPARC) || defined(IA64) /* On a register window machine, we need to save register */ /* contents on the stack for this to work. This may already be */ /* subsumed by the getcontext() call. */ GC_save_regs_ret_val = GC_save_regs_in_stack(); -# endif /* register windows. */ -# elif defined(HAVE_BUILTIN_UNWIND_INIT) - /* This was suggested by Richard Henderson as the way to */ - /* force callee-save registers and register windows onto */ - /* the stack. */ - __builtin_unwind_init(); -# else /* !HAVE_BUILTIN_UNWIND_INIT && !UNIX_LIKE */ - /* && !HAVE_PUSH_REGS */ +# endif + if (NULL == context) /* getcontext failed */ +# endif /* !NO_GETCONTEXT */ + { +# if defined(HAVE_BUILTIN_UNWIND_INIT) + /* This was suggested by Richard Henderson as the way to */ + /* force callee-save registers and register windows onto */ + /* the stack. */ + __builtin_unwind_init(); +# else /* Generic code */ /* The idea is due to Parag Patel at HP. */ /* We're not sure whether he would like */ /* to be acknowledged for it or not. */ jmp_buf regs; - register word * i = (word *) regs; - register ptr_t lim = (ptr_t)(regs) + (sizeof regs); + register word * i = (word *) ®s; + register ptr_t lim = (ptr_t)(®s) + (sizeof regs); /* Setjmp doesn't always clear all of the buffer. */ /* That tends to preserve garbage. Clear it. */ @@ -297,14 +320,16 @@ GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), /* SUSV3, setjmp() may or may not save signal mask. */ /* _setjmp won't, but is less portable. */ # endif -# endif /* !HAVE_PUSH_REGS ... */ - /* FIXME: context here is sometimes just zero. At the moment the */ - /* callees don't really need it. */ - fn(arg, context); - /* Strongly discourage the compiler from treating the above */ - /* as a tail-call, since that would pop the register */ - /* contents before we get a chance to look at them. */ - GC_noop1((word)(&dummy)); +# endif /* !HAVE_BUILTIN_UNWIND_INIT */ + } +# endif /* !HAVE_PUSH_REGS */ + /* FIXME: context here is sometimes just zero. At the moment the */ + /* callees don't really need it. */ + fn(arg, context); + /* Strongly discourage the compiler from treating the above */ + /* as a tail-call, since that would pop the register */ + /* contents before we get a chance to look at them. */ + GC_noop1((word)(&dummy)); } #if defined(ASM_CLEAR_CODE) diff --git a/src/bdwgc/malloc.c b/src/bdwgc/malloc.c index a4dd437f4..502b3e3b0 100644 --- a/src/bdwgc/malloc.c +++ b/src/bdwgc/malloc.c @@ -14,6 +14,7 @@ */ #include "private/gc_priv.h" +#include "gc_inline.h" /* for GC_malloc_kind */ #include #include @@ -37,7 +38,6 @@ GC_INNER GC_bool GC_collect_or_expand(word needed_blocks, /* Allocate a large block of size lb bytes. */ /* The block is not cleared. */ /* Flags is 0 or IGNORE_OFF_PAGE. */ -/* We hold the allocation lock. */ /* EXTRA_BYTES were already added to lb. */ GC_INNER ptr_t GC_alloc_large(size_t lb, int k, unsigned flags) { @@ -46,9 +46,15 @@ GC_INNER ptr_t GC_alloc_large(size_t lb, int k, unsigned flags) ptr_t result; GC_bool retry = FALSE; + GC_ASSERT(I_HOLD_LOCK()); lb = ROUNDUP_GRANULE_SIZE(lb); - n_blocks = OBJ_SZ_TO_BLOCKS(lb); - if (!EXPECT(GC_is_initialized, TRUE)) GC_init(); + n_blocks = OBJ_SZ_TO_BLOCKS_CHECKED(lb); + if (!EXPECT(GC_is_initialized, TRUE)) { + DCL_LOCK_STATE; + UNLOCK(); /* just to unset GC_lock_holder */ + GC_init(); + LOCK(); + } /* Do our share of marking work */ if (GC_incremental && !GC_dont_gc) GC_collect_a_little_inner((int)n_blocks); @@ -79,15 +85,17 @@ GC_INNER ptr_t GC_alloc_large(size_t lb, int k, unsigned flags) } /* Allocate a large block of size lb bytes. Clear if appropriate. */ -/* We hold the allocation lock. */ /* EXTRA_BYTES were already added to lb. */ STATIC ptr_t GC_alloc_large_and_clear(size_t lb, int k, unsigned flags) { - ptr_t result = GC_alloc_large(lb, k, flags); - word n_blocks = OBJ_SZ_TO_BLOCKS(lb); + ptr_t result; + + GC_ASSERT(I_HOLD_LOCK()); + result = GC_alloc_large(lb, k, flags); + if (result != NULL + && (GC_debugging_started || GC_obj_kinds[k].ok_init)) { + word n_blocks = OBJ_SZ_TO_BLOCKS(lb); - if (0 == result) return 0; - if (GC_debugging_started || GC_obj_kinds[k].ok_init) { /* Clear the whole block, in case of GC_realloc call. */ BZERO(result, n_blocks * HBLKSIZE); } @@ -98,13 +106,13 @@ STATIC ptr_t GC_alloc_large_and_clear(size_t lb, int k, unsigned flags) /* Should not be used to directly to allocate */ /* objects such as STUBBORN objects that */ /* require special handling on allocation. */ -/* First a version that assumes we already */ -/* hold lock: */ GC_INNER void * GC_generic_malloc_inner(size_t lb, int k) { void *op; - if(SMALL_OBJ(lb)) { + GC_ASSERT(I_HOLD_LOCK()); + GC_ASSERT(k < MAXOBJKINDS); + if (SMALL_OBJ(lb)) { struct obj_kind * kind = GC_obj_kinds + k; size_t lg = GC_size_map[lb]; void ** opp = &(kind -> ok_freelist[lg]); @@ -113,7 +121,10 @@ GC_INNER void * GC_generic_malloc_inner(size_t lb, int k) if (EXPECT(0 == op, FALSE)) { if (lg == 0) { if (!EXPECT(GC_is_initialized, TRUE)) { + DCL_LOCK_STATE; + UNLOCK(); /* just to unset GC_lock_holder */ GC_init(); + LOCK(); lg = GC_size_map[lb]; } if (0 == lg) { @@ -136,35 +147,45 @@ GC_INNER void * GC_generic_malloc_inner(size_t lb, int k) } *opp = obj_link(op); obj_link(op) = 0; - GC_bytes_allocd += GRANULES_TO_BYTES(lg); + GC_bytes_allocd += GRANULES_TO_BYTES((word)lg); } else { op = (ptr_t)GC_alloc_large_and_clear(ADD_SLOP(lb), k, 0); - GC_bytes_allocd += lb; + if (op != NULL) + GC_bytes_allocd += lb; } return op; } -/* Allocate a composite object of size n bytes. The caller guarantees */ -/* that pointers past the first page are not relevant. Caller holds */ -/* allocation lock. */ -GC_INNER void * GC_generic_malloc_inner_ignore_off_page(size_t lb, int k) -{ +#if defined(DBG_HDRS_ALL) || defined(GC_GCJ_SUPPORT) \ + || !defined(GC_NO_FINALIZATION) + /* Allocate a composite object of size n bytes. The caller */ + /* guarantees that pointers past the first page are not relevant. */ + GC_INNER void * GC_generic_malloc_inner_ignore_off_page(size_t lb, int k) + { word lb_adjusted; void * op; + GC_ASSERT(I_HOLD_LOCK()); if (lb <= HBLKSIZE) - return(GC_generic_malloc_inner(lb, k)); + return GC_generic_malloc_inner(lb, k); + GC_ASSERT(k < MAXOBJKINDS); lb_adjusted = ADD_SLOP(lb); op = GC_alloc_large_and_clear(lb_adjusted, k, IGNORE_OFF_PAGE); - GC_bytes_allocd += lb_adjusted; + if (op != NULL) + GC_bytes_allocd += lb_adjusted; return op; -} + } +#endif #ifdef GC_COLLECT_AT_MALLOC /* Parameter to force GC at every malloc of size greater or equal to */ /* the given value. This might be handy during debugging. */ - size_t GC_dbg_collect_at_malloc_min_lb = (GC_COLLECT_AT_MALLOC); +# if defined(CPPCHECK) + size_t GC_dbg_collect_at_malloc_min_lb = 16*1024; /* e.g. */ +# else + size_t GC_dbg_collect_at_malloc_min_lb = (GC_COLLECT_AT_MALLOC); +# endif #endif GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_malloc(size_t lb, int k) @@ -172,6 +193,7 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_malloc(size_t lb, int k) void * result; DCL_LOCK_STATE; + GC_ASSERT(k < MAXOBJKINDS); if (EXPECT(GC_have_errors, FALSE)) GC_print_all_errors(); GC_INVOKE_FINALIZERS(); @@ -188,8 +210,6 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_malloc(size_t lb, int k) lg = ROUNDED_UP_GRANULES(lb); lb_rounded = GRANULES_TO_BYTES(lg); - if (lb_rounded < lb) - return((*GC_get_oom_fn())(lb)); n_blocks = OBJ_SZ_TO_BLOCKS(lb_rounded); init = GC_obj_kinds[k].ok_init; LOCK(); @@ -207,8 +227,8 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_malloc(size_t lb, int k) ((word *)result)[GRANULES_TO_WORDS(lg)-2] = 0; # endif } + GC_bytes_allocd += lb_rounded; } - GC_bytes_allocd += lb_rounded; UNLOCK(); if (init && !GC_debugging_started && 0 != result) { BZERO(result, n_blocks * HBLKSIZE); @@ -221,105 +241,99 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_malloc(size_t lb, int k) } } -/* Allocate lb bytes of atomic (pointer-free) data. */ -#ifdef THREAD_LOCAL_ALLOC - GC_INNER void * GC_core_malloc_atomic(size_t lb) -#else - GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_atomic(size_t lb) -#endif +GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_kind_global(size_t lb, int k) { - void *op; - size_t lg; - DCL_LOCK_STATE; - - if(SMALL_OBJ(lb)) { - GC_DBG_COLLECT_AT_MALLOC(lb); - lg = GC_size_map[lb]; - LOCK(); - op = GC_aobjfreelist[lg]; - if (EXPECT(0 == op, FALSE)) { - UNLOCK(); - return(GENERAL_MALLOC((word)lb, PTRFREE)); - } - GC_aobjfreelist[lg] = obj_link(op); - GC_bytes_allocd += GRANULES_TO_BYTES(lg); - UNLOCK(); - return((void *) op); - } else { - return(GENERAL_MALLOC((word)lb, PTRFREE)); - } -} - -/* Allocate lb bytes of composite (pointerful) data */ -#ifdef THREAD_LOCAL_ALLOC - GC_INNER void * GC_core_malloc(size_t lb) -#else - GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc(size_t lb) -#endif -{ - void *op; - size_t lg; - DCL_LOCK_STATE; - - if(SMALL_OBJ(lb)) { - GC_DBG_COLLECT_AT_MALLOC(lb); - lg = GC_size_map[lb]; - LOCK(); - op = GC_objfreelist[lg]; - if (EXPECT(0 == op, FALSE)) { - UNLOCK(); - return (GENERAL_MALLOC((word)lb, NORMAL)); - } - GC_ASSERT(0 == obj_link(op) - || ((word)obj_link(op) - <= (word)GC_greatest_plausible_heap_addr - && (word)obj_link(op) - >= (word)GC_least_plausible_heap_addr)); - GC_objfreelist[lg] = obj_link(op); - obj_link(op) = 0; - GC_bytes_allocd += GRANULES_TO_BYTES(lg); - UNLOCK(); - return op; - } else { - return(GENERAL_MALLOC(lb, NORMAL)); - } -} - -/* Allocate lb bytes of pointerful, traced, but not collectible data. */ -GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_uncollectable(size_t lb) -{ - void *op; - size_t lg; - DCL_LOCK_STATE; - + GC_ASSERT(k < MAXOBJKINDS); if (SMALL_OBJ(lb)) { + void *op; + void **opp; + size_t lg = GC_size_map[lb]; + DCL_LOCK_STATE; + + GC_DBG_COLLECT_AT_MALLOC(lb); + LOCK(); + opp = &GC_obj_kinds[k].ok_freelist[lg]; + op = *opp; + if (EXPECT(op != NULL, TRUE)) { + if (k == PTRFREE) { + *opp = obj_link(op); + } else { + GC_ASSERT(0 == obj_link(op) + || ((word)obj_link(op) + <= (word)GC_greatest_plausible_heap_addr + && (word)obj_link(op) + >= (word)GC_least_plausible_heap_addr)); + *opp = obj_link(op); + obj_link(op) = 0; + } + GC_bytes_allocd += GRANULES_TO_BYTES((word)lg); + UNLOCK(); + return op; + } + UNLOCK(); + } + return GENERAL_MALLOC(lb, k); +} + +#if defined(THREADS) && !defined(THREAD_LOCAL_ALLOC) + GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_kind(size_t lb, int k) + { + return GC_malloc_kind_global(lb, k); + } +#endif + +/* Allocate lb bytes of atomic (pointer-free) data. */ +GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_atomic(size_t lb) +{ + return GC_malloc_kind(lb, PTRFREE); +} + +/* Allocate lb bytes of composite (pointerful) data. */ +GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc(size_t lb) +{ + return GC_malloc_kind(lb, NORMAL); +} + +GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_malloc_uncollectable( + size_t lb, int k) +{ + void *op; + DCL_LOCK_STATE; + + GC_ASSERT(k < MAXOBJKINDS); + if (SMALL_OBJ(lb)) { + void **opp; + size_t lg; + GC_DBG_COLLECT_AT_MALLOC(lb); if (EXTRA_BYTES != 0 && lb != 0) lb--; /* We don't need the extra byte, since this won't be */ /* collected anyway. */ lg = GC_size_map[lb]; LOCK(); - op = GC_uobjfreelist[lg]; - if (EXPECT(op != 0, TRUE)) { - GC_uobjfreelist[lg] = obj_link(op); + opp = &GC_obj_kinds[k].ok_freelist[lg]; + op = *opp; + if (EXPECT(op != NULL, TRUE)) { + *opp = obj_link(op); obj_link(op) = 0; - GC_bytes_allocd += GRANULES_TO_BYTES(lg); - /* Mark bit ws already set on free list. It will be */ + GC_bytes_allocd += GRANULES_TO_BYTES((word)lg); + /* Mark bit was already set on free list. It will be */ /* cleared only temporarily during a collection, as a */ /* result of the normal free list mark bit clearing. */ - GC_non_gc_bytes += GRANULES_TO_BYTES(lg); + GC_non_gc_bytes += GRANULES_TO_BYTES((word)lg); UNLOCK(); } else { UNLOCK(); - op = GC_generic_malloc(lb, UNCOLLECTABLE); + op = GC_generic_malloc(lb, k); /* For small objects, the free lists are completely marked. */ } GC_ASSERT(0 == op || GC_is_marked(op)); } else { hdr * hhdr; - op = GC_generic_malloc(lb, UNCOLLECTABLE); - if (0 == op) return(0); + op = GC_generic_malloc(lb, k); + if (NULL == op) + return NULL; GC_ASSERT(((word)op & (HBLKSIZE - 1)) == 0); /* large block */ hhdr = HDR(op); @@ -339,132 +353,150 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_uncollectable(size_t lb) return op; } -#ifdef REDIRECT_MALLOC +/* Allocate lb bytes of pointerful, traced, but not collectible data. */ +GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_uncollectable(size_t lb) +{ + return GC_generic_malloc_uncollectable(lb, UNCOLLECTABLE); +} + +#ifdef GC_ATOMIC_UNCOLLECTABLE + /* Allocate lb bytes of pointer-free, untraced, uncollectible data */ + /* This is normally roughly equivalent to the system malloc. */ + /* But it may be useful if malloc is redefined. */ + GC_API GC_ATTR_MALLOC void * GC_CALL + GC_malloc_atomic_uncollectable(size_t lb) + { + return GC_generic_malloc_uncollectable(lb, AUNCOLLECTABLE); + } +#endif /* GC_ATOMIC_UNCOLLECTABLE */ + +#if defined(REDIRECT_MALLOC) && !defined(REDIRECT_MALLOC_IN_HEADER) # ifndef MSWINCE # include # endif -/* Avoid unnecessary nested procedure calls here, by #defining some */ -/* malloc replacements. Otherwise we end up saving a */ -/* meaningless return address in the object. It also speeds things up, */ -/* but it is admittedly quite ugly. */ + /* Avoid unnecessary nested procedure calls here, by #defining some */ + /* malloc replacements. Otherwise we end up saving a meaningless */ + /* return address in the object. It also speeds things up, but it is */ + /* admittedly quite ugly. */ # define GC_debug_malloc_replacement(lb) GC_debug_malloc(lb, GC_DBG_EXTRAS) -void * malloc(size_t lb) -{ +# if defined(CPPCHECK) +# define REDIRECT_MALLOC_F GC_malloc /* e.g. */ +# else +# define REDIRECT_MALLOC_F REDIRECT_MALLOC +# endif + + void * malloc(size_t lb) + { /* It might help to manually inline the GC_malloc call here. */ /* But any decent compiler should reduce the extra procedure call */ /* to at most a jump instruction in this case. */ # if defined(I386) && defined(GC_SOLARIS_THREADS) - /* Thread initialization can call malloc before we're ready for. */ - /* It's not clear that this is enough to help matters. */ + /* Thread initialization can call malloc before we are ready for. */ + /* It is not clear that this is enough to help matters. */ /* The thread implementation may well call malloc at other */ /* inopportune times. */ if (!EXPECT(GC_is_initialized, TRUE)) return sbrk(lb); -# endif /* I386 && GC_SOLARIS_THREADS */ - return((void *)REDIRECT_MALLOC(lb)); -} - -#if defined(GC_LINUX_THREADS) /* && !defined(USE_PROC_FOR_LIBRARIES) */ - STATIC ptr_t GC_libpthread_start = 0; - STATIC ptr_t GC_libpthread_end = 0; - STATIC ptr_t GC_libld_start = 0; - STATIC ptr_t GC_libld_end = 0; - - STATIC void GC_init_lib_bounds(void) - { - if (GC_libpthread_start != 0) return; - GC_init(); /* if not called yet */ - if (!GC_text_mapping("libpthread-", - &GC_libpthread_start, &GC_libpthread_end)) { - WARN("Failed to find libpthread.so text mapping: Expect crash\n", 0); - /* This might still work with some versions of libpthread, */ - /* so we don't abort. Perhaps we should. */ - /* Generate message only once: */ - GC_libpthread_start = (ptr_t)1; - } - if (!GC_text_mapping("ld-", &GC_libld_start, &GC_libld_end)) { - WARN("Failed to find ld.so text mapping: Expect crash\n", 0); - } +# endif + return (void *)REDIRECT_MALLOC_F(lb); } -#endif /* GC_LINUX_THREADS */ -#include -#ifdef SIZE_MAX -# define GC_SIZE_MAX SIZE_MAX -#else -# define GC_SIZE_MAX (~(size_t)0) -#endif +# if defined(GC_LINUX_THREADS) + STATIC ptr_t GC_libpthread_start = 0; + STATIC ptr_t GC_libpthread_end = 0; + STATIC ptr_t GC_libld_start = 0; + STATIC ptr_t GC_libld_end = 0; -#define GC_SQRT_SIZE_MAX ((1U << (WORDSZ / 2)) - 1) + STATIC void GC_init_lib_bounds(void) + { + IF_CANCEL(int cancel_state;) -void * calloc(size_t n, size_t lb) -{ + if (GC_libpthread_start != 0) return; + DISABLE_CANCEL(cancel_state); + GC_init(); /* if not called yet */ + if (!GC_text_mapping("libpthread-", + &GC_libpthread_start, &GC_libpthread_end)) { + WARN("Failed to find libpthread.so text mapping: Expect crash\n", 0); + /* This might still work with some versions of libpthread, */ + /* so we don't abort. Perhaps we should. */ + /* Generate message only once: */ + GC_libpthread_start = (ptr_t)1; + } + if (!GC_text_mapping("ld-", &GC_libld_start, &GC_libld_end)) { + WARN("Failed to find ld.so text mapping: Expect crash\n", 0); + } + RESTORE_CANCEL(cancel_state); + } +# endif /* GC_LINUX_THREADS */ + + void * calloc(size_t n, size_t lb) + { if ((lb | n) > GC_SQRT_SIZE_MAX /* fast initial test */ && lb && n > GC_SIZE_MAX / lb) - return NULL; -# if defined(GC_LINUX_THREADS) /* && !defined(USE_PROC_FOR_LIBRARIES) */ - /* libpthread allocated some memory that is only pointed to by */ - /* mmapped thread stacks. Make sure it is not collectible. */ - { - static GC_bool lib_bounds_set = FALSE; - ptr_t caller = (ptr_t)__builtin_return_address(0); - /* This test does not need to ensure memory visibility, since */ - /* the bounds will be set when/if we create another thread. */ - if (!EXPECT(lib_bounds_set, TRUE)) { - GC_init_lib_bounds(); - lib_bounds_set = TRUE; - } - if (((word)caller >= (word)GC_libpthread_start - && (word)caller < (word)GC_libpthread_end) - || ((word)caller >= (word)GC_libld_start - && (word)caller < (word)GC_libld_end)) - return GC_malloc_uncollectable(n*lb); - /* The two ranges are actually usually adjacent, so there may */ - /* be a way to speed this up. */ + return (*GC_get_oom_fn())(GC_SIZE_MAX); /* n*lb overflow */ +# if defined(GC_LINUX_THREADS) + /* libpthread allocated some memory that is only pointed to by */ + /* mmapped thread stacks. Make sure it is not collectible. */ + { + static GC_bool lib_bounds_set = FALSE; + ptr_t caller = (ptr_t)__builtin_return_address(0); + /* This test does not need to ensure memory visibility, since */ + /* the bounds will be set when/if we create another thread. */ + if (!EXPECT(lib_bounds_set, TRUE)) { + GC_init_lib_bounds(); + lib_bounds_set = TRUE; } + if (((word)caller >= (word)GC_libpthread_start + && (word)caller < (word)GC_libpthread_end) + || ((word)caller >= (word)GC_libld_start + && (word)caller < (word)GC_libld_end)) + return GC_generic_malloc_uncollectable(n * lb, UNCOLLECTABLE); + /* The two ranges are actually usually adjacent, so there may */ + /* be a way to speed this up. */ + } # endif - return((void *)REDIRECT_MALLOC(n*lb)); -} - -#ifndef strdup - char *strdup(const char *s) - { - size_t lb = strlen(s) + 1; - char *result = (char *)REDIRECT_MALLOC(lb); - if (result == 0) { - errno = ENOMEM; - return 0; - } - BCOPY(s, result, lb); - return result; + return (void *)REDIRECT_MALLOC_F(n * lb); } -#endif /* !defined(strdup) */ + +# ifndef strdup + char *strdup(const char *s) + { + size_t lb = strlen(s) + 1; + char *result = (char *)REDIRECT_MALLOC_F(lb); + if (result == 0) { + errno = ENOMEM; + return 0; + } + BCOPY(s, result, lb); + return result; + } +# endif /* !defined(strdup) */ /* If strdup is macro defined, we assume that it actually calls malloc, */ /* and thus the right thing will happen even without overriding it. */ /* This seems to be true on most Linux systems. */ -#ifndef strndup - /* This is similar to strdup(). */ - char *strndup(const char *str, size_t size) - { - char *copy; - size_t len = strlen(str); - if (len > size) - len = size; - copy = (char *)REDIRECT_MALLOC(len + 1); - if (copy == NULL) { - errno = ENOMEM; - return NULL; +# ifndef strndup + /* This is similar to strdup(). */ + char *strndup(const char *str, size_t size) + { + char *copy; + size_t len = strlen(str); + if (len > size) + len = size; + copy = (char *)REDIRECT_MALLOC_F(len + 1); + if (copy == NULL) { + errno = ENOMEM; + return NULL; + } + BCOPY(str, copy, len); + copy[len] = '\0'; + return copy; } - BCOPY(str, copy, len); - copy[len] = '\0'; - return copy; - } -#endif /* !strndup */ +# endif /* !strndup */ -#undef GC_debug_malloc_replacement +# undef GC_debug_malloc_replacement #endif /* REDIRECT_MALLOC */ @@ -475,7 +507,6 @@ GC_API void GC_CALL GC_free(void * p) hdr *hhdr; size_t sz; /* In bytes */ size_t ngranules; /* sz in granules */ - void **flh; int knd; struct obj_kind * ok; DCL_LOCK_STATE; @@ -489,8 +520,11 @@ GC_API void GC_CALL GC_free(void * p) h = HBLKPTR(p); hhdr = HDR(h); # if defined(REDIRECT_MALLOC) && \ - (defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \ + ((defined(NEED_CALLINFO) && defined(GC_HAVE_BUILTIN_BACKTRACE)) \ + || defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \ || defined(MSWIN32)) + /* This might be called indirectly by GC_print_callers to free */ + /* the result of backtrace_symbols. */ /* For Solaris, we have to redirect malloc calls during */ /* initialization. For the others, this seems to happen */ /* implicitly. */ @@ -503,6 +537,8 @@ GC_API void GC_CALL GC_free(void * p) knd = hhdr -> hb_obj_kind; ok = &GC_obj_kinds[knd]; if (EXPECT(ngranules <= MAXOBJGRANULES, TRUE)) { + void **flh; + LOCK(); GC_bytes_freed += sz; if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz; @@ -518,6 +554,7 @@ GC_API void GC_CALL GC_free(void * p) UNLOCK(); } else { size_t nblocks = OBJ_SZ_TO_BLOCKS(sz); + LOCK(); GC_bytes_freed += sz; if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz; @@ -539,7 +576,6 @@ GC_API void GC_CALL GC_free(void * p) hdr *hhdr; size_t sz; /* bytes */ size_t ngranules; /* sz in granules */ - void ** flh; int knd; struct obj_kind * ok; @@ -550,6 +586,8 @@ GC_API void GC_CALL GC_free(void * p) ngranules = BYTES_TO_GRANULES(sz); ok = &GC_obj_kinds[knd]; if (ngranules <= MAXOBJGRANULES) { + void ** flh; + GC_bytes_freed += sz; if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz; if (ok -> ok_init) { @@ -574,28 +612,33 @@ GC_API void GC_CALL GC_free(void * p) # define REDIRECT_FREE GC_free #endif -#ifdef REDIRECT_FREE +#if defined(REDIRECT_FREE) && !defined(REDIRECT_MALLOC_IN_HEADER) + +# if defined(CPPCHECK) +# define REDIRECT_FREE_F GC_free /* e.g. */ +# else +# define REDIRECT_FREE_F REDIRECT_FREE +# endif + void free(void * p) { -# if defined(GC_LINUX_THREADS) && !defined(USE_PROC_FOR_LIBRARIES) - { - /* Don't bother with initialization checks. If nothing */ - /* has been initialized, the check fails, and that's safe, */ - /* since we have not allocated uncollectible objects neither. */ - ptr_t caller = (ptr_t)__builtin_return_address(0); - /* This test does not need to ensure memory visibility, since */ - /* the bounds will be set when/if we create another thread. */ - if (((word)caller >= (word)GC_libpthread_start - && (word)caller < (word)GC_libpthread_end) - || ((word)caller >= (word)GC_libld_start - && (word)caller < (word)GC_libld_end)) { - GC_free(p); - return; - } - } -# endif # ifndef IGNORE_FREE - REDIRECT_FREE(p); +# if defined(GC_LINUX_THREADS) && !defined(USE_PROC_FOR_LIBRARIES) + /* Don't bother with initialization checks. If nothing */ + /* has been initialized, the check fails, and that's safe, */ + /* since we have not allocated uncollectible objects neither. */ + ptr_t caller = (ptr_t)__builtin_return_address(0); + /* This test does not need to ensure memory visibility, since */ + /* the bounds will be set when/if we create another thread. */ + if (((word)caller >= (word)GC_libpthread_start + && (word)caller < (word)GC_libpthread_end) + || ((word)caller >= (word)GC_libld_start + && (word)caller < (word)GC_libld_end)) { + GC_free(p); + return; + } +# endif + REDIRECT_FREE_F(p); # endif } #endif /* REDIRECT_FREE */ diff --git a/src/bdwgc/mallocx.c b/src/bdwgc/mallocx.c index c8895a1f2..fc5c963cd 100644 --- a/src/bdwgc/mallocx.c +++ b/src/bdwgc/mallocx.c @@ -15,6 +15,7 @@ */ #include "private/gc_priv.h" +#include "gc_inline.h" /* for GC_malloc_kind */ /* * These are extra allocation routines which are likely to be less @@ -42,7 +43,7 @@ void ** const GC_objfreelist_ptr = GC_objfreelist; void ** const GC_aobjfreelist_ptr = GC_aobjfreelist; void ** const GC_uobjfreelist_ptr = GC_uobjfreelist; -# ifdef ATOMIC_UNCOLLECTABLE +# ifdef GC_ATOMIC_UNCOLLECTABLE void ** const GC_auobjfreelist_ptr = GC_auobjfreelist; # endif @@ -65,15 +66,13 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_or_special_malloc(size_t lb, return GC_malloc_stubborn(lb); # endif case PTRFREE: - return GC_malloc_atomic(lb); case NORMAL: - return GC_malloc(lb); + return GC_malloc_kind(lb, knd); case UNCOLLECTABLE: - return GC_malloc_uncollectable(lb); -# ifdef ATOMIC_UNCOLLECTABLE +# ifdef GC_ATOMIC_UNCOLLECTABLE case AUNCOLLECTABLE: - return GC_malloc_atomic_uncollectable(lb); -# endif /* ATOMIC_UNCOLLECTABLE */ +# endif + return GC_generic_malloc_uncollectable(lb, knd); default: return GC_generic_malloc(lb, knd); } @@ -87,11 +86,18 @@ GC_API void * GC_CALL GC_realloc(void * p, size_t lb) { struct hblk * h; hdr * hhdr; - size_t sz; /* Current size in bytes */ - size_t orig_sz; /* Original sz in bytes */ + void * result; + size_t sz; /* Current size in bytes */ + size_t orig_sz; /* Original sz in bytes */ int obj_kind; if (p == 0) return(GC_malloc(lb)); /* Required by ANSI */ + if (0 == lb) /* and p != NULL */ { +# ifndef IGNORE_FREE + GC_free(p); +# endif + return NULL; + } h = HBLKPTR(p); hhdr = HDR(h); sz = hhdr -> hb_sz; @@ -128,31 +134,20 @@ GC_API void * GC_CALL GC_realloc(void * p, size_t lb) BZERO(((ptr_t)p) + lb, orig_sz - lb); } return(p); - } else { - /* shrink */ - void * result = - GC_generic_or_special_malloc((word)lb, obj_kind); - - if (result == 0) return(0); - /* Could also return original object. But this */ - /* gives the client warning of imminent disaster. */ - BCOPY(p, result, lb); -# ifndef IGNORE_FREE - GC_free(p); -# endif - return(result); } - } else { - /* grow */ - void * result = GC_generic_or_special_malloc((word)lb, obj_kind); - - if (result == 0) return(0); - BCOPY(p, result, sz); -# ifndef IGNORE_FREE - GC_free(p); -# endif - return(result); + /* shrink */ + sz = lb; } + result = GC_generic_or_special_malloc((word)lb, obj_kind); + if (result != NULL) { + /* In case of shrink, it could also return original object. */ + /* But this gives the client warning of imminent disaster. */ + BCOPY(p, result, sz); +# ifndef IGNORE_FREE + GC_free(p); +# endif + } + return result; } # if defined(REDIRECT_MALLOC) && !defined(REDIRECT_REALLOC) @@ -165,10 +160,12 @@ GC_API void * GC_CALL GC_realloc(void * p, size_t lb) # define GC_debug_realloc_replacement(p, lb) \ GC_debug_realloc(p, lb, GC_DBG_EXTRAS) -void * realloc(void * p, size_t lb) - { - return(REDIRECT_REALLOC(p, lb)); - } +# if !defined(REDIRECT_MALLOC_IN_HEADER) + void * realloc(void * p, size_t lb) + { + return(REDIRECT_REALLOC(p, lb)); + } +# endif # undef GC_debug_realloc_replacement # endif /* REDIRECT_REALLOC */ @@ -188,10 +185,9 @@ GC_API GC_ATTR_MALLOC void * GC_CALL if (SMALL_OBJ(lb)) return GC_generic_malloc(lb, k); + GC_ASSERT(k < MAXOBJKINDS); lg = ROUNDED_UP_GRANULES(lb); lb_rounded = GRANULES_TO_BYTES(lg); - if (lb_rounded < lb) - return((*GC_get_oom_fn())(lb)); n_blocks = OBJ_SZ_TO_BLOCKS(lb_rounded); init = GC_obj_kinds[k].ok_init; if (EXPECT(GC_have_errors, FALSE)) @@ -200,32 +196,30 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_DBG_COLLECT_AT_MALLOC(lb); LOCK(); result = (ptr_t)GC_alloc_large(ADD_SLOP(lb), k, IGNORE_OFF_PAGE); - if (0 != result) { - if (GC_debugging_started) { - BZERO(result, n_blocks * HBLKSIZE); - } else { -# ifdef THREADS - /* Clear any memory that might be used for GC descriptors */ - /* before we release the lock. */ - ((word *)result)[0] = 0; - ((word *)result)[1] = 0; - ((word *)result)[GRANULES_TO_WORDS(lg)-1] = 0; - ((word *)result)[GRANULES_TO_WORDS(lg)-2] = 0; -# endif - } - } - GC_bytes_allocd += lb_rounded; - if (0 == result) { + if (NULL == result) { GC_oom_func oom_fn = GC_oom_fn; UNLOCK(); - return((*oom_fn)(lb)); - } else { - UNLOCK(); - if (init && !GC_debugging_started) { - BZERO(result, n_blocks * HBLKSIZE); - } - return(result); + return (*oom_fn)(lb); } + + if (GC_debugging_started) { + BZERO(result, n_blocks * HBLKSIZE); + } else { +# ifdef THREADS + /* Clear any memory that might be used for GC descriptors */ + /* before we release the lock. */ + ((word *)result)[0] = 0; + ((word *)result)[1] = 0; + ((word *)result)[GRANULES_TO_WORDS(lg)-1] = 0; + ((word *)result)[GRANULES_TO_WORDS(lg)-2] = 0; +# endif + } + GC_bytes_allocd += lb_rounded; + UNLOCK(); + if (init && !GC_debugging_started) { + BZERO(result, n_blocks * HBLKSIZE); + } + return(result); } GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_ignore_off_page(size_t lb) @@ -292,21 +286,35 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t lb, int k, void **result) DCL_LOCK_STATE; GC_ASSERT(lb != 0 && (lb & (GRANULE_BYTES-1)) == 0); - if (!SMALL_OBJ(lb)) { + if (!SMALL_OBJ(lb) +# ifdef MANUAL_VDB + /* Currently a single object is allocated. */ + /* TODO: GC_dirty should be called for each linked object (but */ + /* the last one) to support multiple objects allocation. */ + || GC_incremental +# endif + ) { op = GC_generic_malloc(lb, k); if (EXPECT(0 != op, TRUE)) obj_link(op) = 0; *result = op; +# ifdef MANUAL_VDB + if (GC_is_heap_ptr(result)) { + GC_dirty(result); + REACHABLE_AFTER_DIRTY(op); + } +# endif return; } + GC_ASSERT(k < MAXOBJKINDS); lw = BYTES_TO_WORDS(lb); lg = BYTES_TO_GRANULES(lb); if (EXPECT(GC_have_errors, FALSE)) GC_print_all_errors(); GC_INVOKE_FINALIZERS(); GC_DBG_COLLECT_AT_MALLOC(lb); - LOCK(); if (!EXPECT(GC_is_initialized, TRUE)) GC_init(); + LOCK(); /* Do our share of marking work */ if (GC_incremental && !GC_dont_gc) { ENTER_GC(); @@ -449,15 +457,17 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_many(size_t lb) { void *result; - GC_generic_malloc_many(ROUNDUP_GRANULE_SIZE(lb + EXTRA_BYTES), - NORMAL, &result); + /* Add EXTRA_BYTES and round up to a multiple of a granule. */ + lb = SIZET_SAT_ADD(lb, EXTRA_BYTES + GRANULE_BYTES - 1) + & ~(GRANULE_BYTES - 1); + + GC_generic_malloc_many(lb, NORMAL, &result); return result; } -/* Not well tested nor integrated. */ -/* Debug version is tricky and currently missing. */ #include +/* Debug version is tricky and currently missing. */ GC_API GC_ATTR_MALLOC void * GC_CALL GC_memalign(size_t align, size_t lb) { size_t new_lb; @@ -474,7 +484,7 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_memalign(size_t align, size_t lb) } /* We could also try to make sure that the real rounded-up object size */ /* is a multiple of align. That would be correct up to HBLKSIZE. */ - new_lb = lb + align - 1; + new_lb = SIZET_SAT_ADD(lb, align - 1); result = GC_malloc(new_lb); /* It is OK not to check result for NULL as in that case */ /* GC_memalign returns NULL too since (0 + 0 % align) is 0. */ @@ -482,7 +492,8 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_memalign(size_t align, size_t lb) if (offset != 0) { offset = align - offset; if (!GC_all_interior_pointers) { - if (offset >= VALID_OFFSET_SZ) return GC_malloc(HBLKSIZE); + GC_STATIC_ASSERT(VALID_OFFSET_SZ <= HBLKSIZE); + GC_ASSERT(offset < VALID_OFFSET_SZ); GC_register_displacement(offset); } } @@ -495,7 +506,8 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_memalign(size_t align, size_t lb) GC_API int GC_CALL GC_posix_memalign(void **memptr, size_t align, size_t lb) { /* Check alignment properly. */ - if (((align - 1) & align) != 0 || align < sizeof(void *)) { + size_t align_minus_one = align - 1; /* to workaround a cppcheck warning */ + if (align < sizeof(void *) || (align_minus_one & align) != 0) { # ifdef MSWINCE return ERROR_INVALID_PARAMETER; # else @@ -513,59 +525,6 @@ GC_API int GC_CALL GC_posix_memalign(void **memptr, size_t align, size_t lb) return 0; } -#ifdef ATOMIC_UNCOLLECTABLE - /* Allocate lb bytes of pointer-free, untraced, uncollectible data */ - /* This is normally roughly equivalent to the system malloc. */ - /* But it may be useful if malloc is redefined. */ - GC_API GC_ATTR_MALLOC void * GC_CALL - GC_malloc_atomic_uncollectable(size_t lb) - { - void *op; - size_t lg; - DCL_LOCK_STATE; - - if (SMALL_OBJ(lb)) { - GC_DBG_COLLECT_AT_MALLOC(lb); - if (EXTRA_BYTES != 0 && lb != 0) lb--; - /* We don't need the extra byte, since this won't be */ - /* collected anyway. */ - lg = GC_size_map[lb]; - LOCK(); - op = GC_auobjfreelist[lg]; - if (EXPECT(op != 0, TRUE)) { - GC_auobjfreelist[lg] = obj_link(op); - obj_link(op) = 0; - GC_bytes_allocd += GRANULES_TO_BYTES(lg); - /* Mark bit was already set while object was on free list. */ - GC_non_gc_bytes += GRANULES_TO_BYTES(lg); - UNLOCK(); - } else { - UNLOCK(); - op = (ptr_t)GC_generic_malloc(lb, AUNCOLLECTABLE); - } - GC_ASSERT(0 == op || GC_is_marked(op)); - return((void *) op); - } else { - hdr * hhdr; - - op = (ptr_t)GC_generic_malloc(lb, AUNCOLLECTABLE); - if (0 == op) return(0); - - GC_ASSERT(((word)op & (HBLKSIZE - 1)) == 0); - hhdr = HDR(op); - - LOCK(); - set_mark_bit_from_hdr(hhdr, 0); /* Only object. */ -# ifndef THREADS - GC_ASSERT(hhdr -> hb_n_marks == 0); -# endif - hhdr -> hb_n_marks = 1; - UNLOCK(); - return((void *) op); - } - } -#endif /* ATOMIC_UNCOLLECTABLE */ - /* provide a version of strdup() that uses the collector to allocate the copy of the string */ GC_API GC_ATTR_MALLOC char * GC_CALL GC_strdup(const char *s) diff --git a/src/bdwgc/mark.c b/src/bdwgc/mark.c index 6e5948045..bf28a8ad2 100644 --- a/src/bdwgc/mark.c +++ b/src/bdwgc/mark.c @@ -14,6 +14,16 @@ * */ +#if defined(__MINGW32__) && !defined(__MINGW_EXCPT_DEFINE_PSDK) \ + && defined(__i386__) /* cannot use macros from gcconfig.h */ + /* Otherwise EXCEPTION_REGISTRATION type declaration from winnt.h */ + /* might be used. That declaration has "handler" callback with NTAPI */ + /* attribute. The proper type (with "handler" field compatible with */ + /* GC mark_ex_handler) is declared in excpt.h. The given macro is */ + /* defined before any system header include. */ +# define __MINGW_EXCPT_DEFINE_PSDK 1 +#endif + #include "private/gc_pmark.h" #include @@ -24,11 +34,18 @@ /* Make arguments appear live to compiler. Put here to minimize the */ /* risk of inlining. Used to minimize junk left in registers. */ +GC_ATTR_NOINLINE void GC_noop6(word arg1 GC_ATTR_UNUSED, word arg2 GC_ATTR_UNUSED, word arg3 GC_ATTR_UNUSED, word arg4 GC_ATTR_UNUSED, word arg5 GC_ATTR_UNUSED, word arg6 GC_ATTR_UNUSED) { - /* Empty */ + /* Avoid GC_noop6 calls to be optimized away. */ +# if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) \ + || defined(PARALLEL_MARK) + AO_compiler_barrier(); /* to serve as a special side-effect */ +# else + GC_noop1(0); +# endif } /* Single argument version, robust against whole program analysis. */ @@ -48,41 +65,33 @@ GC_INNER unsigned GC_n_mark_procs = GC_RESERVED_MARK_PROCS; /* It's done here, since we need to deal with mark descriptors. */ GC_INNER struct obj_kind GC_obj_kinds[MAXOBJKINDS] = { /* PTRFREE */ { &GC_aobjfreelist[0], 0 /* filled in dynamically */, - 0 | GC_DS_LENGTH, FALSE, FALSE + /* 0 | */ GC_DS_LENGTH, FALSE, FALSE /*, */ OK_DISCLAIM_INITZ }, -/* NORMAL */ { &GC_objfreelist[0], 0, - 0 | GC_DS_LENGTH, /* Adjusted in GC_init for EXTRA_BYTES */ +/* NORMAL */ { &GC_objfreelist[0], 0, + /* 0 | */ GC_DS_LENGTH, + /* adjusted in GC_init for EXTRA_BYTES */ TRUE /* add length to descr */, TRUE /*, */ OK_DISCLAIM_INITZ }, /* UNCOLLECTABLE */ { &GC_uobjfreelist[0], 0, - 0 | GC_DS_LENGTH, TRUE /* add length to descr */, TRUE + /* 0 | */ GC_DS_LENGTH, TRUE /* add length to descr */, TRUE /*, */ OK_DISCLAIM_INITZ }, -# ifdef ATOMIC_UNCOLLECTABLE - /* AUNCOLLECTABLE */ +# ifdef GC_ATOMIC_UNCOLLECTABLE { &GC_auobjfreelist[0], 0, - 0 | GC_DS_LENGTH, FALSE /* add length to descr */, FALSE + /* 0 | */ GC_DS_LENGTH, FALSE /* add length to descr */, FALSE /*, */ OK_DISCLAIM_INITZ }, # endif # ifdef STUBBORN_ALLOC -/*STUBBORN*/ { (void **)&GC_sobjfreelist[0], 0, - 0 | GC_DS_LENGTH, TRUE /* add length to descr */, TRUE + { (void **)&GC_sobjfreelist[0], 0, + /* 0 | */ GC_DS_LENGTH, TRUE /* add length to descr */, TRUE /*, */ OK_DISCLAIM_INITZ }, # endif }; -# ifdef ATOMIC_UNCOLLECTABLE -# ifdef STUBBORN_ALLOC -# define GC_N_KINDS_INITIAL_VALUE 5 -# else -# define GC_N_KINDS_INITIAL_VALUE 4 -# endif +# ifdef STUBBORN_ALLOC +# define GC_N_KINDS_INITIAL_VALUE (STUBBORN+1) # else -# ifdef STUBBORN_ALLOC -# define GC_N_KINDS_INITIAL_VALUE 4 -# else -# define GC_N_KINDS_INITIAL_VALUE 3 -# endif +# define GC_N_KINDS_INITIAL_VALUE STUBBORN # endif GC_INNER unsigned GC_n_kinds = GC_N_KINDS_INITIAL_VALUE; @@ -92,9 +101,9 @@ GC_INNER unsigned GC_n_kinds = GC_N_KINDS_INITIAL_VALUE; /* INITIAL_MARK_STACK_SIZE * sizeof(mse) should be a */ /* multiple of HBLKSIZE. */ /* The incremental collector actually likes a larger */ - /* size, since it want to push all marked dirty objs */ - /* before marking anything new. Currently we let it */ - /* grow dynamically. */ + /* size, since it wants to push all marked dirty */ + /* objects before marking anything new. Currently we */ + /* let it grow dynamically. */ # endif STATIC word GC_n_rescuing_pages = 0; @@ -154,7 +163,7 @@ GC_INNER void GC_set_hdr_marks(hdr *hhdr) } # endif # ifdef MARK_BIT_PER_OBJ - hhdr -> hb_n_marks = n_marks - 1; + hhdr -> hb_n_marks = n_marks; # else hhdr -> hb_n_marks = HBLK_OBJS(sz); # endif @@ -194,9 +203,11 @@ GC_API void GC_CALL GC_clear_mark_bit(const void *p) word bit_no = MARK_BIT_NO((ptr_t)p - (ptr_t)h, hhdr -> hb_sz); if (mark_bit_from_hdr(hhdr, bit_no)) { - size_t n_marks; + size_t n_marks = hhdr -> hb_n_marks; + + GC_ASSERT(n_marks != 0); clear_mark_bit_from_hdr(hhdr, bit_no); - n_marks = hhdr -> hb_n_marks - 1; + n_marks--; # ifdef PARALLEL_MARK if (n_marks != 0 || !GC_parallel) hhdr -> hb_n_marks = n_marks; @@ -240,13 +251,15 @@ GC_INNER void GC_clear_marks(void) GC_INNER void GC_initiate_gc(void) { # ifndef GC_DISABLE_INCREMENTAL - if (GC_dirty_maintained) GC_read_dirty(); + if (GC_incremental) { + GC_read_dirty(); + } # endif # ifdef STUBBORN_ALLOC GC_read_changed(); # endif # ifdef CHECKSUMS - if (GC_dirty_maintained) GC_check_dirty(); + if (GC_incremental) GC_check_dirty(); # endif GC_n_rescuing_pages = 0; if (GC_mark_state == MS_NONE) { @@ -276,20 +289,6 @@ STATIC struct hblk * GC_push_next_marked_uncollectable(struct hblk *h); static void alloc_mark_stack(size_t); -# if (((defined(MSWIN32) || defined(MSWINCE)) && !defined(__GNUC__)) \ - || (defined(MSWIN32) && defined(I386)) /* for Win98 */ \ - || (defined(USE_PROC_FOR_LIBRARIES) && defined(THREADS))) \ - && !defined(NO_WRAP_MARK_SOME) - /* Under rare conditions, we may end up marking from nonexistent memory. */ - /* Hence we need to be prepared to recover by running GC_mark_some */ - /* with a suitable handler in place. */ - /* FIXME: Should we really need it for WinCE? If yes then */ - /* WRAP_MARK_SOME should be also defined for CeGCC which requires */ - /* CPU/OS-specific code in mark_ex_handler() and GC_mark_some() */ - /* (for manual stack unwinding and exception handler installation). */ -# define WRAP_MARK_SOME -# endif - /* Perform a small amount of marking. */ /* We try to touch roughly a page of memory. */ /* Return TRUE if we just finished a mark phase. */ @@ -463,9 +462,9 @@ static void alloc_mark_stack(size_t); return ExceptionContinueSearch; } } -# endif /* __GNUC__ && MSWIN32 */ +# endif /* __GNUC__ && MSWIN32 */ -#if defined(GC_WIN32_THREADS) && !defined(__GNUC__) +#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) GC_INNER GC_bool GC_started_thread_while_stopped(void); /* In win32_threads.c. Did we invalidate mark phase with an */ /* unexpected thread start? */ @@ -499,7 +498,7 @@ static void alloc_mark_stack(size_t); EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { goto handle_ex; } -# ifdef GC_WIN32_THREADS +# if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) /* With DllMain-based thread tracking, a thread may have */ /* started while we were marking. This is logically equivalent */ /* to the exception case; our results are invalid and we have */ @@ -518,7 +517,23 @@ static void alloc_mark_stack(size_t); ext_ex_regn er; - er.alt_path = &&handle_ex; +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) \ + || __clang_major__ > 3 \ + || (__clang_major__ == 3 && __clang_minor__ >= 3) +# pragma GCC diagnostic push + /* Suppress "taking the address of label is non-standard" warning. */ +# if defined(__clang__) || __GNUC__ > 6 \ + || (__GNUC__ == 6 && __GNUC_MINOR__ >= 4) +# pragma GCC diagnostic ignored "-Wpedantic" +# else + /* GCC before ~4.8 does not accept "-Wpedantic" quietly. */ +# pragma GCC diagnostic ignored "-pedantic" +# endif + er.alt_path = &&handle_ex; +# pragma GCC diagnostic pop +# else /* pragma diagnostic is not supported */ + er.alt_path = &&handle_ex; +# endif er.ex_reg.handler = mark_ex_handler; __asm__ __volatile__ ("movl %%fs:0, %0" : "=r" (er.ex_reg.prev)); __asm__ __volatile__ ("movl %0, %%fs:0" : : "r" (&er)); @@ -527,6 +542,10 @@ static void alloc_mark_stack(size_t); /* and thus eliminating it. */ if (er.alt_path == 0) goto handle_ex; +# if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) + if (GC_started_thread_while_stopped()) + goto handle_ex; +# endif rm_handler: /* Uninstall the exception handler */ __asm__ __volatile__ ("mov %0, %%fs:0" : : "r" (er.ex_reg.prev)); @@ -554,11 +573,23 @@ static void alloc_mark_stack(size_t); handle_ex: /* Exception handler starts here for all cases. */ - WARN("Caught ACCESS_VIOLATION in marker;" - " memory mapping disappeared\n", 0); + { + static word warned_gc_no; + /* Warn about it at most once per collection. */ + if (warned_gc_no != GC_gc_no) { + warned_gc_no = GC_gc_no; + WARN("Caught ACCESS_VIOLATION in marker;" + " memory mapping disappeared\n", 0); + } + } /* We have bad roots on the stack. Discard mark stack. */ /* Rescan from marked objects. Redetermine roots. */ +# ifdef REGISTER_LIBRARIES_EARLY + START_WORLD(); + GC_cond_register_dynamic_libraries(); + STOP_WORLD(); +# endif GC_invalidate_mark_state(); scan_ptr = 0; @@ -604,13 +635,14 @@ GC_INNER mse * GC_signal_mark_stack_overflow(mse *msp) * encoding, we optionally maintain a cache for the block address to * header mapping, we prefetch when an object is "grayed", etc. */ +GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, mse *mark_stack_limit) { signed_word credit = HBLKSIZE; /* Remaining credit for marking work */ - ptr_t current_p; /* Pointer to current candidate ptr. */ - word current; /* Candidate pointer. */ - ptr_t limit; /* (Incl) limit of current candidate range. */ + ptr_t current_p; /* Pointer to current candidate ptr. */ + word current; /* Candidate pointer. */ + ptr_t limit = 0; /* (Incl) limit of current candidate range. */ word descr; ptr_t greatest_ha = GC_greatest_plausible_heap_addr; ptr_t least_ha = GC_least_plausible_heap_addr; @@ -637,25 +669,23 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, if (descr & ((~(WORDS_TO_BYTES(SPLIT_RANGE_WORDS) - 1)) | GC_DS_TAGS)) { word tag = descr & GC_DS_TAGS; + GC_STATIC_ASSERT(GC_DS_TAGS == 0x3); switch(tag) { case GC_DS_LENGTH: /* Large length. */ /* Process part of the range to avoid pushing too much on the */ /* stack. */ GC_ASSERT(descr < (word)GC_greatest_plausible_heap_addr - - (word)GC_least_plausible_heap_addr); -# ifdef ENABLE_TRACE - if ((word)GC_trace_addr >= (word)current_p - && (word)GC_trace_addr < (word)(current_p + descr)) { - GC_log_printf("GC #%u: large section; start %p, len %lu\n", - (unsigned)GC_gc_no, current_p, (unsigned long)descr); - } -# endif /* ENABLE_TRACE */ + - (word)GC_least_plausible_heap_addr + || (word)(current_p + descr) + <= (word)GC_least_plausible_heap_addr + || (word)current_p >= (word)GC_greatest_plausible_heap_addr); # ifdef PARALLEL_MARK # define SHARE_BYTES 2048 if (descr > SHARE_BYTES && GC_parallel && (word)mark_stack_top < (word)(mark_stack_limit - 1)) { - int new_size = (descr/2) & ~(sizeof(word)-1); + word new_size = (descr/2) & ~(word)(sizeof(word)-1); + mark_stack_top -> mse_start = current_p; mark_stack_top -> mse_descr.w = new_size + sizeof(word); /* makes sure we handle */ @@ -664,10 +694,13 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if ((word)GC_trace_addr >= (word)current_p && (word)GC_trace_addr < (word)(current_p + descr)) { - GC_log_printf("GC #%u: splitting (parallel) %p at %p\n", - (unsigned)GC_gc_no, current_p, current_p + new_size); + GC_log_printf("GC #%u: large section; start %p, len %lu," + " splitting (parallel) at %p\n", + (unsigned)GC_gc_no, (void *)current_p, + (unsigned long)descr, + (void *)(current_p + new_size)); } -# endif /* ENABLE_TRACE */ +# endif current_p += new_size; descr -= new_size; goto retry; @@ -680,10 +713,12 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if ((word)GC_trace_addr >= (word)current_p && (word)GC_trace_addr < (word)(current_p + descr)) { - GC_log_printf("GC #%u: splitting %p at %p\n", - (unsigned)GC_gc_no, current_p, limit); + GC_log_printf("GC #%u: large section; start %p, len %lu," + " splitting at %p\n", + (unsigned)GC_gc_no, (void *)current_p, + (unsigned long)descr, (void *)limit); } -# endif /* ENABLE_TRACE */ +# endif /* Make sure that pointers overlapping the two ranges are */ /* considered. */ limit += sizeof(word) - ALIGNMENT; @@ -695,14 +730,14 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, && (word)GC_trace_addr < (word)(current_p + WORDS_TO_BYTES(WORDSZ-2))) { GC_log_printf("GC #%u: tracing from %p bitmap descr %lu\n", - (unsigned)GC_gc_no, current_p, + (unsigned)GC_gc_no, (void *)current_p, (unsigned long)descr); } # endif /* ENABLE_TRACE */ descr &= ~GC_DS_TAGS; credit -= WORDS_TO_BYTES(WORDSZ/2); /* guess */ while (descr != 0) { - if ((signed_word)descr < 0) { + if ((descr & SIGNB) != 0) { current = *(word *)current_p; FIXUP_POINTER(current); if (current >= (word)least_ha && current < (word)greatest_ha) { @@ -710,12 +745,12 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if (GC_trace_addr == current_p) { GC_log_printf("GC #%u: considering(3) %p -> %p\n", - (unsigned)GC_gc_no, current_p, - (ptr_t)current); + (unsigned)GC_gc_no, (void *)current_p, + (void *)current); } # endif /* ENABLE_TRACE */ PUSH_CONTENTS((ptr_t)current, mark_stack_top, - mark_stack_limit, current_p, exit1); + mark_stack_limit, current_p); } } descr <<= 1; @@ -729,7 +764,7 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, && GC_base(current_p) != 0 && GC_base(current_p) == GC_base(GC_trace_addr)) { GC_log_printf("GC #%u: tracing from %p, proc descr %lu\n", - (unsigned)GC_gc_no, current_p, + (unsigned)GC_gc_no, (void *)current_p, (unsigned long)descr); } # endif /* ENABLE_TRACE */ @@ -746,8 +781,8 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, /* word in object. */ ptr_t type_descr = *(ptr_t *)current_p; /* type_descr is either a valid pointer to the descriptor */ - /* structure, or this object was on a free list. If it */ - /* it was anything but the last object on the free list, */ + /* structure, or this object was on a free list. */ + /* If it was anything but the last object on the free list, */ /* we will misinterpret the next object on the free list as */ /* the type descriptor, and get a 0 GC descriptor, which */ /* is ideal. Unfortunately, we need to check for the last */ @@ -758,8 +793,8 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, continue; } descr = *(word *)(type_descr - - (descr + (GC_INDIR_PER_OBJ_BIAS - - GC_DS_PER_OBJECT))); + - ((signed_word)descr + (GC_INDIR_PER_OBJ_BIAS + - GC_DS_PER_OBJECT))); } if (0 == descr) { /* Can happen either because we generated a 0 descriptor */ @@ -768,25 +803,23 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, continue; } goto retry; - default: - limit = 0; /* initialized to prevent warning. */ - ABORT_RET("GC_mark_from: bad state"); } } else /* Small object with length descriptor */ { mark_stack_top--; # ifndef SMALL_CONFIG if (descr < sizeof(word)) continue; +# endif +# ifdef ENABLE_TRACE + if ((word)GC_trace_addr >= (word)current_p + && (word)GC_trace_addr < (word)(current_p + descr)) { + GC_log_printf("GC #%u: small object; start %p, len %lu\n", + (unsigned)GC_gc_no, (void *)current_p, + (unsigned long)descr); + } # endif limit = current_p + (word)descr; } -# ifdef ENABLE_TRACE - if ((word)GC_trace_addr >= (word)current_p - && (word)GC_trace_addr < (word)limit) { - GC_log_printf("GC #%u: Tracing from %p, length is %lu\n", - (unsigned)GC_gc_no, current_p, (unsigned long)descr); - } -# endif /* ENABLE_TRACE */ /* The simple case in which we're scanning a range. */ GC_ASSERT(!((word)current_p & (ALIGNMENT-1))); credit -= limit - current_p; @@ -841,11 +874,12 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if (GC_trace_addr == current_p) { GC_log_printf("GC #%u: considering(1) %p -> %p\n", - (unsigned)GC_gc_no, current_p, (ptr_t)current); + (unsigned)GC_gc_no, (void *)current_p, + (void *)current); } # endif /* ENABLE_TRACE */ PUSH_CONTENTS((ptr_t)current, mark_stack_top, - mark_stack_limit, current_p, exit2); + mark_stack_limit, current_p); } current_p += ALIGNMENT; } @@ -857,11 +891,12 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, # ifdef ENABLE_TRACE if (GC_trace_addr == current_p) { GC_log_printf("GC #%u: considering(2) %p -> %p\n", - (unsigned)GC_gc_no, current_p, (ptr_t)deferred); + (unsigned)GC_gc_no, (void *)current_p, + (void *)deferred); } # endif /* ENABLE_TRACE */ PUSH_CONTENTS((ptr_t)deferred, mark_stack_top, - mark_stack_limit, current_p, exit4); + mark_stack_limit, current_p); next_object:; # endif } @@ -883,11 +918,35 @@ STATIC unsigned GC_active_count = 0; /* Number of active helpers. */ GC_INNER word GC_mark_no = 0; -#define LOCAL_MARK_STACK_SIZE HBLKSIZE +#ifdef LINT2 +# define LOCAL_MARK_STACK_SIZE (HBLKSIZE / 8) +#else +# define LOCAL_MARK_STACK_SIZE HBLKSIZE /* Under normal circumstances, this is big enough to guarantee */ /* we don't overflow half of it in a single call to */ /* GC_mark_from. */ +#endif +/* Wait all markers to finish initialization (i.e. store */ +/* marker_[b]sp, marker_mach_threads, GC_marker_Id). */ +GC_INNER void GC_wait_for_markers_init(void) +{ + signed_word count; + + if (GC_markers_m1 == 0) + return; + + /* Reuse marker lock and builders count to synchronize */ + /* marker threads startup. */ + GC_acquire_mark_lock(); + GC_fl_builder_count += GC_markers_m1; + count = GC_fl_builder_count; + GC_release_mark_lock(); + if (count != 0) { + GC_ASSERT(count > 0); + GC_wait_for_reclaim(); + } +} /* Steal mark stack entries starting at mse low into mark stack local */ /* until we either steal mse high, or we have max entries. */ @@ -913,9 +972,13 @@ STATIC mse * GC_steal_mark_stack(mse * low, mse * high, mse * local, ++top; top -> mse_descr.w = descr; top -> mse_start = p -> mse_start; - GC_ASSERT((top->mse_descr.w & GC_DS_TAGS) != GC_DS_LENGTH || - top->mse_descr.w < (word)GC_greatest_plausible_heap_addr - - (word)GC_least_plausible_heap_addr); + GC_ASSERT((descr & GC_DS_TAGS) != GC_DS_LENGTH + || descr < (word)GC_greatest_plausible_heap_addr + - (word)GC_least_plausible_heap_addr + || (word)(p->mse_start + descr) + <= (word)GC_least_plausible_heap_addr + || (word)p->mse_start + >= (word)GC_greatest_plausible_heap_addr); /* If this is a big object, count it as */ /* size/256 + 1 objects. */ ++i; @@ -957,20 +1020,28 @@ STATIC void GC_return_mark_stack(mse * low, mse * high) GC_notify_all_marker(); } +/* This function is only called when the local */ +/* and the main mark stacks are both empty. */ +static GC_bool has_inactive_helpers(void) +{ + GC_bool res; + + GC_acquire_mark_lock(); + res = GC_active_count < GC_helper_count; + GC_release_mark_lock(); + return res; +} + /* Mark from the local mark stack. */ /* On return, the local mark stack is empty. */ /* But this may be achieved by copying the */ /* local mark stack back into the global one. */ +/* We do not hold the mark lock. */ STATIC void GC_do_local_mark(mse *local_mark_stack, mse *local_top) { unsigned n; # define N_LOCAL_ITERS 1 -# ifdef GC_ASSERTIONS - /* Make sure we don't hold mark lock. */ - GC_acquire_mark_lock(); - GC_release_mark_lock(); -# endif for (;;) { for (n = 0; n < N_LOCAL_ITERS; ++n) { local_top = GC_mark_from(local_top, local_mark_stack, @@ -984,8 +1055,8 @@ STATIC void GC_do_local_mark(mse *local_mark_stack, mse *local_top) } if ((word)AO_load((volatile AO_t *)&GC_mark_stack_top) < (word)AO_load(&GC_first_nonempty) - && GC_active_count < GC_helper_count - && (word)local_top > (word)(local_mark_stack + 1)) { + && (word)local_top > (word)(local_mark_stack + 1) + && has_inactive_helpers()) { /* Try to share the load, since the main stack is empty, */ /* and helper threads are waiting for a refill. */ /* The entries near the bottom of the stack are likely */ @@ -1007,21 +1078,19 @@ STATIC void GC_do_local_mark(mse *local_mark_stack, mse *local_top) /* Mark using the local mark stack until the global mark stack is empty */ /* and there are no active workers. Update GC_first_nonempty to reflect */ -/* progress. */ -/* Caller does not hold mark lock. */ +/* progress. Caller holds the mark lock. */ /* Caller has already incremented GC_helper_count. We decrement it, */ /* and maintain GC_active_count. */ STATIC void GC_mark_local(mse *local_mark_stack, int id) { mse * my_first_nonempty; - GC_acquire_mark_lock(); GC_active_count++; my_first_nonempty = (mse *)AO_load(&GC_first_nonempty); GC_ASSERT((word)GC_mark_stack <= (word)my_first_nonempty); GC_ASSERT((word)my_first_nonempty <= (word)AO_load((volatile AO_t *)&GC_mark_stack_top) + sizeof(mse)); - GC_VERBOSE_LOG_PRINTF("Starting mark helper %lu\n", (unsigned long)id); + GC_VERBOSE_LOG_PRINTF("Starting mark helper %d\n", id); GC_release_mark_lock(); for (;;) { size_t n_on_stack; @@ -1034,24 +1103,20 @@ STATIC void GC_mark_local(mse *local_mark_stack, int id) (word)my_first_nonempty <= (word)AO_load((volatile AO_t *)&GC_mark_stack_top) + sizeof(mse)); - GC_ASSERT((word)global_first_nonempty >= (word)GC_mark_stack && - (word)global_first_nonempty <= - (word)AO_load((volatile AO_t *)&GC_mark_stack_top) - + sizeof(mse)); + GC_ASSERT((word)global_first_nonempty >= (word)GC_mark_stack); if ((word)my_first_nonempty < (word)global_first_nonempty) { my_first_nonempty = global_first_nonempty; } else if ((word)global_first_nonempty < (word)my_first_nonempty) { - AO_compare_and_swap(&GC_first_nonempty, - (AO_t) global_first_nonempty, - (AO_t) my_first_nonempty); + (void)AO_compare_and_swap(&GC_first_nonempty, + (AO_t)global_first_nonempty, + (AO_t)my_first_nonempty); /* If this fails, we just go ahead, without updating */ /* GC_first_nonempty. */ } /* Perhaps we should also update GC_first_nonempty, if it */ /* is less. But that would require using atomic updates. */ my_top = (mse *)AO_load_acquire((volatile AO_t *)(&GC_mark_stack_top)); - n_on_stack = my_top - my_first_nonempty + 1; - if (0 == n_on_stack) { + if ((word)my_top < (word)my_first_nonempty) { GC_acquire_mark_lock(); my_top = GC_mark_stack_top; /* Asynchronous modification impossible here, */ @@ -1083,9 +1148,7 @@ STATIC void GC_mark_local(mse *local_mark_stack, int id) /* both conditions actually held simultaneously. */ GC_helper_count--; if (0 == GC_helper_count) need_to_notify = TRUE; - GC_VERBOSE_LOG_PRINTF("Finished mark helper %lu\n", - (unsigned long)id); - GC_release_mark_lock(); + GC_VERBOSE_LOG_PRINTF("Finished mark helper %d\n", id); if (need_to_notify) GC_notify_all_marker(); return; } @@ -1098,6 +1161,8 @@ STATIC void GC_mark_local(mse *local_mark_stack, int id) } else { GC_release_mark_lock(); } + } else { + n_on_stack = my_top - my_first_nonempty + 1; } n_to_get = ENTRIES_TO_GET; if (n_on_stack < 2 * ENTRIES_TO_GET) n_to_get = 1; @@ -1133,11 +1198,9 @@ STATIC void GC_do_parallel_mark(void) GC_active_count = 0; GC_helper_count = 1; GC_help_wanted = TRUE; - GC_release_mark_lock(); GC_notify_all_marker(); /* Wake up potential helpers. */ GC_mark_local(local_mark_stack, 0); - GC_acquire_mark_lock(); GC_help_wanted = FALSE; /* Done; clean up. */ while (GC_helper_count > 0) { @@ -1154,15 +1217,15 @@ STATIC void GC_do_parallel_mark(void) /* Try to help out the marker, if it's running. */ /* We do not hold the GC lock, but the requestor does. */ +/* And we hold the mark lock. */ GC_INNER void GC_help_marker(word my_mark_no) { - unsigned my_id; +# define my_id my_id_mse.mse_descr.w + mse my_id_mse; /* align local_mark_stack explicitly */ mse local_mark_stack[LOCAL_MARK_STACK_SIZE]; /* Note: local_mark_stack is quite big (up to 128 KiB). */ - if (!GC_parallel) return; - - GC_acquire_mark_lock(); + GC_ASSERT(GC_parallel); while (GC_mark_no < my_mark_no || (!GC_help_wanted && GC_mark_no == my_mark_no)) { GC_wait_marker(); @@ -1171,17 +1234,37 @@ GC_INNER void GC_help_marker(word my_mark_no) if (GC_mark_no != my_mark_no || my_id > (unsigned)GC_markers_m1) { /* Second test is useful only if original threads can also */ /* act as helpers. Under Linux they can't. */ - GC_release_mark_lock(); return; } - GC_helper_count = my_id + 1; - GC_release_mark_lock(); - GC_mark_local(local_mark_stack, my_id); + GC_helper_count = (unsigned)my_id + 1; + GC_mark_local(local_mark_stack, (int)my_id); /* GC_mark_local decrements GC_helper_count. */ +# undef my_id } #endif /* PARALLEL_MARK */ +GC_INNER void GC_scratch_recycle_inner(void *ptr, size_t bytes) +{ + if (ptr != NULL) { + size_t page_offset = (word)ptr & (GC_page_size - 1); + size_t displ = 0; + size_t recycled_bytes; + + GC_ASSERT(bytes != 0); + GC_ASSERT(GC_page_size != 0); + /* TODO: Assert correct memory flags if GWW_VDB */ + if (page_offset != 0) + displ = GC_page_size - page_offset; + recycled_bytes = (bytes - displ) & ~(GC_page_size - 1); + GC_COND_LOG_PRINTF("Recycle %lu/%lu scratch-allocated bytes at %p\n", + (unsigned long)recycled_bytes, (unsigned long)bytes, + ptr); + if (recycled_bytes > 0) + GC_add_to_heap((struct hblk *)((word)ptr + displ), recycled_bytes); + } +} + /* Allocate or reallocate space for mark stack of size n entries. */ /* May silently fail. */ static void alloc_mark_stack(size_t n) @@ -1199,20 +1282,12 @@ static void alloc_mark_stack(size_t n) # endif GC_mark_stack_too_small = FALSE; - if (GC_mark_stack_size != 0) { + if (GC_mark_stack != NULL) { if (new_stack != 0) { if (recycle_old) { /* Recycle old space */ - size_t page_offset = (word)GC_mark_stack & (GC_page_size - 1); - size_t size = GC_mark_stack_size * sizeof(struct GC_ms_entry); - size_t displ = 0; - - if (0 != page_offset) displ = GC_page_size - page_offset; - size = (size - displ) & ~(GC_page_size - 1); - if (size > 0) { - GC_add_to_heap((struct hblk *) - ((word)GC_mark_stack + displ), (word)size); - } + GC_scratch_recycle_inner(GC_mark_stack, + GC_mark_stack_size * sizeof(struct GC_ms_entry)); } GC_mark_stack = new_stack; GC_mark_stack_size = n; @@ -1223,11 +1298,10 @@ static void alloc_mark_stack(size_t n) } else { WARN("Failed to grow mark stack to %" WARN_PRIdPTR " frames\n", n); } + } else if (NULL == new_stack) { + GC_err_printf("No space for mark stack\n"); + EXIT(); } else { - if (new_stack == 0) { - GC_err_printf("No space for mark stack\n"); - EXIT(); - } GC_mark_stack = new_stack; GC_mark_stack_size = n; GC_mark_stack_limit = new_stack + n; @@ -1295,6 +1369,11 @@ GC_API void GC_CALL GC_push_all(char *bottom, char *top) return; } if ((*dirty_fn)(h-1)) { + if ((word)(GC_mark_stack_top - GC_mark_stack) + > 3 * GC_mark_stack_size / 4) { + GC_push_all(bottom, top); + return; + } GC_push_all(bottom, (ptr_t)h); } @@ -1315,9 +1394,6 @@ GC_API void GC_CALL GC_push_all(char *bottom, char *top) if ((ptr_t)h != top && (*dirty_fn)(h)) { GC_push_all((ptr_t)h, top); } - if ((word)GC_mark_stack_top >= (word)GC_mark_stack_limit) { - ABORT("Unexpected mark stack overflow"); - } } GC_API void GC_CALL GC_push_conditional(char *bottom, char *top, int all) @@ -1326,7 +1402,7 @@ GC_API void GC_CALL GC_push_all(char *bottom, char *top) GC_push_selected((ptr_t)bottom, (ptr_t)top, GC_page_was_dirty); } else { # ifdef PROC_VDB - if (GC_dirty_maintained) { + if (GC_incremental) { /* Pages that were never dirtied cannot contain pointers. */ GC_push_selected((ptr_t)bottom, (ptr_t)top, GC_page_was_ever_dirty); } else @@ -1371,15 +1447,10 @@ GC_API struct GC_ms_entry * GC_CALL GC_mark_and_push(void *obj, } PUSH_CONTENTS_HDR(obj, mark_stack_ptr /* modified */, mark_stack_limit, - (ptr_t)src, was_marked, hhdr, TRUE); - was_marked: + (ptr_t)src, hhdr, TRUE); return mark_stack_ptr; } -#if defined(MANUAL_VDB) && defined(THREADS) - void GC_dirty(ptr_t p); -#endif - /* Mark and push (i.e. gray) a single object p onto the main */ /* mark stack. Consider p to be valid if it is an interior */ /* pointer. */ @@ -1399,28 +1470,24 @@ GC_API struct GC_ms_entry * GC_CALL GC_mark_and_push(void *obj, PREFETCH(p); GET_HDR(p, hhdr); - if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr), FALSE)) { - if (hhdr != 0) { - r = GC_base(p); - hhdr = HDR(r); - } - if (hhdr == 0) { - GC_ADD_TO_BLACK_LIST_STACK(p, source); - return; - } + if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr), FALSE) + && (NULL == hhdr + || (r = GC_base(p)) == NULL + || (hhdr = HDR(r)) == NULL)) { + GC_ADD_TO_BLACK_LIST_STACK(p, source); + return; } if (EXPECT(HBLK_IS_FREE(hhdr), FALSE)) { GC_ADD_TO_BLACK_LIST_NORMAL(p, source); return; } -# if defined(MANUAL_VDB) && defined(THREADS) +# ifdef THREADS /* Pointer is on the stack. We may have dirtied the object */ - /* it points to, but not yet have called GC_dirty(); */ - GC_dirty(p); /* Implicitly affects entire object. */ + /* it points to, but have not called GC_dirty yet. */ + GC_dirty(p); /* entire object */ # endif PUSH_CONTENTS_HDR(r, GC_mark_stack_top, GC_mark_stack_limit, - source, mark_and_push_exit, hhdr, FALSE); - mark_and_push_exit: ; + source, hhdr, FALSE); /* We silently ignore pointers to near the end of a block, */ /* which is very mildly suboptimal. */ /* FIXME: We should probably add a header word to address */ @@ -1428,9 +1495,11 @@ GC_API struct GC_ms_entry * GC_CALL GC_mark_and_push(void *obj, } # undef source -# ifdef TRACE_BUF +#ifdef TRACE_BUF -# define TRACE_ENTRIES 1000 +# ifndef TRACE_ENTRIES +# define TRACE_ENTRIES 1000 +# endif struct trace_entry { char * kind; @@ -1453,12 +1522,13 @@ void GC_add_trace_entry(char *kind, word arg1, word arg2) if (GC_trace_buf_ptr >= TRACE_ENTRIES) GC_trace_buf_ptr = 0; } -void GC_print_trace_inner(word gc_no) +GC_API void GC_CALL GC_print_trace_inner(word gc_no) { int i; - struct trace_entry *p; for (i = GC_trace_buf_ptr-1; i != GC_trace_buf_ptr; i--) { + struct trace_entry *p; + if (i < 0) i = TRACE_ENTRIES-1; p = GC_trace_buf + i; if (p -> gc_no < gc_no || p -> kind == 0) { @@ -1472,7 +1542,7 @@ void GC_print_trace_inner(word gc_no) GC_printf("Trace incomplete\n"); } -void GC_print_trace(word gc_no) +GC_API void GC_CALL GC_print_trace(word gc_no) { DCL_LOCK_STATE; @@ -1481,19 +1551,19 @@ void GC_print_trace(word gc_no) UNLOCK(); } -# endif /* TRACE_BUF */ +#endif /* TRACE_BUF */ /* * A version of GC_push_all that treats all interior pointers as valid * and scans the entire region immediately, in case the contents * change. */ -GC_INNER void GC_push_all_eager(ptr_t bottom, ptr_t top) +GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY +GC_API void GC_CALL GC_push_all_eager(char *bottom, char *top) { word * b = (word *)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1)); word * t = (word *)(((word) top) & ~(ALIGNMENT-1)); register word *p; - register word q; register word *lim; register ptr_t greatest_ha = GC_greatest_plausible_heap_addr; register ptr_t least_ha = GC_least_plausible_heap_addr; @@ -1506,7 +1576,7 @@ GC_INNER void GC_push_all_eager(ptr_t bottom, ptr_t top) lim = t - 1 /* longword */; for (p = b; (word)p <= (word)lim; p = (word *)(((ptr_t)p) + ALIGNMENT)) { - q = *p; + register word q = *p; GC_PUSH_ONE_STACK(q, p); } # undef GC_greatest_plausible_heap_addr @@ -1518,14 +1588,46 @@ GC_INNER void GC_push_all_stack(ptr_t bottom, ptr_t top) # if defined(THREADS) && defined(MPROTECT_VDB) GC_push_all_eager(bottom, top); # else - if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) { - GC_push_all(bottom, top); - } else { +# ifndef NEED_FIXUP_POINTER + if (GC_all_interior_pointers) { + GC_push_all(bottom, top); + } else +# endif + /* else */ { GC_push_all_eager(bottom, top); } # endif } +#if defined(WRAP_MARK_SOME) && defined(PARALLEL_MARK) + /* Similar to GC_push_conditional but scans the whole region immediately. */ + GC_ATTR_NO_SANITIZE_ADDR GC_ATTR_NO_SANITIZE_MEMORY + GC_INNER void GC_push_conditional_eager(ptr_t bottom, ptr_t top, + GC_bool all) + { + word * b = (word *)(((word) bottom + ALIGNMENT-1) & ~(ALIGNMENT-1)); + word * t = (word *)(((word) top) & ~(ALIGNMENT-1)); + register word *p; + register word *lim; + register ptr_t greatest_ha = GC_greatest_plausible_heap_addr; + register ptr_t least_ha = GC_least_plausible_heap_addr; +# define GC_greatest_plausible_heap_addr greatest_ha +# define GC_least_plausible_heap_addr least_ha + + if (top == NULL) + return; + (void)all; /* TODO: If !all then scan only dirty pages. */ + + lim = t - 1; + for (p = b; (word)p <= (word)lim; p = (word *)((ptr_t)p + ALIGNMENT)) { + register word q = *p; + GC_PUSH_ONE_HEAP(q, p, GC_mark_stack_top); + } +# undef GC_greatest_plausible_heap_addr +# undef GC_least_plausible_heap_addr + } +#endif /* WRAP_MARK_SOME && PARALLEL_MARK */ + #if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) && \ defined(MARK_BIT_PER_GRANULE) # if GC_GRANULE_WORDS == 1 @@ -1568,8 +1670,6 @@ STATIC void GC_push_marked1(struct hblk *h, hdr *hhdr) word * mark_word_addr = &(hhdr->hb_marks[0]); word *p; word *plim; - word *q; - word mark_word; /* Allow registers to be used for some frequently accessed */ /* global variables. Otherwise aliasing issues are likely */ @@ -1591,8 +1691,9 @@ STATIC void GC_push_marked1(struct hblk *h, hdr *hhdr) /* go through all words in block */ while ((word)p < (word)plim) { - mark_word = *mark_word_addr++; - q = p; + word mark_word = *mark_word_addr++; + word *q = p; + while(mark_word != 0) { if (mark_word & 1) { PUSH_GRANULE(q); @@ -1622,8 +1723,6 @@ STATIC void GC_push_marked2(struct hblk *h, hdr *hhdr) word * mark_word_addr = &(hhdr->hb_marks[0]); word *p; word *plim; - word *q; - word mark_word; ptr_t greatest_ha = GC_greatest_plausible_heap_addr; ptr_t least_ha = GC_least_plausible_heap_addr; @@ -1642,8 +1741,9 @@ STATIC void GC_push_marked2(struct hblk *h, hdr *hhdr) /* go through all words in block */ while ((word)p < (word)plim) { - mark_word = *mark_word_addr++; - q = p; + word mark_word = *mark_word_addr++; + word *q = p; + while(mark_word != 0) { if (mark_word & 1) { PUSH_GRANULE(q); @@ -1674,8 +1774,6 @@ STATIC void GC_push_marked4(struct hblk *h, hdr *hhdr) word * mark_word_addr = &(hhdr->hb_marks[0]); word *p; word *plim; - word *q; - word mark_word; ptr_t greatest_ha = GC_greatest_plausible_heap_addr; ptr_t least_ha = GC_least_plausible_heap_addr; @@ -1694,8 +1792,9 @@ STATIC void GC_push_marked4(struct hblk *h, hdr *hhdr) /* go through all words in block */ while ((word)p < (word)plim) { - mark_word = *mark_word_addr++; - q = p; + word mark_word = *mark_word_addr++; + word *q = p; + while(mark_word != 0) { if (mark_word & 1) { PUSH_GRANULE(q); @@ -1735,14 +1834,14 @@ STATIC void GC_push_marked(struct hblk *h, hdr *hhdr) mse * mark_stack_limit = GC_mark_stack_limit; /* Some quick shortcuts: */ - if ((0 | GC_DS_LENGTH) == descr) return; + if ((/* 0 | */ GC_DS_LENGTH) == descr) return; if (GC_block_empty(hhdr)/* nothing marked */) return; GC_n_rescuing_pages++; GC_objects_are_marked = TRUE; if (sz > MAXOBJBYTES) { lim = h -> hb_body; } else { - lim = (h + 1)->hb_body - sz; + lim = (ptr_t)((word)(h + 1)->hb_body - sz); } switch(BYTES_TO_GRANULES(sz)) { @@ -1760,6 +1859,8 @@ STATIC void GC_push_marked(struct hblk *h, hdr *hhdr) break; # endif # endif +# else + case 1: /* to suppress "switch statement contains no case" warning */ # endif default: GC_mark_stack_top_reg = GC_mark_stack_top; @@ -1793,7 +1894,7 @@ STATIC void GC_push_marked(struct hblk *h, hdr *hhdr) mse * GC_mark_stack_top_reg; mse * mark_stack_limit = GC_mark_stack_limit; - if ((0 | GC_DS_LENGTH) == descr) + if ((/* 0 | */ GC_DS_LENGTH) == descr) return; GC_n_rescuing_pages++; @@ -1801,11 +1902,11 @@ STATIC void GC_push_marked(struct hblk *h, hdr *hhdr) if (sz > MAXOBJBYTES) lim = h -> hb_body; else - lim = (h + 1)->hb_body - sz; + lim = (ptr_t)((word)(h + 1)->hb_body - sz); GC_mark_stack_top_reg = GC_mark_stack_top; for (p = h -> hb_body; (word)p <= (word)lim; p += sz) - if ((*(GC_word *)p & 0x3) != 0) + if ((*(word *)p & 0x3) != 0) PUSH_OBJ(p, hhdr, GC_mark_stack_top_reg, mark_stack_limit); GC_mark_stack_top = GC_mark_stack_top_reg; } @@ -1840,6 +1941,10 @@ STATIC struct hblk * GC_push_next_marked(struct hblk *h) h = GC_next_used_block(h); if (h == 0) return(0); hhdr = GC_find_header((ptr_t)h); + } else { +# ifdef LINT2 + if (NULL == h) ABORT("Bad HDR() definition"); +# endif } GC_push_marked(h, hhdr); return(h + OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz)); @@ -1851,29 +1956,45 @@ STATIC struct hblk * GC_push_next_marked(struct hblk *h) { hdr * hhdr = HDR(h); - if (!GC_dirty_maintained) ABORT("Dirty bits not set up"); + if (!GC_incremental) ABORT("Dirty bits not set up"); for (;;) { if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr) || HBLK_IS_FREE(hhdr), FALSE)) { h = GC_next_used_block(h); if (h == 0) return(0); hhdr = GC_find_header((ptr_t)h); + } else { +# ifdef LINT2 + if (NULL == h) ABORT("Bad HDR() definition"); +# endif } # ifdef STUBBORN_ALLOC if (hhdr -> hb_obj_kind == STUBBORN) { - if (GC_page_was_changed(h) && GC_block_was_dirty(h, hhdr)) { + if (GC_page_was_changed(h) && GC_block_was_dirty(h, hhdr)) break; - } - } else { - if (GC_block_was_dirty(h, hhdr)) break; - } -# else - if (GC_block_was_dirty(h, hhdr)) break; + } else # endif + /* else */ { + if (GC_block_was_dirty(h, hhdr)) break; + } h += OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz); hhdr = HDR(h); } - GC_push_marked(h, hhdr); +# ifdef ENABLE_DISCLAIM + if ((hhdr -> hb_flags & MARK_UNCONDITIONALLY) != 0) { + GC_push_unconditionally(h, hhdr); + + /* Then we may ask, why not also add the MARK_UNCONDITIONALLY */ + /* case to GC_push_next_marked, which is also applied to */ + /* uncollectible blocks? But it seems to me that the function */ + /* does not need to scan uncollectible (and unconditionally */ + /* marked) blocks since those are already handled in the */ + /* MS_PUSH_UNCOLLECTABLE phase. */ + } else +# endif + /* else */ { + GC_push_marked(h, hhdr); + } return(h + OBJ_SZ_TO_BLOCKS(hhdr -> hb_sz)); } #endif /* !GC_DISABLE_INCREMENTAL */ @@ -1890,6 +2011,10 @@ STATIC struct hblk * GC_push_next_marked_uncollectable(struct hblk *h) h = GC_next_used_block(h); if (h == 0) return(0); hhdr = GC_find_header((ptr_t)h); + } else { +# ifdef LINT2 + if (NULL == h) ABORT("Bad HDR() definition"); +# endif } if (hhdr -> hb_obj_kind == UNCOLLECTABLE) { GC_push_marked(h, hhdr); diff --git a/src/bdwgc/mark_rts.c b/src/bdwgc/mark_rts.c index fc1f46c3b..a85a43cff 100644 --- a/src/bdwgc/mark_rts.c +++ b/src/bdwgc/mark_rts.c @@ -62,7 +62,8 @@ static int n_root_sets = 0; for (i = 0; i < n_root_sets; i++) { GC_printf("From %p to %p%s\n", - GC_static_roots[i].r_start, GC_static_roots[i].r_end, + (void *)GC_static_roots[i].r_start, + (void *)GC_static_roots[i].r_end, GC_static_roots[i].r_tmp ? " (temporary)" : ""); } GC_printf("GC_root_size: %lu\n", (unsigned long)GC_root_size); @@ -167,12 +168,10 @@ GC_API void GC_CALL GC_add_roots(void *b, void *e) /* re-registering dynamic libraries. */ void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp) { - struct roots * old; - GC_ASSERT((word)b <= (word)e); - b = (ptr_t)(((word)b + (sizeof(word) - 1)) & ~(sizeof(word) - 1)); + b = (ptr_t)(((word)b + (sizeof(word) - 1)) & ~(word)(sizeof(word) - 1)); /* round b up to word boundary */ - e = (ptr_t)((word)e & ~(sizeof(word) - 1)); + e = (ptr_t)((word)e & ~(word)(sizeof(word) - 1)); /* round e down to word boundary */ if ((word)b >= (word)e) return; /* nothing to do */ @@ -185,7 +184,8 @@ void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp) /* takes to scan the roots. */ { register int i; - old = 0; /* initialized to prevent warning. */ + struct roots * old = NULL; /* initialized to prevent warning. */ + for (i = 0; i < n_root_sets; i++) { old = GC_static_roots + i; if ((word)b <= (word)old->r_end @@ -232,13 +232,17 @@ void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp) } } # else - old = (struct roots *)GC_roots_present(b); - if (old != 0) { - if ((word)e <= (word)old->r_end) /* already there */ return; - /* else extend */ - GC_root_size += e - old -> r_end; - old -> r_end = e; - return; + { + struct roots * old = (struct roots *)GC_roots_present(b); + + if (old != 0) { + if ((word)e <= (word)old->r_end) + return; /* already there */ + /* else extend */ + GC_root_size += e - old -> r_end; + old -> r_end = e; + return; + } } # endif if (n_root_sets == MAX_ROOT_SETS) { @@ -247,7 +251,8 @@ void GC_add_roots_inner(ptr_t b, ptr_t e, GC_bool tmp) # ifdef DEBUG_ADD_DEL_ROOTS GC_log_printf("Adding data root section %d: %p .. %p%s\n", - n_root_sets, b, e, tmp ? " (temporary)" : ""); + n_root_sets, (void *)b, (void *)e, + tmp ? " (temporary)" : ""); # endif GC_static_roots[n_root_sets].r_start = (ptr_t)b; GC_static_roots[n_root_sets].r_end = (ptr_t)e; @@ -285,7 +290,8 @@ STATIC void GC_remove_root_at_pos(int i) { # ifdef DEBUG_ADD_DEL_ROOTS GC_log_printf("Remove data root section at %d: %p .. %p%s\n", - i, GC_static_roots[i].r_start, GC_static_roots[i].r_end, + i, (void *)GC_static_roots[i].r_start, + (void *)GC_static_roots[i].r_end, GC_static_roots[i].r_tmp ? " (temporary)" : ""); # endif GC_root_size -= (GC_static_roots[i].r_end - GC_static_roots[i].r_start); @@ -333,8 +339,8 @@ STATIC void GC_remove_tmp_roots(void) DCL_LOCK_STATE; /* Quick check whether has nothing to do */ - if ((((word)b + (sizeof(word) - 1)) & ~(sizeof(word) - 1)) >= - ((word)e & ~(sizeof(word) - 1))) + if ((((word)b + (sizeof(word) - 1)) & ~(word)(sizeof(word) - 1)) >= + ((word)e & ~(word)(sizeof(word) - 1))) return; LOCK(); @@ -358,12 +364,108 @@ STATIC void GC_remove_tmp_roots(void) } #endif /* !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) */ -#if (defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)) \ - && !defined(NO_DEBUGGING) - /* Not used at present (except for, may be, debugging purpose). */ +#ifdef USE_PROC_FOR_LIBRARIES + /* Exchange the elements of the roots table. Requires rebuild of */ + /* the roots index table after the swap. */ + GC_INLINE void swap_static_roots(int i, int j) + { + ptr_t r_start = GC_static_roots[i].r_start; + ptr_t r_end = GC_static_roots[i].r_end; + GC_bool r_tmp = GC_static_roots[i].r_tmp; + + GC_static_roots[i].r_start = GC_static_roots[j].r_start; + GC_static_roots[i].r_end = GC_static_roots[j].r_end; + GC_static_roots[i].r_tmp = GC_static_roots[j].r_tmp; + /* No need to swap r_next values. */ + GC_static_roots[j].r_start = r_start; + GC_static_roots[j].r_end = r_end; + GC_static_roots[j].r_tmp = r_tmp; + } + + /* Remove given range from every static root which intersects with */ + /* the range. It is assumed GC_remove_tmp_roots is called before */ + /* this function is called repeatedly by GC_register_map_entries. */ + GC_INNER void GC_remove_roots_subregion(ptr_t b, ptr_t e) + { + int i; + GC_bool rebuild = FALSE; + + GC_ASSERT(I_HOLD_LOCK()); + GC_ASSERT((word)b % sizeof(word) == 0 && (word)e % sizeof(word) == 0); + for (i = 0; i < n_root_sets; i++) { + ptr_t r_start, r_end; + + if (GC_static_roots[i].r_tmp) { + /* The remaining roots are skipped as they are all temporary. */ +# ifdef GC_ASSERTIONS + int j; + for (j = i + 1; j < n_root_sets; j++) { + GC_ASSERT(GC_static_roots[j].r_tmp); + } +# endif + break; + } + r_start = GC_static_roots[i].r_start; + r_end = GC_static_roots[i].r_end; + if (!EXPECT((word)e <= (word)r_start || (word)r_end <= (word)b, TRUE)) { +# ifdef DEBUG_ADD_DEL_ROOTS + GC_log_printf("Removing %p .. %p from root section %d (%p .. %p)\n", + (void *)b, (void *)e, + i, (void *)r_start, (void *)r_end); +# endif + if ((word)r_start < (word)b) { + GC_root_size -= r_end - b; + GC_static_roots[i].r_end = b; + /* No need to rebuild as hash does not use r_end value. */ + if ((word)e < (word)r_end) { + int j; + + if (rebuild) { + GC_rebuild_root_index(); + rebuild = FALSE; + } + GC_add_roots_inner(e, r_end, FALSE); /* updates n_root_sets */ + for (j = i + 1; j < n_root_sets; j++) + if (GC_static_roots[j].r_tmp) + break; + if (j < n_root_sets-1 && !GC_static_roots[n_root_sets-1].r_tmp) { + /* Exchange the roots to have all temporary ones at the end. */ + swap_static_roots(j, n_root_sets - 1); + rebuild = TRUE; + } + } + } else { + if ((word)e < (word)r_end) { + GC_root_size -= e - r_start; + GC_static_roots[i].r_start = e; + } else { + GC_remove_root_at_pos(i); + if (i < n_root_sets - 1 && GC_static_roots[i].r_tmp + && !GC_static_roots[i + 1].r_tmp) { + int j; + + for (j = i + 2; j < n_root_sets; j++) + if (GC_static_roots[j].r_tmp) + break; + /* Exchange the roots to have all temporary ones at the end. */ + swap_static_roots(i, j - 1); + } + i--; + } + rebuild = TRUE; + } + } + } + if (rebuild) + GC_rebuild_root_index(); + } +#endif /* USE_PROC_FOR_LIBRARIES */ + +#if !defined(NO_DEBUGGING) + /* For the debugging purpose only. */ /* Workaround for the OS mapping and unmapping behind our back: */ /* Is the address p in one of the temporary static root sections? */ - GC_bool GC_is_tmp_root(ptr_t p) + GC_API int GC_CALL GC_is_tmp_root(void *p) { static int last_root_set = MAX_ROOT_SETS; register int i; @@ -381,18 +483,21 @@ STATIC void GC_remove_tmp_roots(void) } return(FALSE); } -#endif /* MSWIN32 || MSWINCE || CYGWIN32 */ +#endif /* !NO_DEBUGGING */ GC_INNER ptr_t GC_approx_sp(void) { volatile word sp; - sp = (word)&sp; +# if defined(CPPCHECK) || (__GNUC__ >= 4 \ + && !defined(STACK_NOT_SCANNED)) + sp = (word)__builtin_frame_address(0); +# else + sp = (word)&sp; +# endif /* Also force stack to grow if necessary. Otherwise the */ /* later accesses might cause the kernel to think we're */ /* doing something wrong. */ return((ptr_t)sp); - /* GNU C: alternatively, we may return the value of */ - /*__builtin_frame_address(0). */ } /* @@ -418,10 +523,10 @@ STATIC struct exclusion * GC_next_exclusion(ptr_t start_addr) { size_t low = 0; size_t high = GC_excl_table_entries - 1; - size_t mid; while (high > low) { - mid = (low + high) >> 1; + size_t mid = (low + high) >> 1; + /* low <= mid < high */ if ((word) GC_excl_table[mid].e_end <= (word) start_addr) { low = mid + 1; @@ -438,7 +543,7 @@ STATIC struct exclusion * GC_next_exclusion(ptr_t start_addr) GC_INNER void GC_exclude_static_roots_inner(void *start, void *finish) { struct exclusion * next; - size_t next_index, i; + size_t next_index; GC_ASSERT((word)start % sizeof(word) == 0); GC_ASSERT((word)start < (word)finish); @@ -449,6 +554,8 @@ GC_INNER void GC_exclude_static_roots_inner(void *start, void *finish) next = GC_next_exclusion(start); } if (0 != next) { + size_t i; + if ((word)(next -> e_start) < (word) finish) { /* incomplete error check. */ ABORT("Exclusion ranges overlap"); @@ -478,27 +585,46 @@ GC_API void GC_CALL GC_exclude_static_roots(void *b, void *e) if (b == e) return; /* nothing to exclude? */ /* Round boundaries (in direction reverse to that of GC_add_roots). */ - b = (void *)((word)b & ~(sizeof(word) - 1)); - e = (void *)(((word)e + (sizeof(word) - 1)) & ~(sizeof(word) - 1)); - if (0 == e) e = (void *)(word)(~(sizeof(word) - 1)); /* handle overflow */ + b = (void *)((word)b & ~(word)(sizeof(word) - 1)); + e = (void *)(((word)e + (sizeof(word) - 1)) & ~(word)(sizeof(word) - 1)); + if (NULL == e) + e = (void *)(~(word)(sizeof(word) - 1)); /* handle overflow */ LOCK(); GC_exclude_static_roots_inner(b, e); UNLOCK(); } +#if defined(WRAP_MARK_SOME) && defined(PARALLEL_MARK) + /* GC_mark_local does not handle memory protection faults yet. So, */ + /* the static data regions are scanned immediately by GC_push_roots. */ + GC_INNER void GC_push_conditional_eager(ptr_t bottom, ptr_t top, + GC_bool all); +# define GC_PUSH_CONDITIONAL(b, t, all) \ + (GC_parallel \ + ? GC_push_conditional_eager(b, t, all) \ + : GC_push_conditional((ptr_t)(b), (ptr_t)(t), all)) +#elif defined(GC_DISABLE_INCREMENTAL) +# define GC_PUSH_CONDITIONAL(b, t, all) GC_push_all((ptr_t)(b), (ptr_t)(t)) +#else +# define GC_PUSH_CONDITIONAL(b, t, all) \ + GC_push_conditional((ptr_t)(b), (ptr_t)(t), all) + /* Do either of GC_push_all or GC_push_selected */ + /* depending on the third arg. */ +#endif + /* Invoke push_conditional on ranges that are not excluded. */ STATIC void GC_push_conditional_with_exclusions(ptr_t bottom, ptr_t top, GC_bool all GC_ATTR_UNUSED) { - struct exclusion * next; - ptr_t excl_start; - while ((word)bottom < (word)top) { - next = GC_next_exclusion(bottom); - if (0 == next || (word)(excl_start = next -> e_start) >= (word)top) { - GC_PUSH_CONDITIONAL(bottom, top, all); - return; + struct exclusion *next = GC_next_exclusion(bottom); + ptr_t excl_start; + + if (0 == next + || (word)(excl_start = next -> e_start) >= (word)top) { + GC_PUSH_CONDITIONAL(bottom, top, all); + break; } if ((word)excl_start > (word)bottom) GC_PUSH_CONDITIONAL(bottom, excl_start, all); @@ -581,7 +707,8 @@ GC_INNER void GC_push_all_stack_sections(ptr_t lo, ptr_t hi, STATIC void GC_push_all_stack_partially_eager(ptr_t bottom, ptr_t top, ptr_t cold_gc_frame) { - if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) { +#ifndef NEED_FIXUP_POINTER + if (GC_all_interior_pointers) { /* Push the hot end of the stack eagerly, so that register values */ /* saved inside GC frames are marked before they disappear. */ /* The rest of the marking can be deferred until later. */ @@ -598,11 +725,13 @@ STATIC void GC_push_all_stack_partially_eager(ptr_t bottom, ptr_t top, GC_push_all(bottom, cold_gc_frame + sizeof(ptr_t)); GC_push_all_eager(cold_gc_frame, top); # endif /* STACK_GROWS_UP */ - } else { + } else +#endif + /* else */ { GC_push_all_eager(bottom, top); } # ifdef TRACE_BUF - GC_add_trace_entry("GC_push_all_stack", bottom, top); + GC_add_trace_entry("GC_push_all_stack", (word)bottom, (word)top); # endif } @@ -742,7 +871,7 @@ STATIC void GC_push_regs_and_stack(ptr_t cold_gc_frame) } /* - * Call the mark routines (GC_tl_push for a single pointer, + * Call the mark routines (GC_push_one for a single pointer, * GC_push_conditional on groups of pointers) on every top level * accessible pointer. * If all is FALSE, arrange to push only possibly altered values. diff --git a/src/bdwgc/misc.c b/src/bdwgc/misc.c index 6c01404e3..a0b0bad87 100644 --- a/src/bdwgc/misc.c +++ b/src/bdwgc/misc.c @@ -77,7 +77,7 @@ GC_FAR struct _GC_arrays GC_arrays /* = { 0 } */; GC_INNER GC_bool GC_debugging_started = FALSE; - /* defined here so we don't have to load debug_malloc.o */ + /* defined here so we don't have to load dbg_mlc.o */ ptr_t GC_stackbottom = 0; @@ -230,7 +230,7 @@ GC_API void GC_CALL GC_set_handle_fork(int value GC_ATTR_UNUSED) /* quantization algorithm (but we precompute it). */ STATIC void GC_init_size_map(void) { - int i; + size_t i; /* Map size 0 to something bigger. */ /* This avoids problems at lower levels. */ @@ -274,7 +274,7 @@ GC_INNER void GC_extend_size_map(size_t i) if (granule_sz < orig_granule_sz) granule_sz = orig_granule_sz; } /* For these larger sizes, we use an even number of granules. */ - /* This makes it easier to, for example, construct a 16byte-aligned */ + /* This makes it easier to, e.g., construct a 16-byte-aligned */ /* allocator even if GRANULE_BYTES is 8. */ granule_sz += 1; granule_sz &= ~1; @@ -358,7 +358,6 @@ GC_API void * GC_CALL GC_clear_stack(void *arg) /* Used to occasionally clear a bigger */ /* chunk. */ # endif - ptr_t limit; # define SLOP 400 /* Extra bytes we clear every time. This clears our own */ @@ -366,7 +365,7 @@ GC_API void * GC_CALL GC_clear_stack(void *arg) /* clearing near the cold end of the stack, a good thing. */ # define GC_SLOP 4000 /* We make GC_high_water this much hotter than we really saw */ - /* saw it, to cover for GC noise etc. above our current frame. */ + /* it, to cover for GC noise etc. above our current frame. */ # define CLEAR_THRESHOLD 100000 /* We restart the clearing process after this many bytes of */ /* allocation. Otherwise very heavily recursive programs */ @@ -377,15 +376,15 @@ GC_API void * GC_CALL GC_clear_stack(void *arg) /* larger ... */ # ifdef THREADS if (++random_no % 13 == 0) { - limit = sp; + ptr_t limit = sp; + MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word)); limit = (ptr_t)((word)limit & ~0xf); /* Make it sufficiently aligned for assembly */ /* implementations of GC_clear_stack_inner. */ return GC_clear_stack_inner(arg, limit); - } else { - BZERO((void *)dummy, SMALL_CLEAR_SIZE*sizeof(word)); } + BZERO((void *)dummy, SMALL_CLEAR_SIZE*sizeof(word)); # else if (GC_gc_no > GC_stack_last_cleared) { /* Start things over, so we clear the entire stack again */ @@ -401,16 +400,19 @@ GC_API void * GC_CALL GC_clear_stack(void *arg) GC_high_water = sp; } MAKE_HOTTER(GC_high_water, GC_SLOP); - limit = GC_min_sp; - MAKE_HOTTER(limit, SLOP); - if ((word)sp COOLER_THAN (word)limit) { - limit = (ptr_t)((word)limit & ~0xf); - /* Make it sufficiently aligned for assembly */ - /* implementations of GC_clear_stack_inner. */ - GC_min_sp = sp; - return GC_clear_stack_inner(arg, limit); - } else if (GC_bytes_allocd - GC_bytes_allocd_at_reset - > CLEAR_THRESHOLD) { + { + ptr_t limit = GC_min_sp; + + MAKE_HOTTER(limit, SLOP); + if ((word)sp COOLER_THAN (word)limit) { + limit = (ptr_t)((word)limit & ~0xf); + /* Make it sufficiently aligned for assembly */ + /* implementations of GC_clear_stack_inner. */ + GC_min_sp = sp; + return GC_clear_stack_inner(arg, limit); + } + } + if (GC_bytes_allocd - GC_bytes_allocd_at_reset > CLEAR_THRESHOLD) { /* Restart clearing process, but limit how much clearing we do. */ GC_min_sp = sp; MAKE_HOTTER(GC_min_sp, CLEAR_THRESHOLD/4); @@ -431,7 +433,6 @@ GC_API void * GC_CALL GC_base(void * p) struct hblk *h; bottom_index *bi; hdr *candidate_hdr; - ptr_t limit; r = p; if (!EXPECT(GC_is_initialized, TRUE)) return 0; @@ -453,6 +454,7 @@ GC_API void * GC_CALL GC_base(void * p) size_t offset = HBLKDISPL(r); word sz = candidate_hdr -> hb_sz; size_t obj_displ = offset % sz; + ptr_t limit; r -= obj_displ; limit = r + sz; @@ -684,7 +686,7 @@ GC_API void GC_CALL GC_get_heap_usage_safe(GC_word *pheap_size, } /* At this execution point, GC_setpagesize() and GC_init_win32() */ /* must already be called (for GET_MEM() to work correctly). */ - content = (char *)GET_MEM(ROUNDUP_PAGESIZE_IF_MMAP(len + 1)); + content = (char *)GET_MEM(ROUNDUP_PAGESIZE_IF_MMAP((size_t)len + 1)); if (content == NULL) { CloseHandle(hFile); return; /* allocation failure */ @@ -705,6 +707,7 @@ GC_API void GC_CALL GC_get_heap_usage_safe(GC_word *pheap_size, if (content[ofs] == '\r' || content[ofs] == '\n') content[ofs] = '\0'; } + GC_ASSERT(NULL == GC_envfile_content); GC_envfile_length = len + 1; GC_envfile_content = content; # endif @@ -742,6 +745,11 @@ GC_API void GC_CALL GC_get_heap_usage_safe(GC_word *pheap_size, GC_INNER GC_bool GC_is_initialized = FALSE; +GC_API int GC_CALL GC_is_init_called(void) +{ + return GC_is_initialized; +} + #if (defined(MSWIN32) || defined(MSWINCE)) && defined(THREADS) GC_INNER CRITICAL_SECTION GC_write_cs; #endif @@ -750,7 +758,13 @@ GC_INNER GC_bool GC_is_initialized = FALSE; STATIC void GC_exit_check(void) { if (GC_find_leak) { - GC_gcollect(); +# if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) + GC_in_thread_creation = TRUE; /* OK to collect from unknown thread. */ + GC_gcollect(); + GC_in_thread_creation = FALSE; +# else + GC_gcollect(); +# endif } } #endif @@ -795,13 +809,42 @@ GC_INNER GC_bool GC_is_initialized = FALSE; } #endif +#if defined(MSWIN32) && (!defined(SMALL_CONFIG) \ + || (!defined(_WIN64) && defined(GC_WIN32_THREADS) \ + && defined(CHECK_NOT_WOW64))) + STATIC void GC_win32_MessageBoxA(const char *msg, const char *caption, + unsigned flags) + { +# ifndef DONT_USE_USER32_DLL + /* Use static binding to "user32.dll". */ + (void)MessageBoxA(NULL, msg, caption, flags); +# else + /* This simplifies linking - resolve "MessageBoxA" at run-time. */ + HINSTANCE hU32 = LoadLibrary(TEXT("user32.dll")); + if (hU32) { + FARPROC pfn = GetProcAddress(hU32, "MessageBoxA"); + if (pfn) + (void)(*(int (WINAPI *)(HWND, LPCSTR, LPCSTR, UINT))pfn)( + NULL /* hWnd */, msg, caption, flags); + (void)FreeLibrary(hU32); + } +# endif + } +#endif /* MSWIN32 */ + +#if defined(THREADS) && defined(UNIX_LIKE) && !defined(NO_GETCONTEXT) + static void callee_saves_pushed_dummy_fn(ptr_t data GC_ATTR_UNUSED, + void * context GC_ATTR_UNUSED) {} +#endif + STATIC word GC_parse_mem_size_arg(const char *str) { - char *endptr; word result = 0; /* bad value */ - char ch; if (*str != '\0') { + char *endptr; + char ch; + result = (word)STRTOULL(str, &endptr, 10); ch = *endptr; if (ch != '\0') { @@ -847,11 +890,36 @@ GC_API void GC_CALL GC_init(void) } # endif -# ifdef GC_INITIAL_HEAP_SIZE - initial_heap_sz = divHBLKSZ(GC_INITIAL_HEAP_SIZE); +# if defined(GC_INITIAL_HEAP_SIZE) && !defined(CPPCHECK) + initial_heap_sz = GC_INITIAL_HEAP_SIZE; # else - initial_heap_sz = (word)MINHINCR; + initial_heap_sz = MINHINCR * HBLKSIZE; # endif + +# if defined(MSWIN32) && !defined(_WIN64) && defined(GC_WIN32_THREADS) \ + && defined(CHECK_NOT_WOW64) + { + /* Windows: running 32-bit GC on 64-bit system is broken! */ + /* WoW64 bug affects SuspendThread, no workaround exists. */ + HMODULE hK32 = GetModuleHandle(TEXT("kernel32.dll")); + if (hK32) { + FARPROC pfn = GetProcAddress(hK32, "IsWow64Process"); + BOOL bIsWow64 = FALSE; + if (pfn + && (*(BOOL (WINAPI*)(HANDLE, BOOL*))pfn)(GetCurrentProcess(), + &bIsWow64) + && bIsWow64) { + GC_win32_MessageBoxA("This program uses BDWGC garbage collector" + " compiled for 32-bit but running on 64-bit Windows.\n" + "This is known to be broken due to a design flaw" + " in Windows itself! Expect erratic behavior...", + "32-bit program running on 64-bit system", + MB_ICONWARNING | MB_OK); + } + } + } +# endif + DISABLE_CANCEL(cancel_state); /* Note that although we are nominally called with the */ /* allocation lock held, the allocation lock is now */ @@ -918,7 +986,7 @@ GC_API void GC_CALL GC_init(void) # if (defined(UNIX_LIKE) && !defined(GC_ANDROID_LOG)) \ || defined(CYGWIN32) || defined(SYMBIAN) { - char * file_name = GETENV("GC_LOG_FILE"); + char * file_name = TRUSTED_STRING(GETENV("GC_LOG_FILE")); # ifdef GC_LOG_TO_FILE_ALWAYS if (NULL == file_name) file_name = GC_LOG_STD_NAME; @@ -994,7 +1062,7 @@ GC_API void GC_CALL GC_init(void) # else word addr = (word)STRTOULL(addr_string, NULL, 16); if (addr < 0x1000) - WARN("Unlikely trace address: %p\n", addr); + WARN("Unlikely trace address: %p\n", (void *)addr); GC_trace_addr = (ptr_t)addr; # endif } @@ -1050,7 +1118,7 @@ GC_API void GC_CALL GC_init(void) if (space_divisor_string != NULL) { int space_divisor = atoi(space_divisor_string); if (space_divisor > 0) - GC_free_space_divisor = (GC_word)space_divisor; + GC_free_space_divisor = (word)space_divisor; } } # ifdef USE_MUNMAP @@ -1091,10 +1159,11 @@ GC_API void GC_CALL GC_init(void) } # endif maybe_install_looping_handler(); - /* Adjust normal object descriptor for extra allocation. */ - if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) { - GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH); - } +# if ALIGNMENT > GC_DS_TAGS + /* Adjust normal object descriptor for extra allocation. */ + if (EXTRA_BYTES != 0) + GC_obj_kinds[NORMAL].ok_descriptor = (word)(-ALIGNMENT) | GC_DS_LENGTH; +# endif GC_exclude_static_roots_inner(beginGC_arrays, endGC_arrays); GC_exclude_static_roots_inner(beginGC_obj_kinds, endGC_obj_kinds); # ifdef SEPARATE_GLOBALS @@ -1132,26 +1201,27 @@ GC_API void GC_CALL GC_init(void) # endif } # endif - GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word)); - GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word)); +# if !defined(CPPCHECK) + GC_STATIC_ASSERT(sizeof(ptr_t) == sizeof(word)); + GC_STATIC_ASSERT(sizeof(signed_word) == sizeof(word)); +# if !defined(_AUX_SOURCE) || defined(__GNUC__) + GC_STATIC_ASSERT((word)(-1) > (word)0); + /* word should be unsigned */ +# endif + /* We no longer check for ((void*)(-1) > NULL) since all pointers */ + /* are explicitly cast to word in every less/greater comparison. */ + GC_STATIC_ASSERT((signed_word)(-1) < (signed_word)0); +# endif GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE); # ifndef THREADS GC_ASSERT(!((word)GC_stackbottom HOTTER_THAN (word)GC_approx_sp())); # endif -# if !defined(_AUX_SOURCE) || defined(__GNUC__) - GC_STATIC_ASSERT((word)(-1) > (word)0); - /* word should be unsigned */ -# endif - /* We no longer check for ((void*)(-1) > NULL) since all pointers */ - /* are explicitly cast to word in every less-greater comparison. */ - GC_STATIC_ASSERT((signed_word)(-1) < (signed_word)0); # ifndef GC_DISABLE_INCREMENTAL if (GC_incremental || 0 != GETENV("GC_ENABLE_INCREMENTAL")) { /* For GWW_VDB on Win32, this needs to happen before any */ /* heap memory is allocated. */ - GC_dirty_init(); + GC_incremental = GC_dirty_init(); GC_ASSERT(GC_bytes_allocd == 0); - GC_incremental = TRUE; } # endif @@ -1168,21 +1238,20 @@ GC_API void GC_CALL GC_init(void) if (initial_heap_sz <= MINHINCR * HBLKSIZE) { WARN("Bad initial heap size %s - ignoring it.\n", sz_str); } - initial_heap_sz = divHBLKSZ(initial_heap_sz); } } { char * sz_str = GETENV("GC_MAXIMUM_HEAP_SIZE"); if (sz_str != NULL) { word max_heap_sz = GC_parse_mem_size_arg(sz_str); - if (max_heap_sz < initial_heap_sz * HBLKSIZE) { + if (max_heap_sz < initial_heap_sz) { WARN("Bad maximum heap size %s - ignoring it.\n", sz_str); } if (0 == GC_max_retries) GC_max_retries = 2; GC_set_max_heap_size(max_heap_sz); } } - if (!GC_expand_hp_inner(initial_heap_sz)) { + if (!GC_expand_hp_inner(divHBLKSZ(initial_heap_sz))) { GC_err_printf("Can't start up: not enough memory\n"); EXIT(); } else { @@ -1210,11 +1279,35 @@ GC_API void GC_CALL GC_init(void) # endif GC_is_initialized = TRUE; # if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) - GC_thr_init(); +# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED) + DCL_LOCK_STATE; + LOCK(); /* just to set GC_lock_holder */ + GC_thr_init(); + UNLOCK(); +# else + GC_thr_init(); +# endif +# ifdef PARALLEL_MARK + /* Actually start helper threads. */ + GC_start_mark_threads_inner(); +# endif # endif COND_DUMP; /* Get black list set up and/or incremental GC started */ - if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner(); + if (!GC_dont_precollect || GC_incremental) { +# if defined(GC_ASSERTIONS) && defined(GC_ALWAYS_MULTITHREADED) + LOCK(); + GC_gcollect_inner(); + UNLOCK(); +# else + GC_gcollect_inner(); +# endif + } +# if defined(THREADS) && defined(UNIX_LIKE) && !defined(NO_GETCONTEXT) + /* Ensure getcontext_works is set to avoid potential data race. */ + if (GC_dont_gc || GC_dont_precollect) + GC_with_callee_saves_pushed(callee_saves_pushed_dummy_fn, NULL); +# endif # ifdef STUBBORN_ALLOC GC_stubborn_init(); # endif @@ -1258,14 +1351,19 @@ GC_API void GC_CALL GC_enable_incremental(void) GC_setpagesize(); /* if (GC_no_win32_dlls) goto out; Should be win32S test? */ maybe_install_looping_handler(); /* Before write fault handler! */ - GC_incremental = TRUE; if (!GC_is_initialized) { + UNLOCK(); + GC_incremental = TRUE; /* indicate intention to turn it on */ GC_init(); + LOCK(); } else { - GC_dirty_init(); + GC_incremental = GC_dirty_init(); } - if (GC_dirty_maintained && !GC_dont_gc) { + if (GC_incremental && !GC_dont_gc) { /* Can't easily do it if GC_dont_gc. */ + IF_CANCEL(int cancel_state;) + + DISABLE_CANCEL(cancel_state); if (GC_bytes_allocd > 0) { /* There may be unmarked reachable objects. */ GC_gcollect_inner(); @@ -1274,6 +1372,7 @@ GC_API void GC_CALL GC_enable_incremental(void) /* clean since nothing can point to an */ /* unmarked object. */ GC_read_dirty(); + RESTORE_CANCEL(cancel_state); } } UNLOCK(); @@ -1283,11 +1382,19 @@ GC_API void GC_CALL GC_enable_incremental(void) GC_init(); } -#if defined(THREADS) && (!defined(PARALLEL_MARK) || !defined(CAN_HANDLE_FORK)) +#if defined(THREADS) GC_API void GC_CALL GC_start_mark_threads(void) { - /* No action since parallel markers are disabled (or no POSIX fork). */ - GC_ASSERT(I_DONT_HOLD_LOCK()); +# if defined(PARALLEL_MARK) && defined(CAN_HANDLE_FORK) + IF_CANCEL(int cancel_state;) + + DISABLE_CANCEL(cancel_state); + GC_start_mark_threads_inner(); + RESTORE_CANCEL(cancel_state); +# else + /* No action since parallel markers are disabled (or no POSIX fork). */ + GC_ASSERT(I_DONT_HOLD_LOCK()); +# endif } #endif @@ -1485,17 +1592,17 @@ GC_API void GC_CALL GC_enable_incremental(void) return len; # else int bytes_written = 0; - int result; IF_CANCEL(int cancel_state;) DISABLE_CANCEL(cancel_state); while ((size_t)bytes_written < len) { # ifdef GC_SOLARIS_THREADS - result = syscall(SYS_write, fd, buf + bytes_written, + int result = syscall(SYS_write, fd, buf + bytes_written, len - bytes_written); # else - result = write(fd, buf + bytes_written, len - bytes_written); + int result = write(fd, buf + bytes_written, len - bytes_written); # endif + if (-1 == result) { RESTORE_CANCEL(cancel_state); return(result); @@ -1544,12 +1651,17 @@ GC_API void GC_CALL GC_enable_incremental(void) void GC_printf(const char *format, ...) { - char buf[BUFSZ + 1]; - if (!GC_quiet) { + char buf[BUFSZ + 1]; + GC_PRINTF_FILLBUF(buf, format); - if (WRITE(GC_stdout, buf, strlen(buf)) < 0) - ABORT("write to stdout failed"); +# ifdef NACL + (void)WRITE(GC_stdout, buf, strlen(buf)); + /* Ignore errors silently. */ +# else + if (WRITE(GC_stdout, buf, strlen(buf)) < 0) + ABORT("write to stdout failed"); +# endif } } @@ -1566,8 +1678,12 @@ void GC_log_printf(const char *format, ...) char buf[BUFSZ + 1]; GC_PRINTF_FILLBUF(buf, format); - if (WRITE(GC_log, buf, strlen(buf)) < 0) - ABORT("write to GC log failed"); +# ifdef NACL + (void)WRITE(GC_log, buf, strlen(buf)); +# else + if (WRITE(GC_log, buf, strlen(buf)) < 0) + ABORT("write to GC log failed"); +# endif } #ifndef GC_ANDROID_LOG @@ -1627,7 +1743,7 @@ GC_API void GC_CALLBACK GC_ignore_warn_proc(char *msg, GC_word arg) GC_API void GC_CALL GC_set_warn_proc(GC_warn_proc p) { DCL_LOCK_STATE; - GC_ASSERT(p != 0); + GC_ASSERT(NONNULL_ARG_NOT_NULL(p)); # ifdef GC_WIN32_THREADS # ifdef CYGWIN32 /* Need explicit GC_INIT call */ @@ -1661,22 +1777,7 @@ GC_API GC_warn_proc GC_CALL GC_get_warn_proc(void) if (msg != NULL) { # if defined(MSWIN32) -# ifndef DONT_USE_USER32_DLL - /* Use static binding to "user32.dll". */ - (void)MessageBoxA(NULL, msg, "Fatal error in GC", - MB_ICONERROR | MB_OK); -# else - /* This simplifies linking - resolve "MessageBoxA" at run-time. */ - HINSTANCE hU32 = LoadLibrary(TEXT("user32.dll")); - if (hU32) { - FARPROC pfn = GetProcAddress(hU32, "MessageBoxA"); - if (pfn) - (void)(*(int (WINAPI *)(HWND, LPCSTR, LPCSTR, UINT))pfn)( - NULL /* hWnd */, msg, "Fatal error in GC", - MB_ICONERROR | MB_OK); - (void)FreeLibrary(hU32); - } -# endif + GC_win32_MessageBoxA(msg, "Fatal error in GC", MB_ICONERROR | MB_OK); /* Also duplicate msg to GC log file. */ # endif @@ -1715,7 +1816,7 @@ GC_API GC_warn_proc GC_CALL GC_get_warn_proc(void) GC_API void GC_CALL GC_set_abort_func(GC_abort_func fn) { DCL_LOCK_STATE; - GC_ASSERT(fn != 0); + GC_ASSERT(NONNULL_ARG_NOT_NULL(fn)); LOCK(); GC_on_abort = fn; UNLOCK(); @@ -1758,9 +1859,11 @@ GC_API int GC_CALL GC_is_disabled(void) /* Helper procedures for new kind creation. */ GC_API void ** GC_CALL GC_new_free_list_inner(void) { - void *result = GC_INTERNAL_MALLOC((MAXOBJGRANULES+1)*sizeof(ptr_t), - PTRFREE); - if (result == 0) ABORT("Failed to allocate freelist for new kind"); + void *result; + + GC_ASSERT(I_HOLD_LOCK()); + result = GC_INTERNAL_MALLOC((MAXOBJGRANULES+1) * sizeof(ptr_t), PTRFREE); + if (NULL == result) ABORT("Failed to allocate freelist for new kind"); BZERO(result, (MAXOBJGRANULES+1)*sizeof(ptr_t)); return result; } @@ -1780,6 +1883,8 @@ GC_API unsigned GC_CALL GC_new_kind_inner(void **fl, GC_word descr, { unsigned result = GC_n_kinds; + GC_ASSERT(adjust == FALSE || adjust == TRUE); + GC_ASSERT(clear == FALSE || clear == TRUE); if (result < MAXOBJKINDS) { GC_n_kinds++; GC_obj_kinds[result].ok_freelist = fl; @@ -1912,6 +2017,9 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn, GC_ASSERT(GC_blocked_sp == NULL); GC_ASSERT(GC_traced_stack_sect == &stacksect); +# if defined(CPPCHECK) + GC_noop1((word)GC_traced_stack_sect - (word)GC_blocked_sp); +# endif /* Restore original "stack section". */ GC_traced_stack_sect = stacksect.prev; # ifdef IA64 @@ -1942,7 +2050,10 @@ STATIC void GC_do_blocking_inner(ptr_t data, void * context GC_ATTR_UNUSED) # ifdef SPARC GC_ASSERT(GC_blocked_sp != NULL); # else - GC_ASSERT(GC_blocked_sp == (ptr_t) &d); + GC_ASSERT(GC_blocked_sp == (ptr_t)(&d)); +# endif +# if defined(CPPCHECK) + GC_noop1((word)GC_blocked_sp); # endif GC_blocked_sp = NULL; } @@ -1981,6 +2092,24 @@ GC_API void * GC_CALL GC_do_blocking(GC_fn_type fn, void * client_data) } #endif /* !NO_DEBUGGING */ +static void block_add_size(struct hblk *h, word pbytes) +{ + hdr *hhdr = HDR(h); + *(word *)pbytes += (WORDS_TO_BYTES((word)hhdr->hb_sz) + (HBLKSIZE - 1)) + & ~(word)(HBLKSIZE - 1); +} + +GC_API size_t GC_CALL GC_get_memory_use(void) +{ + word bytes = 0; + DCL_LOCK_STATE; + + LOCK(); + GC_apply_to_all_blocks(block_add_size, (word)(&bytes)); + UNLOCK(); + return (size_t)bytes; +} + /* Getter functions for the public Read-only variables. */ /* GC_get_gc_no() is unsynchronized and should be typically called */ @@ -1997,7 +2126,28 @@ GC_API GC_word GC_CALL GC_get_gc_no(void) /* GC_parallel is initialized at start-up. */ return GC_parallel; } -#endif + + GC_INNER GC_on_thread_event_proc GC_on_thread_event = 0; + + GC_API void GC_CALL GC_set_on_thread_event(GC_on_thread_event_proc fn) + { + /* fn may be 0 (means no event notifier). */ + DCL_LOCK_STATE; + LOCK(); + GC_on_thread_event = fn; + UNLOCK(); + } + + GC_API GC_on_thread_event_proc GC_CALL GC_get_on_thread_event(void) + { + GC_on_thread_event_proc fn; + DCL_LOCK_STATE; + LOCK(); + fn = GC_on_thread_event; + UNLOCK(); + return fn; + } +#endif /* THREADS */ /* Setter and getter functions for the public R/W function variables. */ /* These functions are synchronized (like GC_set_warn_proc() and */ @@ -2005,7 +2155,7 @@ GC_API GC_word GC_CALL GC_get_gc_no(void) GC_API void GC_CALL GC_set_oom_fn(GC_oom_func fn) { - GC_ASSERT(fn != 0); + GC_ASSERT(NONNULL_ARG_NOT_NULL(fn)); DCL_LOCK_STATE; LOCK(); GC_oom_fn = fn; @@ -2171,7 +2321,7 @@ GC_API GC_word GC_CALL GC_get_free_space_divisor(void) GC_API void GC_CALL GC_set_max_retries(GC_word value) { - GC_ASSERT(value != ~(GC_word)0); + GC_ASSERT(value != ~(word)0); GC_max_retries = value; } @@ -2223,3 +2373,9 @@ GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void) { return (int)GC_force_unmap_on_gcollect; } + +GC_API void GC_CALL GC_abort_on_oom(void) +{ + GC_err_printf("Insufficient memory for the allocation\n"); + EXIT(); +} diff --git a/src/bdwgc/new_hblk.c b/src/bdwgc/new_hblk.c index 05c4abff5..108bdc054 100644 --- a/src/bdwgc/new_hblk.c +++ b/src/bdwgc/new_hblk.c @@ -25,7 +25,7 @@ #ifndef SMALL_CONFIG /* Build a free list for size 2 (words) cleared objects inside */ - /* hblk h. Set the last link to be ofl. Return a pointer tpo the */ + /* hblk h. Set the last link to be ofl. Return a pointer to the */ /* first free list entry. */ STATIC ptr_t GC_build_fl_clear2(struct hblk *h, ptr_t ofl) { @@ -58,7 +58,7 @@ p[3] = 0; p += 4; for (; (word)p < (word)lim; p += 4) { - PREFETCH_FOR_WRITE((ptr_t)(p+64)); + GC_PREFETCH_FOR_WRITE((ptr_t)(p + 64)); p[0] = (word)(p-4); p[1] = 0; CLEAR_DOUBLE(p+2); @@ -92,7 +92,7 @@ p[4] = (word)p; p += 8; for (; (word)p < (word)lim; p += 8) { - PREFETCH_FOR_WRITE((ptr_t)(p+64)); + GC_PREFETCH_FOR_WRITE((ptr_t)(p + 64)); p[0] = (word)(p-4); p[4] = (word)p; }; @@ -116,10 +116,10 @@ GC_INNER ptr_t GC_build_fl(struct hblk *h, size_t sz, GC_bool clear, /* If we were more serious about it, these should go inside */ /* the loops. But write prefetches usually don't seem to */ /* matter much. */ - PREFETCH_FOR_WRITE((ptr_t)h); - PREFETCH_FOR_WRITE((ptr_t)h + 128); - PREFETCH_FOR_WRITE((ptr_t)h + 256); - PREFETCH_FOR_WRITE((ptr_t)h + 378); + GC_PREFETCH_FOR_WRITE((ptr_t)h); + GC_PREFETCH_FOR_WRITE((ptr_t)h + 128); + GC_PREFETCH_FOR_WRITE((ptr_t)h + 256); + GC_PREFETCH_FOR_WRITE((ptr_t)h + 378); # ifndef SMALL_CONFIG /* Handle small objects sizes more efficiently. For larger objects */ /* the difference is less significant. */ diff --git a/src/bdwgc/obj_map.c b/src/bdwgc/obj_map.c index c935bf3f2..9fdeb0afc 100644 --- a/src/bdwgc/obj_map.c +++ b/src/bdwgc/obj_map.c @@ -51,13 +51,13 @@ GC_INNER void GC_register_displacement_inner(size_t offset) GC_INNER GC_bool GC_add_map_entry(size_t granules) { unsigned displ; - short * new_map; + unsigned short * new_map; if (granules > BYTES_TO_GRANULES(MAXOBJBYTES)) granules = 0; if (GC_obj_map[granules] != 0) { return(TRUE); } - new_map = (short *)GC_scratch_alloc(MAP_LEN * sizeof(short)); + new_map = (unsigned short *)GC_scratch_alloc(MAP_LEN * sizeof(short)); if (new_map == 0) return(FALSE); GC_COND_LOG_PRINTF( "Adding block map for size of %u granules (%u bytes)\n", @@ -68,7 +68,7 @@ GC_INNER void GC_register_displacement_inner(size_t offset) } } else { for (displ = 0; displ < BYTES_TO_GRANULES(HBLKSIZE); displ++) { - new_map[displ] = (short)(displ % granules); + new_map[displ] = (unsigned short)(displ % granules); } } GC_obj_map[granules] = new_map; diff --git a/src/bdwgc/os_dep.c b/src/bdwgc/os_dep.c index 8cd240cc0..1be3009ab 100644 --- a/src/bdwgc/os_dep.c +++ b/src/bdwgc/os_dep.c @@ -69,7 +69,7 @@ #endif #if defined(MMAP_SUPPORTED) || defined(ADD_HEAP_GUARD_PAGES) -# if defined(USE_MUNMAP) && !defined(USE_MMAP) +# if defined(USE_MUNMAP) && !defined(USE_MMAP) && !defined(CPPCHECK) # error "invalid config - USE_MUNMAP requires USE_MMAP" # endif # include @@ -115,11 +115,11 @@ STATIC ssize_t GC_repeat_read(int fd, char *buf, size_t count) { size_t num_read = 0; - ssize_t result; ASSERT_CANCEL_DISABLED(); while (num_read < count) { - result = READ(fd, buf + num_read, count - num_read); + ssize_t result = READ(fd, buf + num_read, count - num_read); + if (result < 0) return result; if (result == 0) break; num_read += result; @@ -129,8 +129,8 @@ STATIC ssize_t GC_repeat_read(int fd, char *buf, size_t count) #ifdef THREADS /* Determine the length of a file by incrementally reading it into a */ - /* This would be silly to use on a file supporting lseek, but Linux */ - /* /proc files usually do not. */ + /* buffer. This would be silly to use it on a file supporting lseek, */ + /* but Linux /proc files usually do not. */ STATIC size_t GC_get_file_len(int f) { size_t total = 0; @@ -163,7 +163,6 @@ STATIC ssize_t GC_repeat_read(int fd, char *buf, size_t count) /* of time. */ GC_INNER char * GC_get_maps(void) { - int f; ssize_t result; static char *maps_buf = NULL; static size_t maps_buf_sz = 1; @@ -178,9 +177,8 @@ GC_INNER char * GC_get_maps(void) /* stacks. And there is no easy way to read the entire */ /* file atomically. This is arguably a misfeature of the */ /* /proc/.../maps interface. */ - - /* Since we don't believe the file can grow */ - /* asynchronously, it should suffice to first determine */ + /* Since we expect the file can grow asynchronously in rare */ + /* cases, it should suffice to first determine */ /* the size (using lseek or read), and then to reread the */ /* file. If the size is inconsistent we have to retry. */ /* This only matters with threads enabled, and if we use */ @@ -199,7 +197,10 @@ GC_INNER char * GC_get_maps(void) /* Note that we may not allocate conventionally, and */ /* thus can't use stdio. */ do { + int f; + while (maps_size >= maps_buf_sz) { + GC_scratch_recycle_no_gww(maps_buf, maps_buf_sz); /* Grow only by powers of 2, since we leak "too small" buffers.*/ while (maps_size >= maps_buf_sz) maps_buf_sz *= 2; maps_buf = GC_scratch_alloc(maps_buf_sz); @@ -230,17 +231,14 @@ GC_INNER char * GC_get_maps(void) return 0; # ifdef THREADS if (maps_size > old_maps_size) { - ABORT_ARG2("Unexpected asynchronous /proc/self/maps growth " - "(unregistered thread?)", " from %lu to %lu", - (unsigned long)old_maps_size, - (unsigned long)maps_size); + /* This might be caused by e.g. thread creation. */ + WARN("Unexpected asynchronous /proc/self/maps growth" + " (to %" WARN_PRIdPTR " bytes)\n", maps_size); } # endif } while (maps_size >= maps_buf_sz || maps_size < old_maps_size); /* In the single-threaded case, the second clause is false. */ maps_buf[maps_size] = '\0'; - - /* Apply fn to result. */ return maps_buf; } @@ -415,7 +413,6 @@ GC_INNER char * GC_get_maps(void) extern int _etext[], __dso_handle[]; # endif # endif /* LINUX */ - extern int _end[]; ptr_t GC_data_start = NULL; @@ -423,10 +420,12 @@ GC_INNER char * GC_get_maps(void) GC_INNER void GC_init_linux_data_start(void) { + ptr_t data_end = DATAEND; + # if (defined(LINUX) || defined(HURD)) && !defined(IGNORE_PROG_DATA_START) /* Try the easy approaches first: */ # ifdef PLATFORM_ANDROID - /* Workaround for "gold" (default) linker (as of Android NDK r9b). */ + /* Workaround for "gold" (default) linker (as of Android NDK r10e). */ if ((word)__data_start < (word)_etext && (word)_etext < (word)__dso_handle) { GC_data_start = (ptr_t)(__dso_handle); @@ -434,19 +433,18 @@ GC_INNER char * GC_get_maps(void) GC_log_printf( "__data_start is wrong; using __dso_handle as data start\n"); # endif - GC_ASSERT((word)GC_data_start <= (word)_end); - return; - } + } else # endif - if ((ptr_t)__data_start != 0) { - GC_data_start = (ptr_t)(__data_start); - GC_ASSERT((word)GC_data_start <= (word)_end); - return; + /* else */ if (COVERT_DATAFLOW(__data_start) != 0) { + GC_data_start = (ptr_t)(__data_start); + } else { + GC_data_start = (ptr_t)(data_start); } - if ((ptr_t)data_start != 0) { - GC_data_start = (ptr_t)(data_start); - GC_ASSERT((word)GC_data_start <= (word)_end); - return; + if (COVERT_DATAFLOW(GC_data_start) != 0) { + if ((word)GC_data_start > (word)data_end) + ABORT_ARG2("Wrong __data_start/_end pair", + ": %p .. %p", (void *)GC_data_start, (void *)data_end); + return; } # ifdef DEBUG_ADD_DEL_ROOTS GC_log_printf("__data_start not provided\n"); @@ -456,11 +454,11 @@ GC_INNER char * GC_get_maps(void) if (GC_no_dls) { /* Not needed, avoids the SIGSEGV caused by */ /* GC_find_limit which complicates debugging. */ - GC_data_start = (ptr_t)_end; /* set data root size to 0 */ + GC_data_start = data_end; /* set data root size to 0 */ return; } - GC_data_start = GC_find_limit((ptr_t)(_end), FALSE); + GC_data_start = GC_find_limit(data_end, FALSE); } #endif /* SEARCH_FOR_DATA_START */ @@ -504,6 +502,17 @@ GC_INNER char * GC_get_maps(void) } #endif /* NETBSD */ +#if defined(ADDRESS_SANITIZER) && (defined(UNIX_LIKE) \ + || defined(NEED_FIND_LIMIT) || defined(MPROTECT_VDB)) \ + && !defined(CUSTOM_ASAN_DEF_OPTIONS) + /* To tell ASan to allow GC to use its own SIGBUS/SEGV handlers. */ + /* The function is exported just to be visible to ASan library. */ + GC_API const char *__asan_default_options(void) + { + return "allow_user_segv_handler=1"; + } +#endif + #ifdef OPENBSD static struct sigaction old_segv_act; STATIC sigjmp_buf GC_jmp_buf_openbsd; @@ -534,7 +543,9 @@ GC_INNER char * GC_get_maps(void) /* allocation lock held. */ struct sigaction act; - size_t pgsz = (size_t)sysconf(_SC_PAGESIZE); + word pgsz = (word)sysconf(_SC_PAGESIZE); + + GC_ASSERT((word)bound >= pgsz); GC_ASSERT(I_HOLD_LOCK()); act.sa_handler = GC_fault_handler_openbsd; @@ -546,11 +557,11 @@ GC_INNER char * GC_get_maps(void) if (sigsetjmp(GC_jmp_buf_openbsd, 1) == 0) { result = (ptr_t)((word)p & ~(pgsz-1)); for (;;) { - result += pgsz; - if ((word)result >= (word)bound) { + if ((word)result >= (word)bound - pgsz) { result = bound; break; } + result += pgsz; /* no overflow expected */ GC_noop1((word)(*result)); } } @@ -572,7 +583,9 @@ GC_INNER char * GC_get_maps(void) static volatile int firstpass; struct sigaction act; - size_t pgsz = (size_t)sysconf(_SC_PAGESIZE); + word pgsz = (word)sysconf(_SC_PAGESIZE); + + GC_ASSERT((word)bound >= pgsz); GC_ASSERT(I_HOLD_LOCK()); act.sa_handler = GC_fault_handler_openbsd; @@ -585,10 +598,10 @@ GC_INNER char * GC_get_maps(void) result = (ptr_t)((word)p & ~(pgsz-1)); if (sigsetjmp(GC_jmp_buf_openbsd, 1) != 0 || firstpass) { firstpass = 0; - result += pgsz; - if ((word)result >= (word)bound) { + if ((word)result >= (word)bound - pgsz) { result = bound; } else { + result += pgsz; /* no overflow expected */ GC_noop1((word)(*result)); } } @@ -682,7 +695,7 @@ struct o32_obj { # endif /* OS/2 */ /* Find the page size */ -GC_INNER word GC_page_size = 0; +GC_INNER size_t GC_page_size = 0; #if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) # ifndef VER_PLATFORM_WIN32_CE @@ -698,7 +711,20 @@ GC_INNER word GC_page_size = 0; GC_INNER void GC_setpagesize(void) { GetSystemInfo(&GC_sysinfo); - GC_page_size = GC_sysinfo.dwPageSize; +# if defined(CYGWIN32) && defined(USE_MUNMAP) + /* Allocations made with mmap() are aligned to the allocation */ + /* granularity, which (at least on 64-bit Windows OS) is not the */ + /* same as the page size. Probably a separate variable could */ + /* be added to distinguish the allocation granularity from the */ + /* actual page size, but in practice there is no good reason to */ + /* make allocations smaller than dwAllocationGranularity, so we */ + /* just use it instead of the actual page size here (as Cygwin */ + /* itself does in many cases). */ + GC_page_size = (size_t)GC_sysinfo.dwAllocationGranularity; + GC_ASSERT(GC_page_size >= (size_t)GC_sysinfo.dwPageSize); +# else + GC_page_size = (size_t)GC_sysinfo.dwPageSize; +# endif # if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION) { OSVERSIONINFO verInfo; @@ -751,10 +777,17 @@ GC_INNER word GC_page_size = 0; GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb) { - ptr_t trunc_sp = (ptr_t)((word)GC_approx_sp() & ~(GC_page_size - 1)); + ptr_t trunc_sp; + word size; + + /* Set page size if it is not ready (so client can use this */ + /* function even before GC is initialized). */ + if (!GC_page_size) GC_setpagesize(); + + trunc_sp = (ptr_t)((word)GC_approx_sp() & ~(GC_page_size - 1)); /* FIXME: This won't work if called from a deeply recursive */ /* client code (and the committed stack space has grown). */ - word size = GC_get_writable_length(trunc_sp, 0); + size = GC_get_writable_length(trunc_sp, 0); GC_ASSERT(size != 0); sb -> mem_base = trunc_sp + size; return GC_SUCCESS; @@ -782,8 +815,11 @@ GC_INNER word GC_page_size = 0; GC_INNER void GC_setpagesize(void) { # if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP) - GC_page_size = GETPAGESIZE(); - if (!GC_page_size) ABORT("getpagesize failed"); + GC_page_size = (size_t)GETPAGESIZE(); +# if !defined(CPPCHECK) + if (0 == GC_page_size) + ABORT("getpagesize failed"); +# endif # else /* It's acceptable to fake it. */ GC_page_size = HBLKSIZE; @@ -791,7 +827,7 @@ GC_INNER word GC_page_size = 0; } #endif /* !MSWIN32 */ -#ifdef BEOS +#ifdef HAIKU # include GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb) @@ -802,7 +838,7 @@ GC_INNER word GC_page_size = 0; return GC_SUCCESS; } # define HAVE_GET_STACK_BASE -#endif /* BEOS */ +#endif /* HAIKU */ #ifdef OS2 GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *sb) @@ -810,7 +846,8 @@ GC_INNER word GC_page_size = 0; PTIB ptib; /* thread information block */ PPIB ppib; if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) { - ABORT("DosGetInfoBlocks failed"); + WARN("DosGetInfoBlocks failed\n", 0); + return GC_UNIMPLEMENTED; } sb->mem_base = ptib->tib_pstacklimit; return GC_SUCCESS; @@ -822,6 +859,7 @@ GC_INNER word GC_page_size = 0; # define GC_AMIGA_SB # include "extra/AmigaOS.c" # undef GC_AMIGA_SB +# define GET_MAIN_STACKBASE_SPECIAL # endif /* AMIGA */ # if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE) @@ -829,7 +867,8 @@ GC_INNER word GC_page_size = 0; typedef void (*GC_fault_handler_t)(int); # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \ - || defined(HURD) || defined(FREEBSD) || defined(NETBSD) + || defined(HAIKU) || defined(HURD) || defined(FREEBSD) \ + || defined(NETBSD) static struct sigaction old_segv_act; # if defined(_sigargs) /* !Irix6.x */ \ || defined(HURD) || defined(NETBSD) || defined(FREEBSD) @@ -837,7 +876,7 @@ GC_INNER word GC_page_size = 0; # endif # else static GC_fault_handler_t old_segv_handler; -# ifdef SIGBUS +# ifdef HAVE_SIGBUS static GC_fault_handler_t old_bus_handler; # endif # endif @@ -845,7 +884,8 @@ GC_INNER word GC_page_size = 0; GC_INNER void GC_set_and_save_fault_handler(GC_fault_handler_t h) { # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \ - || defined(HURD) || defined(FREEBSD) || defined(NETBSD) + || defined(HAIKU) || defined(HURD) || defined(FREEBSD) \ + || defined(NETBSD) struct sigaction act; act.sa_handler = h; @@ -876,9 +916,12 @@ GC_INNER word GC_page_size = 0; # endif /* !GC_IRIX_THREADS */ # else old_segv_handler = signal(SIGSEGV, h); -# ifdef SIGBUS +# ifdef HAVE_SIGBUS old_bus_handler = signal(SIGBUS, h); # endif +# endif +# if defined(CPPCHECK) && defined(ADDRESS_SANITIZER) + GC_noop1((word)&__asan_default_options); # endif } # endif /* NEED_FIND_LIMIT || UNIX_LIKE */ @@ -888,6 +931,8 @@ GC_INNER word GC_page_size = 0; /* Some tools to implement HEURISTIC2 */ # define MIN_PAGE_SIZE 256 /* Smallest conceivable page size, bytes */ + GC_INNER JMP_BUF GC_jmp_buf; + STATIC void GC_fault_handler(int sig GC_ATTR_UNUSED) { LONGJMP(GC_jmp_buf, 1); @@ -904,7 +949,8 @@ GC_INNER word GC_page_size = 0; GC_INNER void GC_reset_fault_handler(void) { # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(OSF1) \ - || defined(HURD) || defined(FREEBSD) || defined(NETBSD) + || defined(HAIKU) || defined(HURD) || defined(FREEBSD) \ + || defined(NETBSD) (void) sigaction(SIGSEGV, &old_segv_act, 0); # if defined(IRIX5) && defined(_sigargs) /* Irix 5.x, not 6.x */ \ || defined(HURD) || defined(NETBSD) @@ -912,7 +958,7 @@ GC_INNER word GC_page_size = 0; # endif # else (void) signal(SIGSEGV, old_segv_handler); -# ifdef SIGBUS +# ifdef HAVE_SIGBUS (void) signal(SIGBUS, old_bus_handler); # endif # endif @@ -930,6 +976,8 @@ GC_INNER word GC_page_size = 0; /* static since it's only called with the */ /* allocation lock held. */ + GC_ASSERT(up ? (word)bound >= MIN_PAGE_SIZE + : (word)bound <= ~(word)MIN_PAGE_SIZE); GC_ASSERT(I_HOLD_LOCK()); GC_setup_temporary_fault_handler(); if (SETJMP(GC_jmp_buf) == 0) { @@ -937,14 +985,13 @@ GC_INNER word GC_page_size = 0; & ~(MIN_PAGE_SIZE-1)); for (;;) { if (up) { - result += MIN_PAGE_SIZE; - if ((word)result >= (word)bound) { + if ((word)result >= (word)bound - MIN_PAGE_SIZE) { result = bound; break; } + result += MIN_PAGE_SIZE; /* no overflow expected */ } else { - result -= MIN_PAGE_SIZE; - if ((word)result <= (word)bound) { + if ((word)result <= (word)bound + MIN_PAGE_SIZE) { result = bound - MIN_PAGE_SIZE; /* This is to compensate */ /* further result increment (we */ @@ -953,6 +1000,7 @@ GC_INNER word GC_page_size = 0; /* by setjmp otherwise). */ break; } + result -= MIN_PAGE_SIZE; /* no underflow expected */ } GC_noop1((word)(*result)); } @@ -1143,13 +1191,17 @@ GC_INNER word GC_page_size = 0; return (ptr_t)GC_get_main_symbian_stack_base(); } # define GET_MAIN_STACKBASE_SPECIAL -#elif !defined(BEOS) && !defined(AMIGA) && !defined(OS2) \ +#elif !defined(AMIGA) && !defined(HAIKU) && !defined(OS2) \ && !defined(MSWIN32) && !defined(MSWINCE) && !defined(CYGWIN32) \ && !defined(GC_OPENBSD_THREADS) \ && (!defined(GC_SOLARIS_THREADS) || defined(_STRICT_STDC)) -# if defined(LINUX) && defined(USE_GET_STACKBASE_FOR_MAIN) +# if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \ + && (defined(THREADS) || defined(USE_GET_STACKBASE_FOR_MAIN)) # include +# ifdef HAVE_PTHREAD_NP_H +# include /* for pthread_attr_get_np() */ +# endif # elif defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP) /* We could use pthread_get_stackaddr_np even in case of a */ /* single-threaded gclib (there is no -lpthread on Darwin). */ @@ -1161,14 +1213,22 @@ GC_INNER word GC_page_size = 0; ptr_t GC_get_main_stack_base(void) { ptr_t result; -# if defined(LINUX) && !defined(NO_PTHREAD_GETATTR_NP) \ +# if (defined(HAVE_PTHREAD_ATTR_GET_NP) \ + || defined(HAVE_PTHREAD_GETATTR_NP)) \ && (defined(USE_GET_STACKBASE_FOR_MAIN) \ || (defined(THREADS) && !defined(REDIRECT_MALLOC))) pthread_attr_t attr; void *stackaddr; size_t size; - if (pthread_getattr_np(pthread_self(), &attr) == 0) { +# ifdef HAVE_PTHREAD_ATTR_GET_NP + if (pthread_attr_init(&attr) == 0 + && (pthread_attr_get_np(pthread_self(), &attr) == 0 + ? TRUE : (pthread_attr_destroy(&attr), FALSE))) +# else /* HAVE_PTHREAD_GETATTR_NP */ + if (pthread_getattr_np(pthread_self(), &attr) == 0) +# endif + { if (pthread_attr_getstack(&attr, &stackaddr, &size) == 0 && stackaddr != NULL) { (void)pthread_attr_destroy(&attr); @@ -1193,19 +1253,16 @@ GC_INNER word GC_page_size = 0; # else result = (ptr_t)((word)GC_approx_sp() & ~STACKBOTTOM_ALIGNMENT_M1); # endif -# endif /* HEURISTIC1 */ -# ifdef LINUX_STACKBOTTOM +# elif defined(LINUX_STACKBOTTOM) result = GC_linux_main_stack_base(); -# endif -# ifdef FREEBSD_STACKBOTTOM +# elif defined(FREEBSD_STACKBOTTOM) result = GC_freebsd_main_stack_base(); -# endif -# ifdef HEURISTIC2 +# elif defined(HEURISTIC2) { ptr_t sp = GC_approx_sp(); # ifdef STACK_GROWS_DOWN result = GC_find_limit(sp, TRUE); -# ifdef HEURISTIC2_LIMIT +# if defined(HEURISTIC2_LIMIT) && !defined(CPPCHECK) if ((word)result > (word)HEURISTIC2_LIMIT && (word)sp < (word)HEURISTIC2_LIMIT) { result = HEURISTIC2_LIMIT; @@ -1213,7 +1270,7 @@ GC_INNER word GC_page_size = 0; # endif # else result = GC_find_limit(sp, FALSE); -# ifdef HEURISTIC2_LIMIT +# if defined(HEURISTIC2_LIMIT) && !defined(CPPCHECK) if ((word)result < (word)HEURISTIC2_LIMIT && (word)sp > (word)HEURISTIC2_LIMIT) { result = HEURISTIC2_LIMIT; @@ -1221,8 +1278,12 @@ GC_INNER word GC_page_size = 0; # endif # endif } -# endif /* HEURISTIC2 */ -# ifdef STACK_GROWS_DOWN +# elif defined(STACK_NOT_SCANNED) || defined(CPPCHECK) + result = NULL; +# else +# error None of HEURISTIC* and *STACKBOTTOM defined! +# endif +# if defined(STACK_GROWS_DOWN) && !defined(CPPCHECK) if (result == 0) result = (ptr_t)(signed_word)(-sizeof(ptr_t)); # endif @@ -1231,13 +1292,14 @@ GC_INNER word GC_page_size = 0; return(result); } # define GET_MAIN_STACKBASE_SPECIAL -#endif /* !AMIGA, !BEOS, !OPENBSD, !OS2, !Windows */ - -#if (defined(GC_LINUX_THREADS) || defined(PLATFORM_ANDROID)) \ - && !defined(NO_PTHREAD_GETATTR_NP) +#endif /* !AMIGA, !HAIKU, !OPENBSD, !OS2, !Windows */ +#if (defined(HAVE_PTHREAD_ATTR_GET_NP) || defined(HAVE_PTHREAD_GETATTR_NP)) \ + && defined(THREADS) && !defined(HAVE_GET_STACK_BASE) # include - /* extern int pthread_getattr_np(pthread_t, pthread_attr_t *); */ +# ifdef HAVE_PTHREAD_NP_H +# include +# endif GC_API int GC_CALL GC_get_stack_base(struct GC_stack_base *b) { @@ -1247,10 +1309,20 @@ GC_INNER word GC_page_size = 0; DCL_LOCK_STATE; # endif - if (pthread_getattr_np(pthread_self(), &attr) != 0) { +# ifdef HAVE_PTHREAD_ATTR_GET_NP + if (pthread_attr_init(&attr) != 0) + ABORT("pthread_attr_init failed"); + if (pthread_attr_get_np(pthread_self(), &attr) != 0) { + WARN("pthread_attr_get_np failed\n", 0); + (void)pthread_attr_destroy(&attr); + return GC_UNIMPLEMENTED; + } +# else /* HAVE_PTHREAD_GETATTR_NP */ + if (pthread_getattr_np(pthread_self(), &attr) != 0) { WARN("pthread_getattr_np failed\n", 0); return GC_UNIMPLEMENTED; - } + } +# endif if (pthread_attr_getstack(&attr, &(b -> mem_base), &size) != 0) { ABORT("pthread_attr_getstack failed"); } @@ -1286,7 +1358,7 @@ GC_INNER word GC_page_size = 0; return GC_SUCCESS; } # define HAVE_GET_STACK_BASE -#endif /* GC_LINUX_THREADS */ +#endif /* THREADS && (HAVE_PTHREAD_ATTR_GET_NP || HAVE_PTHREAD_GETATTR_NP) */ #if defined(GC_DARWIN_THREADS) && !defined(NO_PTHREAD_GET_STACKADDR_NP) # include @@ -1454,6 +1526,16 @@ void GC_register_data_segments(void) struct o32_obj seg; /* Current segment */ int nsegs; +# if defined(CPPCHECK) + hdrdos.padding[0] = 0; /* to prevent "field unused" warnings */ + hdr386.exe_format_level = 0; + hdr386.os = 0; + hdr386.padding1[0] = 0; + hdr386.padding2[0] = 0; + seg.pagemap = 0; + seg.mapsize = 0; + seg.reserved = 0; +# endif if (DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) { ABORT("DosGetInfoBlocks failed"); } @@ -1626,11 +1708,18 @@ void GC_register_data_segments(void) GC_INNER void GC_init_win32(void) { - /* Set GC_wnt. If we're running under win32s, assume that no DLLs */ - /* will be loaded. I doubt anyone still runs win32s, but... */ - DWORD v = GetVersion(); - GC_wnt = !(v & 0x80000000); - GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3); +# if defined(_WIN64) || (defined(_MSC_VER) && _MSC_VER >= 1800) + /* MS Visual Studio 2013 deprecates GetVersion, but on the other */ + /* hand it cannot be used to target pre-Win2K. */ + GC_wnt = TRUE; +# else + /* Set GC_wnt. If we're running under win32s, assume that no */ + /* DLLs will be loaded. I doubt anyone still runs win32s, but... */ + DWORD v = GetVersion(); + + GC_wnt = !(v & 0x80000000); + GC_no_win32_dlls |= ((!GC_wnt) && (v & 0xff) <= 3); +# endif # ifdef USE_MUNMAP if (GC_no_win32_dlls) { /* Turn off unmapping for safety (since may not work well with */ @@ -1646,15 +1735,15 @@ void GC_register_data_segments(void) STATIC ptr_t GC_least_described_address(ptr_t start) { MEMORY_BASIC_INFORMATION buf; - size_t result; LPVOID limit; ptr_t p; - LPVOID q; limit = GC_sysinfo.lpMinimumApplicationAddress; p = (ptr_t)((word)start & ~(GC_page_size - 1)); for (;;) { - q = (LPVOID)(p - GC_page_size); + size_t result; + LPVOID q = (LPVOID)(p - GC_page_size); + if ((word)q > (word)p /* underflow */ || (word)q < (word)limit) break; result = VirtualQuery(q, &buf, sizeof(buf)); if (result != sizeof(buf) || buf.AllocationBase == 0) break; @@ -1708,11 +1797,12 @@ void GC_register_data_segments(void) GC_INNER void GC_add_current_malloc_heap(void) { - struct GC_malloc_heap_list *new_l = + struct GC_malloc_heap_list *new_l = (struct GC_malloc_heap_list *) malloc(sizeof(struct GC_malloc_heap_list)); - void * candidate = GC_get_allocation_base(new_l); + void *candidate; - if (new_l == 0) return; + if (NULL == new_l) return; + candidate = GC_get_allocation_base(new_l); if (GC_is_malloc_heap_base(candidate)) { /* Try a little harder to find malloc heap. */ size_t req_size = 10000; @@ -1765,16 +1855,17 @@ void GC_register_data_segments(void) STATIC void GC_register_root_section(ptr_t static_root) { MEMORY_BASIC_INFORMATION buf; - size_t result; - DWORD protect; LPVOID p; char * base; - char * limit, * new_limit; + char * limit; if (!GC_no_win32_dlls) return; p = base = limit = GC_least_described_address(static_root); while ((word)p < (word)GC_sysinfo.lpMaximumApplicationAddress) { - result = VirtualQuery(p, &buf, sizeof(buf)); + size_t result = VirtualQuery(p, &buf, sizeof(buf)); + char * new_limit; + DWORD protect; + if (result != sizeof(buf) || buf.AllocationBase == 0 || GC_is_heap_base(buf.AllocationBase)) break; new_limit = (char *)p + buf.RegionSize; @@ -1806,12 +1897,12 @@ void GC_register_data_segments(void) # else /* !OS2 && !Windows */ -# if (defined(SVR4) || defined(AUX) || defined(DGUX) \ +# if (defined(SVR4) || defined(AIX) || defined(DGUX) \ || (defined(LINUX) && defined(SPARC))) && !defined(PCR) ptr_t GC_SysVGetDataStart(size_t max_page_size, ptr_t etext_addr) { word text_end = ((word)(etext_addr) + sizeof(word) - 1) - & ~(sizeof(word) - 1); + & ~(word)(sizeof(word) - 1); /* etext rounded to word boundary */ word next_page = ((text_end + (word)max_page_size - 1) & ~((word)max_page_size - 1)); @@ -1823,7 +1914,17 @@ void GC_register_data_segments(void) GC_setup_temporary_fault_handler(); if (SETJMP(GC_jmp_buf) == 0) { /* Try writing to the address. */ - *result = *result; +# ifdef AO_HAVE_fetch_and_add + volatile AO_t zero = 0; + (void)AO_fetch_and_add((volatile AO_t *)result, zero); +# else + /* Fallback to non-atomic fetch-and-store. */ + char v = *result; +# if defined(CPPCHECK) + GC_noop1((word)&v); +# endif + *result = v; +# endif GC_reset_fault_handler(); } else { GC_reset_fault_handler(); @@ -1831,25 +1932,24 @@ void GC_register_data_segments(void) /* This is known to happen under Solaris 2.4 + gcc, which place */ /* string constants in the text segment, but after etext. */ /* Use plan B. Note that we now know there is a gap between */ - /* text and data segments, so plan A bought us something. */ - result = (char *)GC_find_limit((ptr_t)(DATAEND), FALSE); + /* text and data segments, so plan A brought us something. */ + result = (char *)GC_find_limit(DATAEND, FALSE); } return((ptr_t)result); } # endif -# if defined(FREEBSD) && !defined(PCR) && (defined(I386) || defined(X86_64) \ - || defined(powerpc) || defined(__powerpc__)) - +#ifdef DATASTART_USES_BSDGETDATASTART /* Its unclear whether this should be identical to the above, or */ /* whether it should apply to non-X86 architectures. */ /* For now we don't assume that there is always an empty page after */ /* etext. But in some cases there actually seems to be slightly more. */ /* This also deals with holes between read-only data and writable data. */ -ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr) -{ + GC_INNER ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, + ptr_t etext_addr) + { word text_end = ((word)(etext_addr) + sizeof(word) - 1) - & ~(sizeof(word) - 1); + & ~(word)(sizeof(word) - 1); /* etext rounded to word boundary */ volatile word next_page = (text_end + (word)max_page_size - 1) & ~((word)max_page_size - 1); @@ -1858,19 +1958,17 @@ ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr) if (SETJMP(GC_jmp_buf) == 0) { /* Try reading at the address. */ /* This should happen before there is another thread. */ - for (; next_page < (word)(DATAEND); next_page += (word)max_page_size) + for (; next_page < (word)DATAEND; next_page += (word)max_page_size) *(volatile char *)next_page; GC_reset_fault_handler(); } else { GC_reset_fault_handler(); /* As above, we go to plan B */ - result = GC_find_limit((ptr_t)(DATAEND), FALSE); + result = GC_find_limit(DATAEND, FALSE); } return(result); -} - -# endif /* FREEBSD */ - + } +#endif /* DATASTART_USES_BSDGETDATASTART */ #ifdef AMIGA @@ -1886,12 +1984,15 @@ ptr_t GC_FreeBSDGetDataStart(size_t max_page_size, ptr_t etext_addr) void GC_register_data_segments(void) { ptr_t region_start = DATASTART; - ptr_t region_end; + if ((word)region_start - 1U >= (word)DATAEND) + ABORT_ARG2("Wrong DATASTART/END pair", + ": %p .. %p", (void *)region_start, (void *)DATAEND); for (;;) { - region_end = GC_find_limit_openbsd(region_start, DATAEND); + ptr_t region_end = GC_find_limit_openbsd(region_start, DATAEND); + GC_add_roots_inner(region_start, region_end, FALSE); - if ((word)region_end >= (word)(DATAEND)) + if ((word)region_end >= (word)DATAEND) break; region_start = GC_skip_hole_openbsd(region_end, DATAEND); } @@ -1913,14 +2014,22 @@ void GC_register_data_segments(void) GC_ASSERT(DATASTART); { ptr_t p = (ptr_t)sbrk(0); - if ((word)(DATASTART) < (word)p) + if ((word)DATASTART < (word)p) GC_add_roots_inner(DATASTART, p, FALSE); } # else - GC_ASSERT(DATASTART); - GC_add_roots_inner(DATASTART, (ptr_t)(DATAEND), FALSE); -# if defined(DATASTART2) - GC_add_roots_inner(DATASTART2, (ptr_t)(DATAEND2), FALSE); + if ((word)DATASTART - 1U >= (word)DATAEND) { + /* Subtract one to check also for NULL */ + /* without a compiler warning. */ + ABORT_ARG2("Wrong DATASTART/END pair", + ": %p .. %p", (void *)DATASTART, (void *)DATAEND); + } + GC_add_roots_inner(DATASTART, DATAEND, FALSE); +# ifdef GC_HAVE_DATAREGION2 + if ((word)DATASTART2 - 1U >= (word)DATAEND2) + ABORT_ARG2("Wrong DATASTART/END2 pair", + ": %p .. %p", (void *)DATASTART2, (void *)DATAEND2); + GC_add_roots_inner(DATASTART2, DATAEND2, FALSE); # endif # endif # endif @@ -1989,25 +2098,21 @@ void GC_register_data_segments(void) #ifdef USE_MMAP_ANON # define zero_fd -1 -# if defined(MAP_ANONYMOUS) +# if defined(MAP_ANONYMOUS) && !defined(CPPCHECK) # define OPT_MAP_ANON MAP_ANONYMOUS # else # define OPT_MAP_ANON MAP_ANON # endif #else - static int zero_fd; + static int zero_fd = -1; # define OPT_MAP_ANON 0 #endif -#ifndef HEAP_START -# define HEAP_START ((ptr_t)0) -#endif - #ifdef SYMBIAN extern char* GC_get_private_path_and_zero_file(void); #endif -STATIC ptr_t GC_unix_mmap_get_mem(word bytes) +STATIC ptr_t GC_unix_mmap_get_mem(size_t bytes) { void *result; static ptr_t last_addr = HEAP_START; @@ -2017,16 +2122,19 @@ STATIC ptr_t GC_unix_mmap_get_mem(word bytes) if (!EXPECT(initialized, TRUE)) { # ifdef SYMBIAN - char* path = GC_get_private_path_and_zero_file(); - zero_fd = open(path, O_RDWR | O_CREAT, 0666); - free(path); + char *path = GC_get_private_path_and_zero_file(); + if (path != NULL) { + zero_fd = open(path, O_RDWR | O_CREAT, 0666); + free(path); + } # else zero_fd = open("/dev/zero", O_RDONLY); # endif if (zero_fd == -1) ABORT("Could not open /dev/zero"); + if (fcntl(zero_fd, F_SETFD, FD_CLOEXEC) == -1) + WARN("Could not set FD_CLOEXEC for /dev/zero\n", 0); - fcntl(zero_fd, F_SETFD, FD_CLOEXEC); initialized = TRUE; } # endif @@ -2038,13 +2146,14 @@ STATIC ptr_t GC_unix_mmap_get_mem(word bytes) # undef IGNORE_PAGES_EXECUTABLE if (result == MAP_FAILED) return(0); - last_addr = (ptr_t)ROUNDUP_PAGESIZE((word)result + bytes); + last_addr = (ptr_t)(((word)result + bytes + GC_page_size - 1) + & ~(GC_page_size - 1)); # if !defined(LINUX) if (last_addr == 0) { /* Oops. We got the end of the address space. This isn't */ /* usable by arbitrary C code, since one-past-end pointers */ /* don't work, so we discard it and try again. */ - munmap(result, (size_t)(-GC_page_size) - (size_t)result); + munmap(result, ~GC_page_size - (size_t)result + 1); /* Leave last page mapped, so we can't repeat. */ return GC_unix_mmap_get_mem(bytes); } @@ -2060,13 +2169,13 @@ STATIC ptr_t GC_unix_mmap_get_mem(word bytes) # endif /* MMAP_SUPPORTED */ #if defined(USE_MMAP) - ptr_t GC_unix_get_mem(word bytes) + ptr_t GC_unix_get_mem(size_t bytes) { return GC_unix_mmap_get_mem(bytes); } #else /* !USE_MMAP */ -STATIC ptr_t GC_unix_sbrk_get_mem(word bytes) +STATIC ptr_t GC_unix_sbrk_get_mem(size_t bytes) { ptr_t result; # ifdef IRIX5 @@ -2083,7 +2192,7 @@ STATIC ptr_t GC_unix_sbrk_get_mem(word bytes) goto out; } if (lsbs != 0) { - if((ptr_t)sbrk(GC_page_size - lsbs) == (ptr_t)(-1)) { + if((ptr_t)sbrk((SBRK_ARG_T)GC_page_size - lsbs) == (ptr_t)(-1)) { result = 0; goto out; } @@ -2107,7 +2216,7 @@ STATIC ptr_t GC_unix_sbrk_get_mem(word bytes) return(result); } -ptr_t GC_unix_get_mem(word bytes) +ptr_t GC_unix_get_mem(size_t bytes) { # if defined(MMAP_SUPPORTED) /* By default, we try both sbrk and mmap, in that order. */ @@ -2153,7 +2262,7 @@ void * os2_alloc(size_t bytes) # endif /* OS2 */ #ifdef MSWINCE - ptr_t GC_wince_get_mem(word bytes) + ptr_t GC_wince_get_mem(size_t bytes) { ptr_t result = 0; /* initialized to prevent warning. */ word i; @@ -2172,8 +2281,9 @@ void * os2_alloc(size_t bytes) if (i == GC_n_heap_bases) { /* Reserve more pages */ - word res_bytes = (bytes + GC_sysinfo.dwAllocationGranularity-1) - & ~(GC_sysinfo.dwAllocationGranularity-1); + size_t res_bytes = + SIZET_SAT_ADD(bytes, (size_t)GC_sysinfo.dwAllocationGranularity-1) + & ~((size_t)GC_sysinfo.dwAllocationGranularity-1); /* If we ever support MPROTECT_VDB here, we will probably need to */ /* ensure that res_bytes is strictly > bytes, so that VirtualProtect */ /* never spans regions. It seems to be OK for a VirtualFree */ @@ -2214,7 +2324,8 @@ void * os2_alloc(size_t bytes) # define GLOBAL_ALLOC_TEST GC_no_win32_dlls # endif -# if defined(GC_USE_MEM_TOP_DOWN) && defined(USE_WINALLOC) +# if (defined(GC_USE_MEM_TOP_DOWN) && defined(USE_WINALLOC)) \ + || defined(CPPCHECK) DWORD GC_mem_top_down = MEM_TOP_DOWN; /* Use GC_USE_MEM_TOP_DOWN for better 64-bit */ /* testing. Otherwise all addresses tend to */ @@ -2223,7 +2334,7 @@ void * os2_alloc(size_t bytes) # define GC_mem_top_down 0 # endif /* !GC_USE_MEM_TOP_DOWN */ - ptr_t GC_win32_get_mem(word bytes) + ptr_t GC_win32_get_mem(size_t bytes) { ptr_t result; @@ -2235,8 +2346,10 @@ void * os2_alloc(size_t bytes) /* VirtualAlloc doesn't like PAGE_EXECUTE_READWRITE. */ /* There are also unconfirmed rumors of other */ /* problems, so we dodge the issue. */ - result = (ptr_t) GlobalAlloc(0, bytes + HBLKSIZE); - result = (ptr_t)(((word)result + HBLKSIZE - 1) & ~(HBLKSIZE-1)); + result = (ptr_t)GlobalAlloc(0, SIZET_SAT_ADD(bytes, HBLKSIZE)); + /* Align it at HBLKSIZE boundary. */ + result = (ptr_t)(((word)result + HBLKSIZE - 1) + & ~(word)(HBLKSIZE - 1)); } else # endif /* else */ { @@ -2265,12 +2378,13 @@ void * os2_alloc(size_t bytes) /* available. Otherwise we waste resources or possibly */ /* cause VirtualAlloc to fail (observed in Windows 2000 */ /* SP2). */ - result = (ptr_t) VirtualAlloc(NULL, bytes + VIRTUAL_ALLOC_PAD, - GetWriteWatch_alloc_flag + result = (ptr_t) VirtualAlloc(NULL, + SIZET_SAT_ADD(bytes, VIRTUAL_ALLOC_PAD), + GetWriteWatch_alloc_flag | (MEM_COMMIT | MEM_RESERVE) | GC_mem_top_down, - GC_pages_executable ? PAGE_EXECUTE_READWRITE : - PAGE_READWRITE); + GC_pages_executable ? PAGE_EXECUTE_READWRITE : + PAGE_READWRITE); # undef IGNORE_PAGES_EXECUTABLE } # endif /* USE_WINALLOC */ @@ -2315,6 +2429,19 @@ void * os2_alloc(size_t bytes) # undef GC_AMIGA_AM #endif +#if defined(HAIKU) +# include + ptr_t GC_haiku_get_mem(size_t bytes) + { + void* mem; + + GC_ASSERT(GC_page_size != 0); + if (posix_memalign(&mem, GC_page_size, bytes) == 0) + return mem; + return NULL; + } +#endif /* HAIKU */ + #ifdef USE_MUNMAP /* For now, this only works on Win32/WinCE and some Unix-like */ @@ -2333,7 +2460,8 @@ void * os2_alloc(size_t bytes) /* Return 0 if the block is too small to make this feasible. */ STATIC ptr_t GC_unmap_start(ptr_t start, size_t bytes) { - ptr_t result = (ptr_t)ROUNDUP_PAGESIZE((word)start); + ptr_t result = (ptr_t)(((word)start + GC_page_size - 1) + & ~(GC_page_size - 1)); if ((word)(result + GC_page_size) > (word)(start + bytes)) return 0; return result; @@ -2367,7 +2495,7 @@ GC_INNER void GC_unmap(ptr_t start, size_t bytes) # ifdef USE_WINALLOC while (len != 0) { MEMORY_BASIC_INFORMATION mem_info; - GC_word free_len; + word free_len; if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info)) != sizeof(mem_info)) @@ -2383,13 +2511,25 @@ GC_INNER void GC_unmap(ptr_t start, size_t bytes) /* We immediately remap it to prevent an intervening mmap from */ /* accidentally grabbing the same address space. */ { - void * result; +# ifdef CYGWIN32 + /* Calling mmap() with the new protection flags on an */ + /* existing memory map with MAP_FIXED is broken on Cygwin. */ + /* However, calling mprotect() on the given address range */ + /* with PROT_NONE seems to work fine. */ + if (mprotect(start_addr, len, PROT_NONE)) + ABORT("mprotect(PROT_NONE) failed"); +# else + void * result = mmap(start_addr, len, PROT_NONE, + MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON, + zero_fd, 0/* offset */); - result = mmap(start_addr, len, PROT_NONE, - MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON, - zero_fd, 0/* offset */); - if (result != (void *)start_addr) - ABORT("mmap(PROT_NONE) failed"); + if (result != (void *)start_addr) + ABORT("mmap(PROT_NONE) failed"); +# if defined(CPPCHECK) || defined(LINT2) + /* Explicitly store the resource handle to a global variable. */ + GC_noop1((word)result); +# endif +# endif /* !CYGWIN32 */ } GC_unmapped_bytes += len; # endif @@ -2406,7 +2546,7 @@ GC_INNER void GC_remap(ptr_t start, size_t bytes) # ifdef USE_WINALLOC while (len != 0) { MEMORY_BASIC_INFORMATION mem_info; - GC_word alloc_len; + word alloc_len; ptr_t result; if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info)) @@ -2424,6 +2564,9 @@ GC_INNER void GC_remap(ptr_t start, size_t bytes) ABORT("VirtualAlloc remapping failed"); } } +# ifdef LINT2 + GC_noop1((word)result); +# endif GC_unmapped_bytes -= alloc_len; start_addr += alloc_len; len -= alloc_len; @@ -2433,18 +2576,21 @@ GC_INNER void GC_remap(ptr_t start, size_t bytes) { # ifdef NACL /* NaCl does not expose mprotect, but mmap should work fine. */ - void *mmap_result = mmap(start_addr, len, (PROT_READ | PROT_WRITE) + void *result = mmap(start_addr, len, (PROT_READ | PROT_WRITE) | (GC_pages_executable ? PROT_EXEC : 0), MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON, zero_fd, 0 /* offset */); - if (mmap_result != (void *)start_addr) + if (result != (void *)start_addr) ABORT("mmap as mprotect failed"); +# if defined(CPPCHECK) || defined(LINT2) + GC_noop1((word)result); +# endif # else if (mprotect(start_addr, len, (PROT_READ | PROT_WRITE) | (GC_pages_executable ? PROT_EXEC : 0)) != 0) { ABORT_ARG3("mprotect remapping failed", " at %p (length %lu), errcode= %d", - start_addr, (unsigned long)len, errno); + (void *)start_addr, (unsigned long)len, errno); } # endif /* !NACL */ } @@ -2475,7 +2621,7 @@ GC_INNER void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, # ifdef USE_WINALLOC while (len != 0) { MEMORY_BASIC_INFORMATION mem_info; - GC_word free_len; + word free_len; if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info)) != sizeof(mem_info)) @@ -2490,14 +2636,22 @@ GC_INNER void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, # else if (len != 0) { /* Immediately remap as above. */ - void * result; - result = mmap(start_addr, len, PROT_NONE, - MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON, - zero_fd, 0/* offset */); - if (result != (void *)start_addr) - ABORT("mmap(PROT_NONE) failed"); +# ifdef CYGWIN32 + if (mprotect(start_addr, len, PROT_NONE)) + ABORT("mprotect(PROT_NONE) failed"); +# else + void * result = mmap(start_addr, len, PROT_NONE, + MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON, + zero_fd, 0/* offset */); + + if (result != (void *)start_addr) + ABORT("mmap(PROT_NONE) failed"); +# if defined(CPPCHECK) || defined(LINT2) + GC_noop1((word)result); +# endif +# endif /* !CYGWIN32 */ + GC_unmapped_bytes += len; } - GC_unmapped_bytes += len; # endif } @@ -2623,32 +2777,32 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) * are running on Windows 95, Windows 2000 or earlier), * MPROTECT_VDB may be defined as a fallback strategy. */ -#ifndef GC_DISABLE_INCREMENTAL - GC_INNER GC_bool GC_dirty_maintained = FALSE; -#endif -#if defined(PROC_VDB) || defined(GWW_VDB) - /* Add all pages in pht2 to pht1 */ - STATIC void GC_or_pages(page_hash_table pht1, page_hash_table pht2) - { - register unsigned i; - for (i = 0; i < PHT_SIZE; i++) pht1[i] |= pht2[i]; - } - -# ifdef MPROTECT_VDB - STATIC GC_bool GC_gww_page_was_dirty(struct hblk * h) -# else - GC_INNER GC_bool GC_page_was_dirty(struct hblk * h) -# endif +#if defined(GWW_VDB) || defined(MPROTECT_VDB) || defined(PROC_VDB) \ + || defined(MANUAL_VDB) + /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */ + /* If the actual page size is different, this returns TRUE if any */ + /* of the pages overlapping h are dirty. This routine may err on the */ + /* side of labeling pages as dirty (and this implementation does). */ + GC_INNER GC_bool GC_page_was_dirty(struct hblk * h) { register word index; + if (HDR(h) == 0) return TRUE; index = PHT_HASH(h); return get_pht_entry_from_index(GC_grungy_pages, index); } +#endif + +#if (defined(CHECKSUMS) && defined(GWW_VDB)) || defined(PROC_VDB) + /* Add all pages in pht2 to pht1. */ + STATIC void GC_or_pages(page_hash_table pht1, page_hash_table pht2) + { + register unsigned i; + for (i = 0; i < PHT_SIZE; i++) pht1[i] |= pht2[i]; + } -# if defined(CHECKSUMS) || defined(PROC_VDB) /* Used only if GWW_VDB. */ # ifdef MPROTECT_VDB STATIC GC_bool GC_gww_page_was_ever_dirty(struct hblk * h) @@ -2662,16 +2816,15 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) index = PHT_HASH(h); return get_pht_entry_from_index(GC_written_pages, index); } -# endif /* CHECKSUMS || PROC_VDB */ +#endif /* CHECKSUMS && GWW_VDB || PROC_VDB */ -# ifndef MPROTECT_VDB +#if ((defined(GWW_VDB) || defined(PROC_VDB)) && !defined(MPROTECT_VDB)) \ + || defined(MANUAL_VDB) || defined(DEFAULT_VDB) /* Ignore write hints. They don't help us here. */ GC_INNER void GC_remove_protection(struct hblk * h GC_ATTR_UNUSED, word nblocks GC_ATTR_UNUSED, GC_bool is_ptrfree GC_ATTR_UNUSED) {} -# endif - -#endif /* PROC_VDB || GWW_VDB */ +#endif #ifdef GWW_VDB @@ -2680,19 +2833,15 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) /* and everything is dirty. */ static PVOID gww_buf[GC_GWW_BUF_LEN]; -# ifdef MPROTECT_VDB +# ifndef MPROTECT_VDB +# define GC_gww_dirty_init GC_dirty_init +# endif + GC_INNER GC_bool GC_gww_dirty_init(void) { detect_GetWriteWatch(); return GC_GWW_AVAILABLE(); } -# else - GC_INNER void GC_dirty_init(void) - { - detect_GetWriteWatch(); - GC_dirty_maintained = GC_GWW_AVAILABLE(); - } -# endif /* !MPROTECT_VDB */ # ifdef MPROTECT_VDB STATIC void GC_gww_read_dirty(void) @@ -2708,10 +2857,9 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) GC_ULONG_PTR count; do { - PVOID * pages, * pages_end; + PVOID * pages = gww_buf; DWORD page_size; - pages = gww_buf; count = GC_GWW_BUF_LEN; /* GetWriteWatch is documented as returning non-zero when it */ /* fails, but the documentation doesn't explicitly say why it */ @@ -2751,7 +2899,8 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) } count = 1; /* Done with this section. */ } else /* succeeded */ { - pages_end = pages + count; + PVOID * pages_end = pages + count; + while (pages != pages_end) { struct hblk * h = (struct hblk *) *pages++; struct hblk * h_end = (struct hblk *) ((char *) h + page_size); @@ -2766,7 +2915,9 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) /* up. But that should still be handled correctly. */ } - GC_or_pages(GC_written_pages, GC_grungy_pages); +# ifdef CHECKSUMS + GC_or_pages(GC_written_pages, GC_grungy_pages); +# endif } #endif /* GWW_VDB */ @@ -2777,10 +2928,10 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) /* written. */ /* Initialize virtual dirty bit implementation. */ - GC_INNER void GC_dirty_init(void) + GC_INNER GC_bool GC_dirty_init(void) { GC_VERBOSE_LOG_PRINTF("Initializing DEFAULT_VDB...\n"); - GC_dirty_maintained = TRUE; + return TRUE; } /* Retrieve system dirty bits for heap to a local buffer. */ @@ -2808,25 +2959,15 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) } # endif /* CHECKSUMS */ - /* A call that: */ - /* I) hints that [h, h+nblocks) is about to be written. */ - /* II) guarantees that protection is removed. */ - /* (I) may speed up some dirty bit implementations. */ - /* (II) may be essential if we need to ensure that */ - /* pointer-free system call buffers in the heap are */ - /* not protected. */ - GC_INNER void GC_remove_protection(struct hblk * h GC_ATTR_UNUSED, - word nblocks GC_ATTR_UNUSED, - GC_bool is_ptrfree GC_ATTR_UNUSED) {} #endif /* DEFAULT_VDB */ #ifdef MANUAL_VDB /* Initialize virtual dirty bit implementation. */ - GC_INNER void GC_dirty_init(void) + GC_INNER GC_bool GC_dirty_init(void) { GC_VERBOSE_LOG_PRINTF("Initializing MANUAL_VDB...\n"); /* GC_dirty_pages and GC_grungy_pages are already cleared. */ - GC_dirty_maintained = TRUE; + return TRUE; } /* Retrieve system dirty bits for heap to a local buffer. */ @@ -2838,31 +2979,17 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) BZERO((word *)GC_dirty_pages, (sizeof GC_dirty_pages)); } - /* Is the HBLKSIZE sized page at h marked dirty in the local buffer? */ - /* If the actual page size is different, this returns TRUE if any */ - /* of the pages overlapping h are dirty. This routine may err on the */ - /* side of labeling pages as dirty (and this implementation does). */ - GC_INNER GC_bool GC_page_was_dirty(struct hblk *h) - { - register word index = PHT_HASH(h); - return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index)); - } - # define async_set_pht_entry_from_index(db, index) \ set_pht_entry_from_index(db, index) /* for now */ /* Mark the page containing p as dirty. Logically, this dirties the */ /* entire object. */ - void GC_dirty(ptr_t p) + GC_INNER void GC_dirty_inner(const void *p) { word index = PHT_HASH(p); async_set_pht_entry_from_index(GC_dirty_pages, index); } - GC_INNER void GC_remove_protection(struct hblk * h GC_ATTR_UNUSED, - word nblocks GC_ATTR_UNUSED, - GC_bool is_ptrfree GC_ATTR_UNUSED) {} - # ifdef CHECKSUMS /* Could any valid GC heap pointer ever have been written to this page? */ GC_INNER GC_bool GC_page_was_ever_dirty(struct hblk * h GC_ATTR_UNUSED) @@ -2911,7 +3038,9 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) # elif !defined(USE_WINALLOC) # include # include -# include +# if !defined(HAIKU) +# include +# endif # define PROTECT(addr, len) \ if (mprotect((caddr_t)(addr), (size_t)(len), \ @@ -3038,12 +3167,12 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) set_pht_entry_from_index(db, index) #endif /* !THREADS */ -#ifdef CHECKSUMS - void GC_record_fault(struct hblk * h); /* from checksums.c */ -#endif - #ifndef DARWIN +# ifdef CHECKSUMS + void GC_record_fault(struct hblk * h); /* from checksums.c */ +# endif + # if !defined(MSWIN32) && !defined(MSWINCE) # include # if defined(FREEBSD) || defined(HURD) || defined(HPUX) @@ -3056,7 +3185,9 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) # ifndef SEGV_ACCERR # define SEGV_ACCERR 2 # endif -# if defined(POWERPC) +# if defined(AARCH64) || defined(ARM32) || defined(MIPS) +# define CODE_OK (si -> si_code == SEGV_ACCERR) +# elif defined(POWERPC) # define AIM /* Pretend that we're AIM. */ # include # define CODE_OK (si -> si_code == EXC_DSI \ @@ -3069,7 +3200,7 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) # define CODE_OK (si -> si_code == 2 /* experimentally determined */) # elif defined(IRIX5) # define CODE_OK (si -> si_code == EACCES) -# elif defined(HURD) +# elif defined(HAIKU) || defined(HURD) # define CODE_OK TRUE # elif defined(LINUX) # define CODE_OK TRUE @@ -3104,16 +3235,16 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) char * addr = (char *) (exc_info -> ExceptionRecord -> ExceptionInformation[1]); # endif - unsigned i; if (SIG_OK && CODE_OK) { register struct hblk * h = (struct hblk *)((word)addr & ~(GC_page_size-1)); GC_bool in_allocd_block; + size_t i; + # ifdef CHECKSUMS GC_record_fault(h); # endif - # ifdef SUNOS5SIGS /* Address is only within the correct physical page. */ in_allocd_block = FALSE; @@ -3151,10 +3282,10 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) } # endif - if (old_handler == (SIG_HNDLR_PTR)SIG_DFL) { + if (old_handler == (SIG_HNDLR_PTR)(signed_word)SIG_DFL) { # if !defined(MSWIN32) && !defined(MSWINCE) ABORT_ARG1("Unexpected bus error or segmentation fault", - " at %p", addr); + " at %p", (void *)addr); # else return(EXCEPTION_CONTINUE_SEARCH); # endif @@ -3171,7 +3302,7 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) ((SIG_HNDLR_PTR)old_handler) (sig, si, raw_sc); else /* FIXME: should pass nonstandard args as well. */ - ((PLAIN_HNDLR_PTR)old_handler) (sig); + ((PLAIN_HNDLR_PTR)(signed_word)old_handler)(sig); return; # endif } @@ -3189,7 +3320,7 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) /* and then to have the thread stopping code set the dirty */ /* flag, if necessary. */ for (i = 0; i < divHBLKSZ(GC_page_size); i++) { - size_t index = PHT_HASH(h+i); + word index = PHT_HASH(h+i); async_set_pht_entry_from_index(GC_dirty_pages, index); } @@ -3205,7 +3336,7 @@ GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void) return EXCEPTION_CONTINUE_SEARCH; # else ABORT_ARG1("Unexpected bus error or segmentation fault", - " at %p", addr); + " at %p", (void *)addr); # endif } @@ -3233,16 +3364,18 @@ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, # if defined(GWW_VDB) if (GC_GWW_AVAILABLE()) return; # endif - if (!GC_dirty_maintained) return; + if (!GC_incremental) return; h_trunc = (struct hblk *)((word)h & ~(GC_page_size-1)); - h_end = (struct hblk *)ROUNDUP_PAGESIZE((word)(h + nblocks)); + h_end = (struct hblk *)(((word)(h + nblocks) + GC_page_size - 1) + & ~(GC_page_size - 1)); if (h_end == h_trunc + 1 && get_pht_entry_from_index(GC_dirty_pages, PHT_HASH(h_trunc))) { /* already marked dirty, and hence unprotected. */ return; } for (current = h_trunc; (word)current < (word)h_end; ++current) { - size_t index = PHT_HASH(current); + word index = PHT_HASH(current); + if (!is_ptrfree || (word)current < (word)h || (word)current >= (word)(h + nblocks)) { async_set_pht_entry_from_index(GC_dirty_pages, index); @@ -3252,7 +3385,7 @@ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, } #if !defined(DARWIN) - GC_INNER void GC_dirty_init(void) + GC_INNER GC_bool GC_dirty_init(void) { # if !defined(MSWIN32) && !defined(MSWINCE) struct sigaction act, oldact; @@ -3269,7 +3402,6 @@ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, # endif /* !MSWIN32 */ GC_VERBOSE_LOG_PRINTF( "Initializing mprotect virtual dirty bit implementation\n"); - GC_dirty_maintained = TRUE; if (GC_page_size % HBLKSIZE != 0) { ABORT("Page size not multiple of HBLKSIZE"); } @@ -3288,18 +3420,18 @@ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, GC_old_segv_handler = oldact.sa_sigaction; GC_old_segv_handler_used_si = TRUE; } else { - GC_old_segv_handler = (SIG_HNDLR_PTR)oldact.sa_handler; + GC_old_segv_handler = (SIG_HNDLR_PTR)(signed_word)oldact.sa_handler; GC_old_segv_handler_used_si = FALSE; } - if (GC_old_segv_handler == (SIG_HNDLR_PTR)SIG_IGN) { + if (GC_old_segv_handler == (SIG_HNDLR_PTR)(signed_word)SIG_IGN) { WARN("Previously ignored segmentation violation!?\n", 0); - GC_old_segv_handler = (SIG_HNDLR_PTR)SIG_DFL; + GC_old_segv_handler = (SIG_HNDLR_PTR)(signed_word)SIG_DFL; } - if (GC_old_segv_handler != (SIG_HNDLR_PTR)SIG_DFL) { + if (GC_old_segv_handler != (SIG_HNDLR_PTR)(signed_word)SIG_DFL) { GC_VERBOSE_LOG_PRINTF("Replaced other SIGSEGV handler\n"); } # if defined(HPUX) || defined(LINUX) || defined(HURD) \ - || (defined(FREEBSD) && defined(SUNOS5SIGS)) + || (defined(FREEBSD) && (defined(__GLIBC__) || defined(SUNOS5SIGS))) sigaction(SIGBUS, &act, &oldact); if ((oldact.sa_flags & SA_SIGINFO) != 0) { GC_old_bus_handler = oldact.sa_sigaction; @@ -3307,26 +3439,26 @@ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, GC_old_bus_handler_used_si = TRUE; # endif } else { - GC_old_bus_handler = (SIG_HNDLR_PTR)oldact.sa_handler; + GC_old_bus_handler = (SIG_HNDLR_PTR)(signed_word)oldact.sa_handler; # if !defined(LINUX) GC_old_bus_handler_used_si = FALSE; # endif } - if (GC_old_bus_handler == (SIG_HNDLR_PTR)SIG_IGN) { + if (GC_old_bus_handler == (SIG_HNDLR_PTR)(signed_word)SIG_IGN) { WARN("Previously ignored bus error!?\n", 0); # if !defined(LINUX) - GC_old_bus_handler = (SIG_HNDLR_PTR)SIG_DFL; + GC_old_bus_handler = (SIG_HNDLR_PTR)(signed_word)SIG_DFL; # else /* GC_old_bus_handler is not used by GC_write_fault_handler. */ # endif - } else if (GC_old_bus_handler != (SIG_HNDLR_PTR)SIG_DFL) { + } else if (GC_old_bus_handler != (SIG_HNDLR_PTR)(signed_word)SIG_DFL) { GC_VERBOSE_LOG_PRINTF("Replaced other SIGBUS handler\n"); } # endif /* HPUX || LINUX || HURD || (FREEBSD && SUNOS5SIGS) */ # endif /* ! MS windows */ # if defined(GWW_VDB) if (GC_gww_dirty_init()) - return; + return TRUE; # endif # if defined(MSWIN32) GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler); @@ -3339,6 +3471,10 @@ GC_INNER void GC_remove_protection(struct hblk *h, word nblocks, /* MPROTECT_VDB is unsupported for WinCE at present. */ /* FIXME: implement it (if possible). */ # endif +# if defined(CPPCHECK) && defined(ADDRESS_SANITIZER) + GC_noop1((word)&__asan_default_options); +# endif + return TRUE; } #endif /* !DARWIN */ @@ -3359,20 +3495,21 @@ GC_API int GC_CALL GC_incremental_protection_needs(void) STATIC void GC_protect_heap(void) { - ptr_t start; - size_t len; - struct hblk * current; - struct hblk * current_start; /* Start of block to be protected. */ - struct hblk * limit; unsigned i; GC_bool protect_all = - (0 != (GC_incremental_protection_needs() & GC_PROTECTS_PTRFREE_HEAP)); + (0 != (GC_incremental_protection_needs() & GC_PROTECTS_PTRFREE_HEAP)); + for (i = 0; i < GC_n_heap_sects; i++) { - start = GC_heap_sects[i].hs_start; - len = GC_heap_sects[i].hs_bytes; + ptr_t start = GC_heap_sects[i].hs_start; + size_t len = GC_heap_sects[i].hs_bytes; + if (protect_all) { PROTECT(start, len); } else { + struct hblk * current; + struct hblk * current_start; /* Start of block to be protected. */ + struct hblk * limit; + GC_ASSERT(PAGE_ALIGNED(len)); GC_ASSERT(PAGE_ALIGNED(start)); current_start = current = (struct hblk *)start; @@ -3433,19 +3570,6 @@ GC_INNER void GC_read_dirty(void) GC_protect_heap(); } -GC_INNER GC_bool GC_page_was_dirty(struct hblk *h) -{ - register word index; - -# if defined(GWW_VDB) - if (GC_GWW_AVAILABLE()) - return GC_gww_page_was_dirty(h); -# endif - - index = PHT_HASH(h); - return(HDR(h) == 0 || get_pht_entry_from_index(GC_grungy_pages, index)); -} - /* * Acquiring the allocation lock here is dangerous, since this * can be called from within GC_call_with_alloc_lock, and the cord @@ -3488,14 +3612,13 @@ GC_INNER GC_bool GC_page_was_dirty(struct hblk *h) # include # define INITIAL_BUF_SZ 16384 - STATIC word GC_proc_buf_size = INITIAL_BUF_SZ; + STATIC size_t GC_proc_buf_size = INITIAL_BUF_SZ; STATIC char *GC_proc_buf = NULL; STATIC int GC_proc_fd = 0; -GC_INNER void GC_dirty_init(void) +GC_INNER GC_bool GC_dirty_init(void) { - int fd; - char buf[30]; + char buf[40]; if (GC_bytes_allocd != 0 || GC_bytes_allocd_before_gc != 0) { memset(GC_written_pages, 0xff, sizeof(page_hash_table)); @@ -3504,24 +3627,20 @@ GC_INNER void GC_dirty_init(void) (unsigned long)(GC_bytes_allocd + GC_bytes_allocd_before_gc)); } - (void)snprintf(buf, sizeof(buf), "/proc/%ld", (long)getpid()); + (void)snprintf(buf, sizeof(buf), "/proc/%ld/pagedata", (long)getpid()); buf[sizeof(buf) - 1] = '\0'; - fd = open(buf, O_RDONLY); - if (fd < 0) { - ABORT("/proc open failed"); - } - GC_proc_fd = syscall(SYS_ioctl, fd, PIOCOPENPD, 0); - close(fd); - syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC); + GC_proc_fd = open(buf, O_RDONLY); if (GC_proc_fd < 0) { - WARN("/proc ioctl(PIOCOPENPD) failed", 0); - return; + WARN("/proc open failed; cannot enable GC incremental mode\n", 0); + return FALSE; } + if (syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC) == -1) + WARN("Could not set FD_CLOEXEC for /proc\n", 0); - GC_dirty_maintained = TRUE; GC_proc_buf = GC_scratch_alloc(GC_proc_buf_size); if (GC_proc_buf == NULL) ABORT("Insufficient space for /proc read"); + return TRUE; } # define READ read @@ -3529,24 +3648,20 @@ GC_INNER void GC_dirty_init(void) GC_INNER void GC_read_dirty(void) { int nmaps; - unsigned long npages; - unsigned pagesize; - ptr_t vaddr, limit; - struct prasmap * map; - char * bufp; + char * bufp = GC_proc_buf; int i; BZERO(GC_grungy_pages, sizeof(GC_grungy_pages)); - bufp = GC_proc_buf; if (READ(GC_proc_fd, bufp, GC_proc_buf_size) <= 0) { /* Retry with larger buffer. */ - word new_size = 2 * GC_proc_buf_size; + size_t new_size = 2 * GC_proc_buf_size; char *new_buf; WARN("/proc read failed: GC_proc_buf_size = %" WARN_PRIdPTR "\n", (signed_word)GC_proc_buf_size); new_buf = GC_scratch_alloc(new_size); if (new_buf != 0) { + GC_scratch_recycle_no_gww(bufp, GC_proc_buf_size); GC_proc_buf = bufp = new_buf; GC_proc_buf_size = new_size; } @@ -3567,14 +3682,16 @@ GC_INNER void GC_read_dirty(void) # endif bufp += sizeof(struct prpageheader); for (i = 0; i < nmaps; i++) { - map = (struct prasmap *)bufp; - vaddr = (ptr_t)(map -> pr_vaddr); - npages = map -> pr_npage; - pagesize = map -> pr_pagesize; + struct prasmap * map = (struct prasmap *)bufp; + ptr_t vaddr = (ptr_t)(map -> pr_vaddr); + unsigned long npages = map -> pr_npage; + unsigned pagesize = map -> pr_pagesize; + ptr_t limit; + # ifdef DEBUG_DIRTY_BITS GC_log_printf( "pr_vaddr= %p, npage= %lu, mflags= 0x%x, pagesize= 0x%x\n", - vaddr, npages, map->pr_mflags, pagesize); + (void *)vaddr, npages, map->pr_mflags, pagesize); # endif bufp += sizeof(struct prasmap); @@ -3584,7 +3701,7 @@ GC_INNER void GC_read_dirty(void) register struct hblk * h; ptr_t next_vaddr = vaddr + pagesize; # ifdef DEBUG_DIRTY_BITS - GC_log_printf("dirty page at: %p\n", vaddr); + GC_log_printf("dirty page at: %p\n", (void *)vaddr); # endif for (h = (struct hblk *)vaddr; (word)h < (word)next_vaddr; h++) { @@ -3593,10 +3710,11 @@ GC_INNER void GC_read_dirty(void) } } } - bufp = (char *)(((word)bufp + (sizeof(long)-1)) & ~(sizeof(long)-1)); + bufp = (char *)(((word)bufp + (sizeof(long)-1)) + & ~(word)(sizeof(long)-1)); } # ifdef DEBUG_DIRTY_BITS - GC_log_printf("Proc VDB read done.\n"); + GC_log_printf("Proc VDB read done\n"); # endif /* Update GC_written_pages. */ @@ -3618,9 +3736,8 @@ STATIC ptr_t GC_vd_base = NULL; /* Address corresponding to GC_grungy_bits[0] */ /* HBLKSIZE aligned. */ -GC_INNER void GC_dirty_init(void) +GC_INNER GC_bool GC_dirty_init(void) { - GC_dirty_maintained = TRUE; /* For the time being, we assume the heap generally grows up */ GC_vd_base = GC_heap_sects[0].hs_start; if (GC_vd_base == 0) { @@ -3630,6 +3747,7 @@ GC_INNER void GC_dirty_init(void) != PCR_ERes_okay) { ABORT("Dirty bit initialization failed"); } + return TRUE; } GC_INNER void GC_read_dirty(void) @@ -3873,6 +3991,10 @@ STATIC void *GC_mprotect_thread(void *arg) mach_msg_id_t id; if ((word)arg == (word)-1) return 0; /* to make compiler happy */ +# if defined(CPPCHECK) + reply.data[0] = 0; /* to prevent "field unused" warnings */ + msg.data[0] = 0; +# endif # if defined(THREADS) && !defined(GC_NO_THREADS_DISCOVERY) GC_darwin_register_mach_handler_thread(mach_thread_self()); @@ -3961,12 +4083,12 @@ STATIC void *GC_mprotect_thread(void *arg) ABORT("Got more than 8 SIGBUSs in a row!"); } else { GC_sigbus_count++; - WARN("Ignoring SIGBUS.\n", 0); + WARN("Ignoring SIGBUS\n", 0); } } #endif /* BROKEN_EXCEPTION_HANDLING */ -GC_INNER void GC_dirty_init(void) +GC_INNER GC_bool GC_dirty_init(void) { kern_return_t r; mach_port_t me; @@ -3978,13 +4100,13 @@ GC_INNER void GC_dirty_init(void) if (GC_handle_fork) { /* To both support GC incremental mode and GC functions usage in */ /* the forked child, pthread_atfork should be used to install */ - /* handlers that switch off GC_dirty_maintained in the child */ + /* handlers that switch off GC_incremental in the child */ /* gracefully (unprotecting all pages and clearing */ /* GC_mach_handler_thread). For now, we just disable incremental */ /* mode if fork() handling is requested by the client. */ - GC_COND_LOG_PRINTF("GC incremental mode disabled since fork()" - " handling requested\n"); - return; + WARN("Can't turn on GC incremental mode as fork()" + " handling requested\n", 0); + return FALSE; } # endif @@ -3992,9 +4114,8 @@ GC_INNER void GC_dirty_init(void) " virtual dirty bit implementation\n"); # ifdef BROKEN_EXCEPTION_HANDLING WARN("Enabling workarounds for various darwin " - "exception handling bugs.\n", 0); + "exception handling bugs\n", 0); # endif - GC_dirty_maintained = TRUE; if (GC_page_size % HBLKSIZE != 0) { ABORT("Page size not multiple of HBLKSIZE"); } @@ -4002,6 +4123,7 @@ GC_INNER void GC_dirty_init(void) GC_task_self = me = mach_task_self(); r = mach_port_allocate(me, MACH_PORT_RIGHT_RECEIVE, &GC_ports.exception); + /* TODO: WARN and return FALSE in case of a failure. */ if (r != KERN_SUCCESS) ABORT("mach_port_allocate failed (exception port)"); @@ -4051,11 +4173,12 @@ GC_INNER void GC_dirty_init(void) /* sa.sa_restorer is deprecated and should not be initialized. */ if (sigaction(SIGBUS, &sa, &oldsa) < 0) ABORT("sigaction failed"); - if ((SIG_HNDLR_PTR)oldsa.sa_handler != SIG_DFL) { + if (oldsa.sa_handler != (SIG_HNDLR_PTR)(signed_word)SIG_DFL) { GC_VERBOSE_LOG_PRINTF("Replaced other SIGBUS handler\n"); } } # endif /* BROKEN_EXCEPTION_HANDLING */ + return TRUE; } /* The source code for Apple's GDB was used as a reference for the */ @@ -4122,12 +4245,12 @@ STATIC kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task, # define DARWIN_EXC_STATE ARM_EXCEPTION_STATE # define DARWIN_EXC_STATE_COUNT ARM_EXCEPTION_STATE_COUNT # define DARWIN_EXC_STATE_T arm_exception_state_t -# define DARWIN_EXC_STATE_DAR THREAD_FLD(far) +# define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(far) #elif defined(AARCH64) # define DARWIN_EXC_STATE ARM_EXCEPTION_STATE64 # define DARWIN_EXC_STATE_COUNT ARM_EXCEPTION_STATE64_COUNT # define DARWIN_EXC_STATE_T arm_exception_state64_t -# define DARWIN_EXC_STATE_DAR THREAD_FLD(far) +# define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(far) #elif defined(POWERPC) # if CPP_WORDSZ == 32 # define DARWIN_EXC_STATE PPC_EXCEPTION_STATE @@ -4138,7 +4261,7 @@ STATIC kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task, # define DARWIN_EXC_STATE_COUNT PPC_EXCEPTION_STATE64_COUNT # define DARWIN_EXC_STATE_T ppc_exception_state64_t # endif -# define DARWIN_EXC_STATE_DAR THREAD_FLD(dar) +# define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(dar) #elif defined(I386) || defined(X86_64) # if CPP_WORDSZ == 32 # if defined(i386_EXCEPTION_STATE_COUNT) \ @@ -4157,8 +4280,8 @@ STATIC kern_return_t GC_forward_exception(mach_port_t thread, mach_port_t task, # define DARWIN_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT # define DARWIN_EXC_STATE_T x86_exception_state64_t # endif -# define DARWIN_EXC_STATE_DAR THREAD_FLD(faultvaddr) -#else +# define DARWIN_EXC_STATE_DAR THREAD_FLD_NAME(faultvaddr) +#elif !defined(CPPCHECK) # error FIXME for non-arm/ppc/x86 darwin #endif @@ -4174,8 +4297,6 @@ catch_exception_raise(mach_port_t exception_port GC_ATTR_UNUSED, { kern_return_t r; char *addr; - struct hblk *h; - unsigned int i; thread_state_flavor_t flavor = DARWIN_EXC_STATE; mach_msg_type_number_t exc_state_count = DARWIN_EXC_STATE_COUNT; DARWIN_EXC_STATE_T exc_state; @@ -4225,8 +4346,8 @@ catch_exception_raise(mach_port_t exception_port GC_ATTR_UNUSED, return KERN_SUCCESS; } - GC_err_printf( - "Unexpected KERN_PROTECTION_FAILURE at %p; aborting...\n", addr); + GC_err_printf("Unexpected KERN_PROTECTION_FAILURE at %p; aborting...\n", + (void *)addr); /* Can't pass it along to the signal handler because that is */ /* ignoring SIGBUS signals. We also shouldn't call ABORT here as */ /* signals don't always work too well from the exception handler. */ @@ -4244,10 +4365,12 @@ catch_exception_raise(mach_port_t exception_port GC_ATTR_UNUSED, # endif if (GC_mprotect_state == GC_MP_NORMAL) { /* common case */ - h = (struct hblk*)((word)addr & ~(GC_page_size-1)); + struct hblk * h = (struct hblk*)((word)addr & ~(GC_page_size-1)); + size_t i; + UNPROTECT(h, GC_page_size); for (i = 0; i < divHBLKSZ(GC_page_size); i++) { - register int index = PHT_HASH(h+i); + word index = PHT_HASH(h+i); async_set_pht_entry_from_index(GC_dirty_pages, index); } } else if (GC_mprotect_state == GC_MP_DISCARDING) { @@ -4318,7 +4441,9 @@ GC_API int GC_CALL GC_get_pages_executable(void) struct frame { struct frame *fr_savfp; long fr_savpc; - long fr_arg[NARGS]; /* All the arguments go here. */ +# if NARGS > 0 + long fr_arg[NARGS]; /* All the arguments go here. */ +# endif }; #endif @@ -4378,10 +4503,10 @@ GC_API int GC_CALL GC_get_pages_executable(void) /* Deal with possible malloc calls in backtrace by omitting */ /* the infinitely recursing backtrace. */ # ifdef THREADS - __thread /* If your compiler doesn't understand this */ + __thread /* If your compiler doesn't understand this */ /* you could use something like pthread_getspecific. */ # endif - GC_in_save_callers = FALSE; + GC_bool GC_in_save_callers = FALSE; #endif GC_INNER void GC_save_callers(struct callinfo info[NFRAMES]) @@ -4400,6 +4525,12 @@ GC_INNER void GC_save_callers(struct callinfo info[NFRAMES]) } GC_in_save_callers = TRUE; # endif + + GC_ASSERT(I_HOLD_LOCK()); + /* backtrace may call dl_iterate_phdr which is also */ + /* used by GC_register_dynamic_libraries, and */ + /* dl_iterate_phdr is not guaranteed to be reentrant. */ + GC_STATIC_ASSERT(sizeof(struct callinfo) == sizeof(void *)); npcs = backtrace((void **)tmp_info, NFRAMES + IGNORE_FRAMES); BCOPY(tmp_info+IGNORE_FRAMES, info, (npcs - IGNORE_FRAMES) * sizeof(void *)); @@ -4500,21 +4631,27 @@ GC_INNER void GC_print_callers(struct callinfo info[NFRAMES]) if (reentry_count > 1) { /* We were called during an allocation during */ /* a previous GC_print_callers call; punt. */ - GC_err_printf("\t\t##PC##= 0x%lx\n", info[i].ci_pc); + GC_err_printf("\t\t##PC##= 0x%lx\n", + (unsigned long)info[i].ci_pc); continue; } { + char buf[40]; + char *name; # if defined(GC_HAVE_BUILTIN_BACKTRACE) \ && !defined(GC_BACKTRACE_SYMBOLS_BROKEN) char **sym_name = backtrace_symbols((void **)(&(info[i].ci_pc)), 1); - char *name = sym_name[0]; -# else - char buf[40]; - char *name = buf; - (void)snprintf(buf, sizeof(buf), "##PC##= 0x%lx", info[i].ci_pc); - buf[sizeof(buf) - 1] = '\0'; + if (sym_name != NULL) { + name = sym_name[0]; + } else # endif + /* else */ { + (void)snprintf(buf, sizeof(buf), "##PC##= 0x%lx", + (unsigned long)info[i].ci_pc); + buf[sizeof(buf) - 1] = '\0'; + name = buf; + } # if defined(LINUX) && !defined(SMALL_CONFIG) /* Try for a line number. */ { @@ -4584,14 +4721,16 @@ GC_INNER void GC_print_callers(struct callinfo info[NFRAMES]) } /* Get rid of embedded newline, if any. Test for "main" */ { - char * nl = strchr(result_buf, '\n'); - if (nl != NULL - && (word)nl < (word)(result_buf + result_len)) { - *nl = ':'; - } - if (strncmp(result_buf, "main", nl - result_buf) == 0) { - stop = TRUE; - } + char * nl = strchr(result_buf, '\n'); + if (nl != NULL + && (word)nl < (word)(result_buf + result_len)) { + *nl = ':'; + } + if (strncmp(result_buf, "main", + nl != NULL ? (size_t)(nl - result_buf) + : result_len) == 0) { + stop = TRUE; + } } if (result_len < RESULT_SZ - 25) { /* Add in hex address */ @@ -4608,7 +4747,8 @@ GC_INNER void GC_print_callers(struct callinfo info[NFRAMES]) GC_err_printf("\t\t%s\n", name); # if defined(GC_HAVE_BUILTIN_BACKTRACE) \ && !defined(GC_BACKTRACE_SYMBOLS_BROKEN) - free(sym_name); /* May call GC_free; that's OK */ + if (sym_name != NULL) + free(sym_name); /* May call GC_[debug_]free; that's OK */ # endif } } diff --git a/src/bdwgc/pcr_interface.c b/src/bdwgc/pcr_interface.c index c6c868c3b..015ebd7f3 100644 --- a/src/bdwgc/pcr_interface.c +++ b/src/bdwgc/pcr_interface.c @@ -65,16 +65,18 @@ typedef struct { PCR_Any ed_client_data; } enumerate_data; -void GC_enumerate_block(struct hblk *h; enumerate_data * ed) +void GC_enumerate_block(struct hblk *h, enumerate_data * ed) { register hdr * hhdr; register int sz; ptr_t p; ptr_t lim; word descr; + +# if !defined(CPPCHECK) # error This code was updated without testing. # error and its precursor was clearly broken. - +# endif hhdr = HDR(h); descr = hhdr -> hb_descr; sz = hhdr -> hb_sz; diff --git a/src/bdwgc/pthread_start.c b/src/bdwgc/pthread_start.c index bd4fc4a04..f83dc434c 100644 --- a/src/bdwgc/pthread_start.c +++ b/src/bdwgc/pthread_start.c @@ -59,6 +59,7 @@ GC_INNER_PTHRSTART void * GC_CALLBACK GC_inner_start_routine( GC_log_printf("Finishing thread %p\n", (void *)pthread_self()); # endif me -> status = result; + GC_dirty(me); # ifndef NACL pthread_cleanup_pop(1); /* Cleanup acquires lock, ensuring that we can't exit while */ diff --git a/src/bdwgc/pthread_stop_world.c b/src/bdwgc/pthread_stop_world.c index a68e92225..bea5b65ce 100644 --- a/src/bdwgc/pthread_stop_world.c +++ b/src/bdwgc/pthread_stop_world.c @@ -22,18 +22,18 @@ #ifdef NACL -#include -#include +# include +# include -STATIC int GC_nacl_num_gc_threads = 0; -STATIC __thread int GC_nacl_thread_idx = -1; -STATIC int GC_nacl_park_threads_now = 0; -STATIC pthread_t GC_nacl_thread_parker = -1; + STATIC int GC_nacl_num_gc_threads = 0; + STATIC __thread int GC_nacl_thread_idx = -1; + STATIC volatile int GC_nacl_park_threads_now = 0; + STATIC volatile pthread_t GC_nacl_thread_parker = -1; -GC_INNER __thread GC_thread GC_nacl_gc_thread_self = NULL; + GC_INNER __thread GC_thread GC_nacl_gc_thread_self = NULL; -int GC_nacl_thread_parked[MAX_NACL_GC_THREADS]; -int GC_nacl_thread_used[MAX_NACL_GC_THREADS]; + volatile int GC_nacl_thread_parked[MAX_NACL_GC_THREADS]; + int GC_nacl_thread_used[MAX_NACL_GC_THREADS]; #elif defined(GC_OPENBSD_UTHREADS) @@ -44,12 +44,17 @@ int GC_nacl_thread_used[MAX_NACL_GC_THREADS]; #include #include #include +#include /* for nanosleep() */ #include #include "atomic_ops.h" /* It's safe to call original pthread_sigmask() here. */ #undef pthread_sigmask +#ifdef GC_ENABLE_SUSPEND_THREAD + static void *GC_CALLBACK suspend_self_inner(void *client_data); +#endif + #ifdef DEBUG_THREADS # ifndef NSIG # if defined(MAXSIG) @@ -59,7 +64,7 @@ int GC_nacl_thread_used[MAX_NACL_GC_THREADS]; # elif defined(__SIGRTMAX) # define NSIG (__SIGRTMAX+1) # else - --> please fix it +# error define NSIG # endif # endif /* NSIG */ @@ -92,7 +97,7 @@ STATIC void GC_remove_allowed_signals(sigset_t *set) /* Handlers write to the thread structure, which is in the heap, */ /* and hence can trigger a protection fault. */ if (sigdelset(set, SIGSEGV) != 0 -# ifdef SIGBUS +# ifdef HAVE_SIGBUS || sigdelset(set, SIGBUS) != 0 # endif ) { @@ -107,10 +112,10 @@ STATIC volatile AO_t GC_stop_count = 0; /* Incremented at the beginning of GC_stop_world. */ STATIC volatile AO_t GC_world_is_stopped = FALSE; - /* FALSE ==> it is safe for threads to restart, i.e. */ - /* they will see another suspend signal before they */ - /* are expected to stop (unless they have voluntarily */ - /* stopped). */ + /* FALSE ==> it is safe for threads to restart, */ + /* i.e. they will see another suspend signal */ + /* before they are expected to stop (unless */ + /* they have stopped voluntarily). */ #ifdef GC_OSF1_THREADS STATIC GC_bool GC_retry_signals = TRUE; @@ -132,7 +137,7 @@ STATIC volatile AO_t GC_world_is_stopped = FALSE; #ifndef SIG_THR_RESTART # if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) \ || defined(GC_NETBSD_THREADS) || defined(GC_USESIGRT_SIGNALS) -# ifdef _SIGRTMIN +# if defined(_SIGRTMIN) && !defined(CPPCHECK) # define SIG_THR_RESTART _SIGRTMIN + 5 # else # define SIG_THR_RESTART SIGRTMIN + 5 @@ -175,7 +180,8 @@ GC_API int GC_CALL GC_get_thr_restart_signal(void) ? GC_sig_thr_restart : SIG_THR_RESTART; } -#ifdef GC_EXPLICIT_SIGNALS_UNBLOCK +#if defined(GC_EXPLICIT_SIGNALS_UNBLOCK) \ + || !defined(NO_SIGNALS_UNBLOCK_IN_MAIN) /* Some targets (e.g., Solaris) might require this to be called when */ /* doing thread registering from the thread destructor. */ GC_INNER void GC_unblock_gc_signals(void) @@ -200,9 +206,9 @@ STATIC sem_t GC_suspend_ack_sem; STATIC sem_t GC_restart_ack_sem; #endif -STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context); +STATIC void GC_suspend_handler_inner(ptr_t dummy, void *context); -#ifdef SA_SIGINFO +#ifndef NO_SA_SIGACTION STATIC void GC_suspend_handler(int sig, siginfo_t * info GC_ATTR_UNUSED, void * context GC_ATTR_UNUSED) #else @@ -211,34 +217,38 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, void *context); { int old_errno = errno; + if (sig != GC_sig_suspend) { +# if defined(GC_FREEBSD_THREADS) + /* Workaround "deferred signal handling" bug in FreeBSD 9.2. */ + if (0 == sig) return; +# endif + ABORT("Bad signal in suspend_handler"); + } + # if defined(IA64) || defined(HP_PA) || defined(M68K) - GC_with_callee_saves_pushed(GC_suspend_handler_inner, (ptr_t)(word)sig); + GC_with_callee_saves_pushed(GC_suspend_handler_inner, NULL); # else /* We believe that in all other cases the full context is already */ /* in the signal handler frame. */ -# ifndef SA_SIGINFO - void *context = 0; -# endif - GC_suspend_handler_inner((ptr_t)(word)sig, context); + { +# ifdef NO_SA_SIGACTION + void *context = 0; +# endif + GC_suspend_handler_inner(NULL, context); + } # endif errno = old_errno; } -STATIC void GC_suspend_handler_inner(ptr_t sig_arg, +STATIC void GC_suspend_handler_inner(ptr_t dummy GC_ATTR_UNUSED, void * context GC_ATTR_UNUSED) { pthread_t self = pthread_self(); GC_thread me; IF_CANCEL(int cancel_state;) - AO_t my_stop_count = AO_load(&GC_stop_count); - - if ((signed_word)sig_arg != GC_sig_suspend) { -# if defined(GC_FREEBSD_THREADS) - /* Workaround "deferred signal handling" bug in FreeBSD 9.2. */ - if (0 == sig_arg) return; -# endif - ABORT("Bad signal in suspend_handler"); - } + AO_t my_stop_count = AO_load_acquire(&GC_stop_count); + /* After the barrier, this thread should see */ + /* the actual content of GC_threads. */ DISABLE_CANCEL(cancel_state); /* pthread_setcancelstate is not defined to be async-signal-safe. */ @@ -258,6 +268,27 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, /* of a thread which holds the allocation lock in order */ /* to stop the world. Thus concurrent modification of the */ /* data structure is impossible. */ + +# ifdef GC_ENABLE_SUSPEND_THREAD + if (AO_load(&me->suspended_ext)) { +# ifdef SPARC + me -> stop_info.stack_ptr = GC_save_regs_in_stack(); +# else + me -> stop_info.stack_ptr = GC_approx_sp(); +# ifdef IA64 + me -> backing_store_ptr = GC_save_regs_in_stack(); +# endif +# endif + sem_post(&GC_suspend_ack_sem); + suspend_self_inner(me); +# ifdef DEBUG_THREADS + GC_log_printf("Continuing %p on GC_resume_thread\n", (void *)self); +# endif + RESTORE_CANCEL(cancel_state); + return; + } +# endif + if (me -> stop_info.last_stop_count == my_stop_count) { /* Duplicate signal. OK if we are retrying. */ if (!GC_retry_signals) { @@ -279,7 +310,7 @@ STATIC void GC_suspend_handler_inner(ptr_t sig_arg, /* thread has been stopped. Note that sem_post() is */ /* the only async-signal-safe primitive in LinuxThreads. */ sem_post(&GC_suspend_ack_sem); - me -> stop_info.last_stop_count = my_stop_count; + AO_store_release(&me->stop_info.last_stop_count, my_stop_count); /* Wait until that thread tells us to restart by sending */ /* this thread a GC_sig_thr_restart signal (should be masked */ @@ -337,6 +368,141 @@ STATIC void GC_restart_handler(int sig) # endif } +# ifdef USE_TKILL_ON_ANDROID + extern int tkill(pid_t tid, int sig); /* from sys/linux-unistd.h */ + + static int android_thread_kill(pid_t tid, int sig) + { + int ret; + int old_errno = errno; + + ret = tkill(tid, sig); + if (ret < 0) { + ret = errno; + errno = old_errno; + } + return ret; + } + +# define THREAD_SYSTEM_ID(t) (t)->kernel_id +# define RAISE_SIGNAL(t, sig) android_thread_kill(THREAD_SYSTEM_ID(t), sig) +# else +# define THREAD_SYSTEM_ID(t) (t)->id +# define RAISE_SIGNAL(t, sig) pthread_kill(THREAD_SYSTEM_ID(t), sig) +# endif /* !USE_TKILL_ON_ANDROID */ + +# ifdef GC_ENABLE_SUSPEND_THREAD +# include + + STATIC void GC_brief_async_signal_safe_sleep(void) + { + struct timeval tv; + tv.tv_sec = 0; +# if defined(GC_TIME_LIMIT) && !defined(CPPCHECK) + tv.tv_usec = 1000 * GC_TIME_LIMIT / 2; +# else + tv.tv_usec = 1000 * 50 / 2; +# endif + (void)select(0, 0, 0, 0, &tv); + } + + static void *GC_CALLBACK suspend_self_inner(void *client_data) { + GC_thread me = (GC_thread)client_data; + + while (AO_load_acquire(&me->suspended_ext)) { + /* TODO: Use sigsuspend() instead. */ + GC_brief_async_signal_safe_sleep(); + } + return NULL; + } + + GC_API void GC_CALL GC_suspend_thread(GC_SUSPEND_THREAD_ID thread) { + GC_thread t; + IF_CANCEL(int cancel_state;) + DCL_LOCK_STATE; + + LOCK(); + t = GC_lookup_thread((pthread_t)thread); + if (t == NULL || t -> suspended_ext) { + UNLOCK(); + return; + } + + /* Set the flag making the change visible to the signal handler. */ + AO_store_release(&t->suspended_ext, TRUE); + + if ((pthread_t)thread == pthread_self()) { + UNLOCK(); + /* It is safe as "t" cannot become invalid here (no race with */ + /* GC_unregister_my_thread). */ + (void)GC_do_blocking(suspend_self_inner, t); + return; + } + if ((t -> flags & FINISHED) != 0) { + /* Terminated but not joined yet. */ + UNLOCK(); + return; + } + + DISABLE_CANCEL(cancel_state); + /* GC_suspend_thread is not a cancellation point. */ +# ifdef PARALLEL_MARK + /* Ensure we do not suspend a thread while it is rebuilding */ + /* a free list, otherwise such a dead-lock is possible: */ + /* thread 1 is blocked in GC_wait_for_reclaim holding */ + /* the allocation lock, thread 2 is suspended in */ + /* GC_reclaim_generic invoked from GC_generic_malloc_many */ + /* (with GC_fl_builder_count > 0), and thread 3 is blocked */ + /* acquiring the allocation lock in GC_resume_thread. */ + if (GC_parallel) + GC_wait_for_reclaim(); +# endif + + /* TODO: Support GC_retry_signals */ + switch (RAISE_SIGNAL(t, GC_sig_suspend)) { + /* ESRCH cannot happen as terminated threads are handled above. */ + case 0: + break; + default: + ABORT("pthread_kill failed"); + } + + /* Wait for the thread to complete threads table lookup and */ + /* stack_ptr assignment. */ + GC_ASSERT(GC_thr_initialized); + while (sem_wait(&GC_suspend_ack_sem) != 0) { + if (errno != EINTR) + ABORT("sem_wait for handler failed (suspend_self)"); + } + RESTORE_CANCEL(cancel_state); + UNLOCK(); + } + + GC_API void GC_CALL GC_resume_thread(GC_SUSPEND_THREAD_ID thread) { + GC_thread t; + DCL_LOCK_STATE; + + LOCK(); + t = GC_lookup_thread((pthread_t)thread); + if (t != NULL) + AO_store(&t->suspended_ext, FALSE); + UNLOCK(); + } + + GC_API int GC_CALL GC_is_thread_suspended(GC_SUSPEND_THREAD_ID thread) { + GC_thread t; + int is_suspended = 0; + DCL_LOCK_STATE; + + LOCK(); + t = GC_lookup_thread((pthread_t)thread); + if (t != NULL && t -> suspended_ext) + is_suspended = (int)TRUE; + UNLOCK(); + return is_suspended; + } +# endif /* GC_ENABLE_SUSPEND_THREAD */ + #endif /* !GC_OPENBSD_UTHREADS && !NACL */ #ifdef IA64 @@ -399,9 +565,15 @@ GC_INNER void GC_push_all_stacks(void) } # ifdef DEBUG_THREADS GC_log_printf("Stack for thread %p = [%p,%p)\n", - (void *)p->id, lo, hi); + (void *)p->id, (void *)lo, (void *)hi); # endif if (0 == lo) ABORT("GC_push_all_stacks: sp not set!"); + if (p->altstack != NULL && (word)p->altstack <= (word)lo + && (word)lo <= (word)p->altstack + p->altstack_size) { + hi = p->altstack + p->altstack_size; + /* FIXME: Need to scan the normal stack too, but how ? */ + /* FIXME: Assume stack grows down */ + } GC_push_all_stack_sections(lo, hi, traced_stack_sect); # ifdef STACK_GROWS_UP total_size += lo - hi; @@ -417,7 +589,7 @@ GC_INNER void GC_push_all_stacks(void) # ifdef IA64 # ifdef DEBUG_THREADS GC_log_printf("Reg stack for thread %p = [%p,%p)\n", - (void *)p->id, bs_lo, bs_hi); + (void *)p->id, (void *)bs_lo, (void *)bs_hi); # endif /* FIXME: This (if p->id==self) may add an unbounded number of */ /* entries, and hence overflow the mark stack, which is bad. */ @@ -441,24 +613,6 @@ GC_INNER void GC_push_all_stacks(void) int GC_stopping_pid = 0; #endif -#ifdef PLATFORM_ANDROID - extern int tkill(pid_t tid, int sig); /* from sys/linux-unistd.h */ - - static int android_thread_kill(pid_t tid, int sig) - { - int ret; - int old_errno = errno; - - ret = tkill(tid, sig); - if (ret < 0) { - ret = errno; - errno = old_errno; - } - - return ret; - } -#endif /* PLATFORM_ANDROID */ - /* We hold the allocation lock. Suspend all threads that might */ /* still be running. Return the number of suspend signals that */ /* were sent. */ @@ -466,7 +620,6 @@ STATIC int GC_suspend_all(void) { int n_live_threads = 0; int i; - # ifndef NACL GC_thread p; # ifndef GC_OPENBSD_UTHREADS @@ -481,10 +634,14 @@ STATIC int GC_suspend_all(void) for (i = 0; i < THREAD_TABLE_SZ; i++) { for (p = GC_threads[i]; p != 0; p = p -> next) { if (!THREAD_EQUAL(p -> id, self)) { - if (p -> flags & FINISHED) continue; + if ((p -> flags & FINISHED) != 0) continue; if (p -> thread_blocked) /* Will wait */ continue; # ifndef GC_OPENBSD_UTHREADS - if (p -> stop_info.last_stop_count == GC_stop_count) continue; +# ifdef GC_ENABLE_SUSPEND_THREAD + if (p -> suspended_ext) continue; +# endif + if (AO_load(&p->stop_info.last_stop_count) == GC_stop_count) + continue; n_live_threads++; # endif # ifdef DEBUG_THREADS @@ -499,19 +656,22 @@ STATIC int GC_suspend_all(void) if (pthread_stackseg_np(p->id, &stack)) ABORT("pthread_stackseg_np failed"); p -> stop_info.stack_ptr = (ptr_t)stack.ss_sp - stack.ss_size; + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, + (void *)p->id); } # else -# ifndef PLATFORM_ANDROID - result = pthread_kill(p -> id, GC_sig_suspend); -# else - result = android_thread_kill(p -> kernel_id, GC_sig_suspend); -# endif + result = RAISE_SIGNAL(p, GC_sig_suspend); switch(result) { case ESRCH: /* Not really there anymore. Possible? */ n_live_threads--; break; case 0: + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, + (void *)(word)THREAD_SYSTEM_ID(p)); + /* Note: thread id might be truncated. */ break; default: ABORT_ARG1("pthread_kill failed at suspend", @@ -552,6 +712,8 @@ STATIC int GC_suspend_all(void) num_used++; if (GC_nacl_thread_parked[i] == 1) { num_threads_parked++; + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, (void *)(word)i); } } } @@ -629,7 +791,23 @@ GC_INNER void GC_stop_world(void) } wait_usecs = 0; } - usleep(WAIT_UNIT); + +# ifdef LINT2 + /* Workaround "waiting while holding a lock" warning. */ +# undef WAIT_UNIT +# define WAIT_UNIT 1 + sched_yield(); +# elif defined(CPPCHECK) /* || _POSIX_C_SOURCE >= 199309L */ + { + struct timespec ts; + + ts.tv_sec = 0; + ts.tv_nsec = WAIT_UNIT * 1000; + (void)nanosleep(&ts, NULL); + } +# else + usleep(WAIT_UNIT); +# endif wait_usecs += WAIT_UNIT; } } @@ -690,8 +868,22 @@ GC_INNER void GC_stop_world(void) NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));\ __asm__ __volatile__ ("add $16, %esp"); \ } while (0) +# elif defined(__arm__) +# define NACL_STORE_REGS() \ + do { \ + __asm__ __volatile__ ("push {r4-r8,r10-r12,lr}"); \ + __asm__ __volatile__ ("mov r0, %0" \ + : : "r" (&GC_nacl_gc_thread_self->stop_info.stack_ptr)); \ + __asm__ __volatile__ ("bic r0, r0, #0xc0000000"); \ + __asm__ __volatile__ ("str sp, [r0]"); \ + BCOPY(GC_nacl_gc_thread_self->stop_info.stack_ptr, \ + GC_nacl_gc_thread_self->stop_info.reg_storage, \ + NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t)); \ + __asm__ __volatile__ ("add sp, sp, #40"); \ + __asm__ __volatile__ ("bic sp, sp, #0xc0000000"); \ + } while (0) # else -# error FIXME for non-amd64/x86 NaCl +# error TODO Please port NACL_STORE_REGS # endif GC_API_OSCALL void nacl_pre_syscall_hook(void) @@ -748,16 +940,28 @@ GC_INNER void GC_stop_world(void) STATIC GC_bool GC_nacl_thread_parking_inited = FALSE; STATIC pthread_mutex_t GC_nacl_thread_alloc_lock = PTHREAD_MUTEX_INITIALIZER; - extern void nacl_register_gc_hooks(void (*pre)(void), void (*post)(void)); + struct nacl_irt_blockhook { + int (*register_block_hooks)(void (*pre)(void), void (*post)(void)); + }; + + extern size_t nacl_interface_query(const char *interface_ident, + void *table, size_t tablesize); GC_INNER void GC_nacl_initialize_gc_thread(void) { int i; - nacl_register_gc_hooks(nacl_pre_syscall_hook, nacl_post_syscall_hook); + static struct nacl_irt_blockhook gc_hook; + pthread_mutex_lock(&GC_nacl_thread_alloc_lock); if (!EXPECT(GC_nacl_thread_parking_inited, TRUE)) { BZERO(GC_nacl_thread_parked, sizeof(GC_nacl_thread_parked)); BZERO(GC_nacl_thread_used, sizeof(GC_nacl_thread_used)); + /* TODO: replace with public 'register hook' function when */ + /* available from glibc. */ + nacl_interface_query("nacl-irt-blockhook-0.1", + &gc_hook, sizeof(gc_hook)); + gc_hook.register_block_hooks(nacl_pre_syscall_hook, + nacl_post_syscall_hook); GC_nacl_thread_parking_inited = TRUE; } GC_ASSERT(GC_nacl_num_gc_threads <= MAX_NACL_GC_THREADS); @@ -797,23 +1001,26 @@ GC_INNER void GC_start_world(void) register int n_live_threads = 0; register int result; # endif -# ifdef GC_NETBSD_THREADS_WORKAROUND - int code; -# endif # ifdef DEBUG_THREADS GC_log_printf("World starting\n"); # endif # ifndef GC_OPENBSD_UTHREADS - AO_store(&GC_world_is_stopped, FALSE); + AO_store_release(&GC_world_is_stopped, FALSE); + /* The updated value should now be visible to the */ + /* signal handler (note that pthread_kill is not on */ + /* the list of functions which synchronize memory). */ # endif for (i = 0; i < THREAD_TABLE_SZ; i++) { for (p = GC_threads[i]; p != 0; p = p -> next) { if (!THREAD_EQUAL(p -> id, self)) { - if (p -> flags & FINISHED) continue; + if ((p -> flags & FINISHED) != 0) continue; if (p -> thread_blocked) continue; # ifndef GC_OPENBSD_UTHREADS +# ifdef GC_ENABLE_SUSPEND_THREAD + if (p -> suspended_ext) continue; +# endif n_live_threads++; # endif # ifdef DEBUG_THREADS @@ -823,19 +1030,19 @@ GC_INNER void GC_start_world(void) # ifdef GC_OPENBSD_UTHREADS if (pthread_resume_np(p -> id) != 0) ABORT("pthread_resume_np failed"); + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, (void *)p->id); # else -# ifndef PLATFORM_ANDROID - result = pthread_kill(p -> id, GC_sig_thr_restart); -# else - result = android_thread_kill(p -> kernel_id, - GC_sig_thr_restart); -# endif + result = RAISE_SIGNAL(p, GC_sig_thr_restart); switch(result) { case ESRCH: /* Not really there anymore. Possible? */ n_live_threads--; break; case 0: + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, + (void *)(word)THREAD_SYSTEM_ID(p)); break; default: ABORT_ARG1("pthread_kill failed at resume", @@ -847,10 +1054,10 @@ GC_INNER void GC_start_world(void) } # ifdef GC_NETBSD_THREADS_WORKAROUND for (i = 0; i < n_live_threads; i++) { - while (0 != (code = sem_wait(&GC_restart_ack_sem))) { + while (0 != sem_wait(&GC_restart_ack_sem)) { if (errno != EINTR) { ABORT_ARG1("sem_wait() for restart handler failed", - ": errcode= %d", code); + ": errcode= %d", errno); } } } @@ -863,6 +1070,9 @@ GC_INNER void GC_start_world(void) GC_log_printf("World starting...\n"); # endif GC_nacl_park_threads_now = 0; + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, NULL); + /* TODO: Send event for every unsuspended thread. */ # endif } @@ -890,7 +1100,7 @@ GC_INNER void GC_stop_init(void) # else act.sa_flags = 0 # endif -# ifdef SA_SIGINFO +# ifndef NO_SA_SIGACTION | SA_SIGINFO # endif ; @@ -905,7 +1115,7 @@ GC_INNER void GC_stop_init(void) GC_remove_allowed_signals(&act.sa_mask); /* GC_sig_thr_restart is set in the resulting mask. */ /* It is unmasked by the handler when necessary. */ -# ifdef SA_SIGINFO +# ifndef NO_SA_SIGACTION act.sa_sigaction = GC_suspend_handler; # else act.sa_handler = GC_suspend_handler; @@ -915,7 +1125,7 @@ GC_INNER void GC_stop_init(void) ABORT("Cannot set SIG_SUSPEND handler"); } -# ifdef SA_SIGINFO +# ifndef NO_SA_SIGACTION act.sa_flags &= ~SA_SIGINFO; # endif act.sa_handler = GC_restart_handler; @@ -939,6 +1149,10 @@ GC_INNER void GC_stop_init(void) if (GC_retry_signals) { GC_COND_LOG_PRINTF("Will retry suspend signal if necessary\n"); } +# ifndef NO_SIGNALS_UNBLOCK_IN_MAIN + /* Explicitly unblock the signals once before new threads creation. */ + GC_unblock_gc_signals(); +# endif # endif /* !GC_OPENBSD_UTHREADS && !NACL */ } diff --git a/src/bdwgc/pthread_support.c b/src/bdwgc/pthread_support.c index 2fca3602b..3dc7b59e4 100644 --- a/src/bdwgc/pthread_support.c +++ b/src/bdwgc/pthread_support.c @@ -27,23 +27,6 @@ * all flavors of pthread support code into this file. */ -/* - * Linux_threads.c now also includes some code to support HPUX and - * OSF1 (Compaq Tru64 Unix, really). The OSF1 support is based on Eric Benson's - * patch. - * - * Eric also suggested an alternate basis for a lock implementation in - * his code: - * + #elif defined(OSF1) - * + unsigned long GC_allocate_lock = 0; - * + msemaphore GC_allocate_semaphore; - * + # define GC_TRY_LOCK() \ - * + ((msem_lock(&GC_allocate_semaphore, MSEM_IF_NOWAIT) == 0) \ - * + ? (GC_allocate_lock = 1) \ - * + : 0) - * + # define GC_LOCK_TAKEN GC_allocate_lock - */ - #if defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS) # include @@ -103,7 +86,7 @@ # ifndef GC_NO_PTHREAD_CANCEL # undef pthread_cancel # endif -# ifdef GC_PTHREAD_EXIT_ATTRIBUTE +# ifdef GC_HAVE_PTHREAD_EXIT # undef pthread_exit # endif # undef pthread_join @@ -117,7 +100,7 @@ # ifndef GC_NO_PTHREAD_CANCEL # define pthread_cancel __pthread_cancel # endif -# ifdef GC_PTHREAD_EXIT_ATTRIBUTE +# ifdef GC_HAVE_PTHREAD_EXIT # define pthread_exit __pthread_exit # endif # endif @@ -136,7 +119,7 @@ # ifndef GC_NO_PTHREAD_CANCEL int REAL_FUNC(pthread_cancel)(pthread_t); # endif -# ifdef GC_PTHREAD_EXIT_ATTRIBUTE +# ifdef GC_HAVE_PTHREAD_EXIT void REAL_FUNC(pthread_exit)(void *) GC_PTHREAD_EXIT_ATTRIBUTE; # endif #else @@ -165,7 +148,7 @@ typedef int (* GC_pthread_cancel_t)(pthread_t); static GC_pthread_cancel_t REAL_FUNC(pthread_cancel); # endif -# ifdef GC_PTHREAD_EXIT_ATTRIBUTE +# ifdef GC_HAVE_PTHREAD_EXIT typedef void (* GC_pthread_exit_t)(void *) GC_PTHREAD_EXIT_ATTRIBUTE; static GC_pthread_exit_t REAL_FUNC(pthread_exit); # endif @@ -215,12 +198,12 @@ } # endif /* !GC_NO_PTHREAD_CANCEL */ -# ifdef GC_PTHREAD_EXIT_ATTRIBUTE +# ifdef GC_HAVE_PTHREAD_EXIT GC_API GC_PTHREAD_EXIT_ATTRIBUTE void GC_pthread_exit(void *retval) { pthread_exit(retval); } -# endif /* GC_PTHREAD_EXIT_ATTRIBUTE */ +# endif #endif /* Linker-based interception. */ #ifdef GC_USE_DLOPEN_WRAP @@ -240,7 +223,7 @@ } if (NULL == dl_handle) ABORT("Couldn't open libpthread"); # endif - REAL_FUNC(pthread_create) = (GC_pthread_create_t) + REAL_FUNC(pthread_create) = (GC_pthread_create_t)(word) dlsym(dl_handle, "pthread_create"); # ifdef RTLD_NEXT if (REAL_FUNC(pthread_create) == 0) @@ -248,19 +231,19 @@ " (probably -lgc is specified after -lpthread)"); # endif # ifndef GC_NO_PTHREAD_SIGMASK - REAL_FUNC(pthread_sigmask) = (GC_pthread_sigmask_t) + REAL_FUNC(pthread_sigmask) = (GC_pthread_sigmask_t)(word) dlsym(dl_handle, "pthread_sigmask"); # endif - REAL_FUNC(pthread_join) = (GC_pthread_join_t) + REAL_FUNC(pthread_join) = (GC_pthread_join_t)(word) dlsym(dl_handle, "pthread_join"); - REAL_FUNC(pthread_detach) = (GC_pthread_detach_t) + REAL_FUNC(pthread_detach) = (GC_pthread_detach_t)(word) dlsym(dl_handle, "pthread_detach"); # ifndef GC_NO_PTHREAD_CANCEL - REAL_FUNC(pthread_cancel) = (GC_pthread_cancel_t) + REAL_FUNC(pthread_cancel) = (GC_pthread_cancel_t)(word) dlsym(dl_handle, "pthread_cancel"); # endif -# ifdef GC_PTHREAD_EXIT_ATTRIBUTE - REAL_FUNC(pthread_exit) = (GC_pthread_exit_t) +# ifdef GC_HAVE_PTHREAD_EXIT + REAL_FUNC(pthread_exit) = (GC_pthread_exit_t)(word) dlsym(dl_handle, "pthread_exit"); # endif GC_syms_initialized = TRUE; @@ -372,6 +355,11 @@ STATIC void * GC_mark_thread(void * id) marker_mach_threads[(word)id] = mach_thread_self(); # endif + /* Inform GC_start_mark_threads about completion of marker data init. */ + GC_acquire_mark_lock(); + if (0 == --GC_fl_builder_count) /* count may have a negative value */ + GC_notify_all_builder(); + for (;; ++my_mark_no) { /* GC_mark_no is passed only to allow GC_help_marker to terminate */ /* promptly. This is important if it were called from the signal */ @@ -396,56 +384,110 @@ STATIC pthread_t GC_mark_threads[MAX_MARKERS]; #ifdef CAN_HANDLE_FORK static int available_markers_m1 = 0; -# define start_mark_threads GC_start_mark_threads - GC_API void GC_CALL + static pthread_cond_t mark_cv; + /* initialized by GC_start_mark_threads_inner */ #else # define available_markers_m1 GC_markers_m1 - static void + static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER; #endif -start_mark_threads(void) + +GC_INNER void GC_start_mark_threads_inner(void) { int i; pthread_attr_t attr; - - GC_ASSERT(I_DONT_HOLD_LOCK()); -# ifdef CAN_HANDLE_FORK - if (available_markers_m1 <= 0 || GC_parallel) return; - /* Skip if parallel markers disabled or already started. */ +# ifndef NO_MARKER_SPECIAL_SIGMASK + sigset_t set, oldset; # endif - INIT_REAL_SYMS(); /* for pthread_create */ + GC_ASSERT(I_DONT_HOLD_LOCK()); + if (available_markers_m1 <= 0) return; + /* Skip if parallel markers disabled or already started. */ +# ifdef CAN_HANDLE_FORK + if (GC_parallel) return; + /* Initialize mark_cv (for the first time), or cleanup its value */ + /* after forking in the child process. All the marker threads in */ + /* the parent process were blocked on this variable at fork, so */ + /* pthread_cond_wait() malfunction (hang) is possible in the */ + /* child process without such a cleanup. */ + /* TODO: This is not portable, it is better to shortly unblock */ + /* all marker threads in the parent process at fork. */ + { + pthread_cond_t mark_cv_local = PTHREAD_COND_INITIALIZER; + BCOPY(&mark_cv_local, &mark_cv, sizeof(mark_cv)); + } +# endif + + GC_ASSERT(GC_fl_builder_count == 0); + INIT_REAL_SYMS(); /* for pthread_create */ if (0 != pthread_attr_init(&attr)) ABORT("pthread_attr_init failed"); if (0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) ABORT("pthread_attr_setdetachstate failed"); -# if defined(HPUX) || defined(GC_DGUX386_THREADS) - /* Default stack size is usually too small: fix it. */ - /* Otherwise marker threads or GC may run out of */ - /* space. */ -# define MIN_STACK_SIZE (8*HBLKSIZE*sizeof(word)) +# ifdef DEFAULT_STACK_MAYBE_SMALL + /* Default stack size is usually too small: increase it. */ + /* Otherwise marker threads or GC may run out of space. */ { size_t old_size; if (pthread_attr_getstacksize(&attr, &old_size) != 0) ABORT("pthread_attr_getstacksize failed"); - if (old_size < MIN_STACK_SIZE) { + if (old_size < MIN_STACK_SIZE + && old_size != 0 /* stack size is known */) { if (pthread_attr_setstacksize(&attr, MIN_STACK_SIZE) != 0) ABORT("pthread_attr_setstacksize failed"); } } -# endif /* HPUX || GC_DGUX386_THREADS */ +# endif /* DEFAULT_STACK_MAYBE_SMALL */ + +# ifndef NO_MARKER_SPECIAL_SIGMASK + /* Apply special signal mask to GC marker threads, and don't drop */ + /* user defined signals by GC marker threads. */ + if (sigfillset(&set) != 0) + ABORT("sigfillset failed"); + +# if !defined(GC_DARWIN_THREADS) && !defined(GC_OPENBSD_UTHREADS) \ + && !defined(NACL) + /* These are used by GC to stop and restart the world. */ + if (sigdelset(&set, GC_get_suspend_signal()) != 0 + || sigdelset(&set, GC_get_thr_restart_signal()) != 0) + ABORT("sigdelset failed"); +# endif + + if (pthread_sigmask(SIG_BLOCK, &set, &oldset) < 0) { + WARN("pthread_sigmask set failed, no markers started," + " errno = %" WARN_PRIdPTR "\n", errno); + GC_markers_m1 = 0; + (void)pthread_attr_destroy(&attr); + return; + } +# endif /* !NO_MARKER_SPECIAL_SIGMASK */ + +# ifdef CAN_HANDLE_FORK + /* To have proper GC_parallel value in GC_help_marker. */ + GC_markers_m1 = available_markers_m1; +# endif for (i = 0; i < available_markers_m1; ++i) { if (0 != REAL_FUNC(pthread_create)(GC_mark_threads + i, &attr, GC_mark_thread, (void *)(word)i)) { WARN("Marker thread creation failed, errno = %" WARN_PRIdPTR "\n", errno); /* Don't try to create other marker threads. */ + GC_markers_m1 = i; break; } } - GC_markers_m1 = i; + +# ifndef NO_MARKER_SPECIAL_SIGMASK + /* Restore previous signal mask. */ + if (pthread_sigmask(SIG_SETMASK, &oldset, NULL) < 0) { + WARN("pthread_sigmask restore failed, errno = %" WARN_PRIdPTR "\n", + errno); + } +# endif + (void)pthread_attr_destroy(&attr); + GC_wait_for_markers_init(); GC_COND_LOG_PRINTF("Started %d mark helper threads\n", GC_markers_m1); } @@ -458,10 +500,9 @@ GC_INNER volatile GC_thread GC_threads[THREAD_TABLE_SZ] = {0}; void GC_push_thread_structures(void) { GC_ASSERT(I_HOLD_LOCK()); - GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads)); + GC_PUSH_ALL_SYM(GC_threads); # if defined(THREAD_LOCAL_ALLOC) - GC_push_all((ptr_t)(&GC_thread_key), - (ptr_t)(&GC_thread_key) + sizeof(GC_thread_key)); + GC_PUSH_ALL_SYM(GC_thread_key); # endif } @@ -486,17 +527,22 @@ void GC_push_thread_structures(void) /* It may not be safe to allocate when we register the first thread. */ static struct GC_Thread_Rep first_thread; +#define THREAD_TABLE_INDEX(id) \ + (int)(((NUMERIC_THREAD_ID(id) >> 16) \ + ^ (NUMERIC_THREAD_ID(id) >> 8) \ + ^ NUMERIC_THREAD_ID(id)) % THREAD_TABLE_SZ) + /* Add a thread to GC_threads. We assume it wasn't already there. */ /* Caller holds allocation lock. */ STATIC GC_thread GC_new_thread(pthread_t id) { - int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ; + int hv = THREAD_TABLE_INDEX(id); GC_thread result; static GC_bool first_thread_used = FALSE; + # ifdef DEBUG_THREADS GC_log_printf("Creating thread %p\n", (void *)id); # endif - GC_ASSERT(I_HOLD_LOCK()); if (!EXPECT(first_thread_used, TRUE)) { result = &first_thread; @@ -507,7 +553,7 @@ STATIC GC_thread GC_new_thread(pthread_t id) if (result == 0) return(0); } result -> id = id; -# ifdef PLATFORM_ANDROID +# ifdef USE_TKILL_ON_ANDROID result -> kernel_id = gettid(); # endif result -> next = GC_threads[hv]; @@ -517,6 +563,8 @@ STATIC GC_thread GC_new_thread(pthread_t id) GC_nacl_initialize_gc_thread(); # endif GC_ASSERT(result -> flags == 0 && result -> thread_blocked == 0); + if (EXPECT(result != &first_thread, TRUE)) + GC_dirty(result); return(result); } @@ -525,7 +573,7 @@ STATIC GC_thread GC_new_thread(pthread_t id) /* It is safe to delete the main thread. */ STATIC void GC_delete_thread(pthread_t id) { - int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ; + int hv = THREAD_TABLE_INDEX(id); register GC_thread p = GC_threads[hv]; register GC_thread prev = 0; @@ -548,6 +596,7 @@ STATIC void GC_delete_thread(pthread_t id) GC_threads[hv] = p -> next; } else { prev -> next = p -> next; + GC_dirty(prev); } if (p != &first_thread) { # ifdef GC_DARWIN_THREADS @@ -564,7 +613,7 @@ STATIC void GC_delete_thread(pthread_t id) STATIC void GC_delete_gc_thread(GC_thread t) { pthread_t id = t -> id; - int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ; + int hv = THREAD_TABLE_INDEX(id); register GC_thread p = GC_threads[hv]; register GC_thread prev = 0; @@ -577,6 +626,7 @@ STATIC void GC_delete_gc_thread(GC_thread t) GC_threads[hv] = p -> next; } else { prev -> next = p -> next; + GC_dirty(prev); } # ifdef GC_DARWIN_THREADS mach_port_deallocate(mach_task_self(), p->stop_info.mach_thread); @@ -597,8 +647,7 @@ STATIC void GC_delete_gc_thread(GC_thread t) /* return the most recent one. */ GC_INNER GC_thread GC_lookup_thread(pthread_t id) { - int hv = NUMERIC_THREAD_ID(id) % THREAD_TABLE_SZ; - register GC_thread p = GC_threads[hv]; + GC_thread p = GC_threads[THREAD_TABLE_INDEX(id)]; while (p != 0 && !THREAD_EQUAL(p -> id, id)) p = p -> next; return(p); @@ -658,6 +707,36 @@ GC_API int GC_CALL GC_thread_is_registered(void) return me != NULL; } +static pthread_t main_pthread_id; +static void *main_stack, *main_altstack; +static word main_stack_size, main_altstack_size; + +GC_API void GC_CALL GC_register_altstack(void *stack, GC_word stack_size, + void *altstack, + GC_word altstack_size) +{ + GC_thread me; + pthread_t self = pthread_self(); + DCL_LOCK_STATE; + + LOCK(); + me = GC_lookup_thread(self); + if (me != NULL) { + me->stack = stack; + me->stack_size = stack_size; + me->altstack = altstack; + me->altstack_size = altstack_size; + } else { + /* This happens if we are called before GC_thr_init. */ + main_pthread_id = self; + main_stack = stack; + main_stack_size = stack_size; + main_altstack = altstack; + main_altstack_size = altstack_size; + } + UNLOCK(); +} + #ifdef CAN_HANDLE_FORK /* Remove all entries from the GC_threads table, except the */ /* one for the current thread. We need to do this in the child */ @@ -673,7 +752,8 @@ STATIC void GC_remove_all_threads_but_me(void) me = 0; for (p = GC_threads[hv]; 0 != p; p = next) { next = p -> next; - if (THREAD_EQUAL(p -> id, self)) { + if (THREAD_EQUAL(p -> id, self) + && me == NULL) { /* ignore dead threads with the same id */ me = p; p -> next = 0; # ifdef GC_DARWIN_THREADS @@ -681,22 +761,33 @@ STATIC void GC_remove_all_threads_but_me(void) /* GC_destroy_thread_local and GC_free_internal */ /* before update). */ me -> stop_info.mach_thread = mach_thread_self(); -# elif defined(PLATFORM_ANDROID) +# endif +# ifdef USE_TKILL_ON_ANDROID me -> kernel_id = gettid(); # endif # if defined(THREAD_LOCAL_ALLOC) && !defined(USE_CUSTOM_SPECIFIC) + { + int res; + /* Some TLS implementations might be not fork-friendly, so */ /* we re-assign thread-local pointer to 'tlfs' for safety */ /* instead of the assertion check (again, it is OK to call */ /* GC_destroy_thread_local and GC_free_internal before). */ - if (GC_setspecific(GC_thread_key, &me->tlfs) != 0) + res = GC_setspecific(GC_thread_key, &me->tlfs); + if (COVERT_DATAFLOW(res) != 0) ABORT("GC_setspecific failed (in child)"); + } # endif } else { # ifdef THREAD_LOCAL_ALLOC if (!(p -> flags & FINISHED)) { - GC_destroy_thread_local(&(p->tlfs)); - GC_remove_specific(GC_thread_key); + /* Cannot call GC_destroy_thread_local here. The free */ + /* lists may be in an inconsistent state (as thread p may */ + /* be updating one of the lists by GC_generic_malloc_many */ + /* or GC_FAST_MALLOC_GRANS when fork is invoked). */ + /* This should not be a problem because the lost elements */ + /* of the free lists will be collected during GC. */ + GC_remove_specific_after_fork(GC_thread_key, p -> id); } # endif if (p != &first_thread) GC_INTERNAL_FREE(p); @@ -786,7 +877,8 @@ STATIC void GC_remove_all_threads_but_me(void) # define GC_get_nprocs() pthread_num_processors_np() #elif defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS) \ - || defined(GC_SOLARIS_THREADS) || defined(GC_GNU_THREADS) \ + || defined(GC_HAIKU_THREADS) || defined(GC_SOLARIS_THREADS) \ + || defined(GC_GNU_THREADS) \ || defined(PLATFORM_ANDROID) || defined(NACL) GC_INLINE int GC_get_nprocs(void) { @@ -997,13 +1089,34 @@ static void fork_child_proc(void) # endif /* PARALLEL_MARK */ RESTORE_CANCEL(fork_cancel_state); UNLOCK(); + /* Even though after a fork the child only inherits the single */ + /* thread that called the fork(), if another thread in the parent */ + /* was attempting to lock the mutex while being held in */ + /* fork_child_prepare(), the mutex will be left in an inconsistent */ + /* state in the child after the UNLOCK. This is the case, at */ + /* least, in Mac OS X and leads to an unusable GC in the child */ + /* which will block when attempting to perform any GC operation */ + /* that acquires the allocation mutex. */ +# ifdef USE_PTHREAD_LOCKS + GC_ASSERT(I_DONT_HOLD_LOCK()); + /* Reinitialize the mutex. It should be safe since we are */ + /* running this in the child which only inherits a single thread. */ + /* mutex_destroy() may return EBUSY, which makes no sense, but */ + /* that is the reason for the need of the reinitialization. */ + (void)pthread_mutex_destroy(&GC_allocate_ml); + /* TODO: Probably some targets might need the default mutex */ + /* attribute to be passed instead of NULL. */ + if (0 != pthread_mutex_init(&GC_allocate_ml, NULL)) + ABORT("pthread_mutex_init failed (in child)"); +# endif } /* Routines for fork handling by client (no-op if pthread_atfork works). */ GC_API void GC_CALL GC_atfork_prepare(void) { + if (!EXPECT(GC_is_initialized, TRUE)) GC_init(); # if defined(GC_DARWIN_THREADS) && defined(MPROTECT_VDB) - if (GC_dirty_maintained) { + if (GC_incremental) { GC_ASSERT(0 == GC_handle_fork); ABORT("Unable to fork while mprotect_thread is running"); } @@ -1035,9 +1148,9 @@ static void fork_child_proc(void) static void setup_mark_lock(void); #endif -/* We hold the allocation lock. */ GC_INNER void GC_thr_init(void) { + GC_ASSERT(I_HOLD_LOCK()); if (GC_thr_initialized) return; GC_thr_initialized = TRUE; @@ -1075,7 +1188,9 @@ GC_INNER void GC_thr_init(void) # endif /* Add the initial thread, so we can stop it. */ { - GC_thread t = GC_new_thread(pthread_self()); + pthread_t self = pthread_self(); + GC_thread t = GC_new_thread(self); + if (t == NULL) ABORT("Failed to allocate memory for the initial thread"); # ifdef GC_DARWIN_THREADS @@ -1084,6 +1199,12 @@ GC_INNER void GC_thr_init(void) t -> stop_info.stack_ptr = GC_approx_sp(); # endif t -> flags = DETACHED | MAIN_THREAD; + if (THREAD_EQUAL(self, main_pthread_id)) { + t -> stack = main_stack; + t -> stack_size = main_stack_size; + t -> altstack = main_altstack; + t -> altstack_size = main_altstack_size; + } } # ifndef GC_DARWIN_THREADS @@ -1112,30 +1233,31 @@ GC_INNER void GC_thr_init(void) available_markers_m1 = 0; /* but use only one marker */ # endif } else { -# ifdef PARALLEL_MARK - { - char * markers_string = GETENV("GC_MARKERS"); - int markers_m1; +# ifdef PARALLEL_MARK + { + char * markers_string = GETENV("GC_MARKERS"); + int markers; - if (markers_string != NULL) { - markers_m1 = atoi(markers_string) - 1; - if (markers_m1 >= MAX_MARKERS) { - WARN("Limiting number of mark threads\n", 0); - markers_m1 = MAX_MARKERS - 1; - } - } else { - markers_m1 = GC_nprocs - 1; -# ifdef GC_MIN_MARKERS - /* This is primarily for targets without getenv(). */ - if (markers_m1 < GC_MIN_MARKERS - 1) - markers_m1 = GC_MIN_MARKERS - 1; -# endif - if (markers_m1 >= MAX_MARKERS) - markers_m1 = MAX_MARKERS - 1; /* silently limit the value */ - } - available_markers_m1 = markers_m1; - } -# endif + if (markers_string != NULL) { + markers = atoi(markers_string); + if (markers <= 0 || markers > MAX_MARKERS) { + WARN("Too big or invalid number of mark threads: %" WARN_PRIdPTR + "; using maximum threads\n", (signed_word)markers); + markers = MAX_MARKERS; + } + } else { + markers = GC_nprocs; +# if defined(GC_MIN_MARKERS) && !defined(CPPCHECK) + /* This is primarily for targets without getenv(). */ + if (markers < GC_MIN_MARKERS) + markers = GC_MIN_MARKERS; +# endif + if (markers > MAX_MARKERS) + markers = MAX_MARKERS; /* silently limit the value */ + } + available_markers_m1 = markers - 1; + } +# endif } GC_COND_LOG_PRINTF("Number of processors = %d\n", GC_nprocs); # ifdef PARALLEL_MARK @@ -1148,8 +1270,6 @@ GC_INNER void GC_thr_init(void) /* Disable true incremental collection, but generational is OK. */ GC_time_limit = GC_TIME_UNLIMITED; setup_mark_lock(); - /* If we are using a parallel marker, actually start helper threads. */ - start_mark_threads(); } # endif } @@ -1182,14 +1302,15 @@ GC_INNER void GC_init_parallel(void) sigset_t *oset) { sigset_t fudged_set; - int sig_suspend; INIT_REAL_SYMS(); if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) { + int sig_suspend = GC_get_suspend_signal(); + fudged_set = *set; - sig_suspend = GC_get_suspend_signal(); GC_ASSERT(sig_suspend >= 0); - sigdelset(&fudged_set, sig_suspend); + if (sigdelset(&fudged_set, sig_suspend) != 0) + ABORT("sigdelset failed"); set = &fudged_set; } return(REAL_FUNC(pthread_sigmask)(how, set, oset)); @@ -1316,14 +1437,14 @@ STATIC void GC_unregister_my_thread_inner(GC_thread me) # ifdef DEBUG_THREADS GC_log_printf( "Unregistering thread %p, gc_thread = %p, n_threads = %d\n", - (void *)me->id, me, GC_count_threads()); + (void *)me->id, (void *)me, GC_count_threads()); # endif GC_ASSERT(!(me -> flags & FINISHED)); # if defined(THREAD_LOCAL_ALLOC) GC_ASSERT(GC_getspecific(GC_thread_key) == &me->tlfs); GC_destroy_thread_local(&(me->tlfs)); # endif -# if defined(GC_PTHREAD_EXIT_ATTRIBUTE) || !defined(GC_NO_PTHREAD_CANCEL) +# if defined(GC_HAVE_PTHREAD_EXIT) || !defined(GC_NO_PTHREAD_CANCEL) /* Handle DISABLED_GC flag which is set by the */ /* intercepted pthread_cancel or pthread_exit. */ if ((me -> flags & DISABLED_GC) != 0) { @@ -1357,7 +1478,7 @@ GC_API int GC_CALL GC_unregister_my_thread(void) # ifdef DEBUG_THREADS GC_log_printf( "Called GC_unregister_my_thread on %p, gc_thread = %p\n", - (void *)self, me); + (void *)self, (void *)me); # endif GC_ASSERT(me->id == self); GC_unregister_my_thread_inner(me); @@ -1373,13 +1494,13 @@ GC_API int GC_CALL GC_unregister_my_thread(void) /* resources or id anyway. */ GC_INNER_PTHRSTART void GC_thread_exit_proc(void *arg) { + IF_CANCEL(int cancel_state;) + DCL_LOCK_STATE; + # ifdef DEBUG_THREADS GC_log_printf("Called GC_thread_exit_proc on %p, gc_thread = %p\n", (void *)((GC_thread)arg)->id, arg); # endif - IF_CANCEL(int cancel_state;) - DCL_LOCK_STATE; - LOCK(); DISABLE_CANCEL(cancel_state); GC_wait_for_gc_completion(FALSE); @@ -1414,9 +1535,11 @@ GC_API int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) # endif if (result == 0) { LOCK(); - /* Here the pthread thread id may have been recycled. */ - GC_ASSERT((t -> flags & FINISHED) != 0); - GC_delete_gc_thread(t); + /* Here the pthread thread id may have been recycled. */ + /* Delete the thread from GC_threads (unless it has been */ + /* registered again from the client thread key destructor). */ + if ((t -> flags & FINISHED) != 0) + GC_delete_gc_thread(t); UNLOCK(); } return result; @@ -1479,7 +1602,7 @@ GC_API int WRAP_FUNC(pthread_detach)(pthread_t thread) } #endif /* !GC_NO_PTHREAD_CANCEL */ -#ifdef GC_PTHREAD_EXIT_ATTRIBUTE +#ifdef GC_HAVE_PTHREAD_EXIT GC_API GC_PTHREAD_EXIT_ATTRIBUTE void WRAP_FUNC(pthread_exit)(void *retval) { pthread_t self = pthread_self(); @@ -1497,15 +1620,9 @@ GC_API int WRAP_FUNC(pthread_detach)(pthread_t thread) } UNLOCK(); -# ifdef NACL - /* Native Client doesn't support pthread cleanup functions, */ - /* so cleanup the thread here. */ - GC_thread_exit_proc(0); -# endif - REAL_FUNC(pthread_exit)(retval); } -#endif /* GC_PTHREAD_EXIT_ATTRIBUTE */ +#endif /* GC_HAVE_PTHREAD_EXIT */ GC_INNER GC_bool GC_in_thread_creation = FALSE; /* Protected by allocation lock. */ @@ -1550,10 +1667,7 @@ GC_API void GC_CALL GC_allow_register_threads(void) { /* Check GC is initialized and the current thread is registered. */ GC_ASSERT(GC_lookup_thread(pthread_self()) != 0); - -# ifndef GC_ALWAYS_MULTITHREADED - GC_need_to_lock = TRUE; /* We are multi-threaded now. */ -# endif + set_need_to_lock(); } GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) @@ -1580,6 +1694,11 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) } else if ((me -> flags & FINISHED) != 0) { /* This code is executed when a thread is registered from the */ /* client thread key destructor. */ +# ifdef GC_DARWIN_THREADS + /* Reinitialize mach_thread to avoid thread_suspend fail */ + /* with MACH_SEND_INVALID_DEST error. */ + me -> stop_info.mach_thread = mach_thread_self(); +# endif GC_record_stack_base(me, sb); me -> flags &= ~FINISHED; /* but not DETACHED */ # ifdef GC_EXPLICIT_SIGNALS_UNBLOCK @@ -1621,7 +1740,7 @@ GC_INNER_PTHRSTART GC_thread GC_start_rtn_prepare_thread( # ifdef DEBUG_THREADS GC_log_printf("Starting thread %p, pid = %ld, sp = %p\n", - (void *)self, (long)getpid(), &arg); + (void *)self, (long)getpid(), (void *)&arg); # endif LOCK(); me = GC_register_my_thread_inner(sb, self); @@ -1726,13 +1845,7 @@ GC_API int WRAP_FUNC(pthread_create)(pthread_t *new_thread, # endif stack_size = 1000000; } -# ifdef PARALLEL_MARK - GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word))); -# else - /* FreeBSD-5.3/Alpha: default pthread stack is 64K, */ - /* HBLKSIZE=8192, sizeof(word)=8 */ - GC_ASSERT(stack_size >= 65536); -# endif + GC_ASSERT(stack_size >= MIN_STACK_SIZE); /* Our threads may need to do some work for the GC. */ /* Ridiculously small threads won't work, and they */ /* probably wouldn't work anyway. */ @@ -1750,10 +1863,7 @@ GC_API int WRAP_FUNC(pthread_create)(pthread_t *new_thread, GC_log_printf("About to start new thread from thread %p\n", (void *)pthread_self()); # endif -# ifndef GC_ALWAYS_MULTITHREADED - GC_need_to_lock = TRUE; -# endif - + set_need_to_lock(); result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, si); /* Wait until child has been added to the thread table. */ @@ -1764,12 +1874,16 @@ GC_API int WRAP_FUNC(pthread_create)(pthread_t *new_thread, IF_CANCEL(int cancel_state;) # ifdef DEBUG_THREADS - if (new_thread) + /* new_thread is non-NULL because pthread_create requires it. */ GC_log_printf("Started thread %p\n", (void *)(*new_thread)); # endif DISABLE_CANCEL(cancel_state); /* pthread_create is not a cancellation point. */ while (0 != sem_wait(&(si -> registered))) { +# if defined(GC_HAIKU_THREADS) + /* To workaround some bug in Haiku semaphores. */ + if (EACCES == errno) continue; +# endif if (EINTR != errno) ABORT("sem_wait failed"); } RESTORE_CANCEL(cancel_state); @@ -1925,7 +2039,7 @@ yield: # define SLEEP_THRESHOLD 12 /* Under Linux very short sleeps tend to wait until */ /* the current time quantum expires. On old Linux */ - /* kernels nanosleep(<= 2ms) just spins under Linux. */ + /* kernels nanosleep (<= 2 msecs) just spins. */ /* (Under 2.4, this happens only for real-time */ /* processes.) We want to minimize both behaviors */ /* here. */ @@ -1935,8 +2049,8 @@ yield: struct timespec ts; if (i > 24) i = 24; - /* Don't wait for more than about 15msecs, even */ - /* under extreme contention. */ + /* Don't wait for more than about 15 msecs, */ + /* even under extreme contention. */ ts.tv_sec = 0; ts.tv_nsec = 1 << i; nanosleep(&ts, 0); @@ -2092,11 +2206,10 @@ GC_INNER void GC_notify_all_builder(void) } } -static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER; - GC_INNER void GC_wait_marker(void) { ASSERT_CANCEL_DISABLED(); + GC_ASSERT(GC_parallel); UNSET_MARK_LOCK_HOLDER; if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) { ABORT("pthread_cond_wait failed"); @@ -2107,6 +2220,7 @@ GC_INNER void GC_wait_marker(void) GC_INNER void GC_notify_all_marker(void) { + GC_ASSERT(GC_parallel); if (pthread_cond_broadcast(&mark_cv) != 0) { ABORT("pthread_cond_broadcast failed"); } diff --git a/src/bdwgc/ptr_chck.c b/src/bdwgc/ptr_chck.c index 011b27efb..687aabe67 100644 --- a/src/bdwgc/ptr_chck.c +++ b/src/bdwgc/ptr_chck.c @@ -131,8 +131,7 @@ GC_API void * GC_CALL GC_is_valid_displacement(void *p) h = FORWARDED_ADDR(h, hhdr); hhdr = HDR(h); } - } - if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { + } else if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) { goto fail; } sz = hhdr -> hb_sz; @@ -140,7 +139,8 @@ GC_API void * GC_CALL GC_is_valid_displacement(void *p) offset = pdispl % sz; if ((sz > MAXOBJBYTES && (word)p >= (word)h + sz) || !GC_valid_offsets[offset] - || (word)p - offset + sz > (word)(h + 1)) { + || ((word)p + (sz - offset) > (word)(h + 1) + && !IS_FORWARDING_ADDR_OR_NIL(HDR(h + 1)))) { goto fail; } return(p); @@ -178,7 +178,7 @@ void (GC_CALLBACK *GC_is_visible_print_proc)(void * p) = /* Check that p is visible */ /* to the collector as a possibly pointer containing location. */ -/* If it isn't invoke *GC_is_visible_print_proc. */ +/* If it isn't, invoke *GC_is_visible_print_proc. */ /* Returns the argument in all cases. May erroneously succeed */ /* in hard cases. (This is intended for debugging use with */ /* untyped allocations. The idea is that it should be possible, though */ @@ -215,10 +215,12 @@ GC_API void * GC_CALL GC_is_visible(void *p) } else { /* p points to the heap. */ word descr; - ptr_t base = GC_base(p); /* Should be manually inlined? */ + ptr_t base = (ptr_t)GC_base(p); + /* TODO: should GC_base be manually inlined? */ - if (base == 0) goto fail; - if (HBLKPTR(base) != HBLKPTR(p)) hhdr = HDR((word)p); + if (NULL == base) goto fail; + if (HBLKPTR(base) != HBLKPTR(p)) + hhdr = HDR(base); descr = hhdr -> hb_descr; retry: switch(descr & GC_DS_TAGS) { diff --git a/src/bdwgc/reclaim.c b/src/bdwgc/reclaim.c index a332ef67b..246802fa3 100644 --- a/src/bdwgc/reclaim.c +++ b/src/bdwgc/reclaim.c @@ -28,10 +28,11 @@ GC_INNER signed_word GC_bytes_found = 0; /* on free lists which we had to drop. */ #if defined(PARALLEL_MARK) - GC_INNER word GC_fl_builder_count = 0; + GC_INNER signed_word GC_fl_builder_count = 0; /* Number of threads currently building free lists without */ /* holding GC lock. It is not safe to collect if this is */ - /* nonzero. */ + /* nonzero. Also, together with the mark lock, it is used as */ + /* a semaphore during marker threads startup. */ #endif /* PARALLEL_MARK */ /* We defer printing of leaked objects until we're done with the GC */ @@ -222,7 +223,7 @@ STATIC ptr_t GC_reclaim_uninit(struct hblk *hbp, hdr *hhdr, size_t sz, STATIC ptr_t GC_disclaim_and_reclaim(struct hblk *hbp, hdr *hhdr, size_t sz, ptr_t list, signed_word *count) { - int bit_no = 0; + word bit_no = 0; word *p, *q, *plim; signed_word n_bytes_found = 0; struct obj_kind *ok = &GC_obj_kinds[hhdr->hb_obj_kind]; @@ -376,7 +377,6 @@ STATIC void GC_reclaim_block(struct hblk *hbp, word report_if_found) hdr * hhdr = HDR(hbp); size_t sz = hhdr -> hb_sz; /* size of objects in current block */ struct obj_kind * ok = &GC_obj_kinds[hhdr -> hb_obj_kind]; - struct hblk ** rlh; if( sz > MAXOBJBYTES ) { /* 1 big object */ if( !mark_bit_from_hdr(hhdr, 0) ) { @@ -387,7 +387,6 @@ STATIC void GC_reclaim_block(struct hblk *hbp, word report_if_found) # ifdef ENABLE_DISCLAIM if (EXPECT(hhdr->hb_flags & HAS_DISCLAIM, 0)) { - struct obj_kind *ok = &GC_obj_kinds[hhdr->hb_obj_kind]; if ((*ok->ok_disclaim_proc)(hbp)) { /* Not disclaimed => resurrect the object. */ set_mark_bit_from_hdr(hhdr, 0); @@ -439,9 +438,13 @@ STATIC void GC_reclaim_block(struct hblk *hbp, word report_if_found) } } else if (GC_find_leak || !GC_block_nearly_full(hhdr)) { /* group of smaller objects, enqueue the real work */ - rlh = &(ok -> ok_reclaim_list[BYTES_TO_GRANULES(sz)]); - hhdr -> hb_next = *rlh; - *rlh = hbp; + struct hblk **rlh = ok -> ok_reclaim_list; + + if (rlh != NULL) { + rlh += BYTES_TO_GRANULES(sz); + hhdr -> hb_next = *rlh; + *rlh = hbp; + } } /* else not worth salvaging. */ /* We used to do the nearly_full check later, but we */ /* already have the right cache context here. Also */ @@ -523,7 +526,7 @@ int GC_n_set_marks(hdr *hhdr) # else result += set_bits(hhdr -> hb_marks[n_mark_words - 1]); # endif - return(result - 1); + return result; /* the number of set bits excluding the one past the end */ } #endif /* !USE_MARK_BYTES */ @@ -535,19 +538,19 @@ STATIC void GC_print_block_descr(struct hblk *h, size_t bytes = hhdr -> hb_sz; struct Print_stats *ps; unsigned n_marks = GC_n_set_marks(hhdr); + unsigned n_objs = (unsigned)HBLK_OBJS(bytes); + if (0 == n_objs) n_objs = 1; if (hhdr -> hb_n_marks != n_marks) { - GC_printf("(%u:%u,%u!=%u)\n", hhdr->hb_obj_kind, (unsigned)bytes, - (unsigned)hhdr->hb_n_marks, n_marks); + GC_printf("%u,%u,%u!=%u,%u\n", hhdr->hb_obj_kind, (unsigned)bytes, + (unsigned)hhdr->hb_n_marks, n_marks, n_objs); } else { - GC_printf("(%u:%u,%u)\n", hhdr->hb_obj_kind, - (unsigned)bytes, n_marks); + GC_printf("%u,%u,%u,%u\n", hhdr->hb_obj_kind, (unsigned)bytes, + n_marks, n_objs); } - bytes += HBLKSIZE-1; - bytes &= ~(HBLKSIZE-1); ps = (struct Print_stats *)raw_ps; - ps->total_bytes += bytes; + ps->total_bytes += (bytes + (HBLKSIZE-1)) & ~(HBLKSIZE-1); /* round up */ ps->number_of_blocks++; } @@ -555,7 +558,8 @@ void GC_print_block_list(void) { struct Print_stats pstats; - GC_printf("(kind(0=ptrfree,1=normal,2=unc.):size_in_bytes, #_marks_set)\n"); + GC_printf("kind(0=ptrfree,1=normal,2=unc.)," + "size_in_bytes,#_marks_set,#objs\n"); pstats.number_of_blocks = 0; pstats.total_bytes = 0; GC_apply_to_all_blocks(GC_print_block_descr, (word)&pstats); @@ -564,17 +568,21 @@ void GC_print_block_list(void) (unsigned long)pstats.total_bytes); } +#include "gc_inline.h" /* for GC_print_free_list prototype */ + /* Currently for debugger use only: */ -void GC_print_free_list(int kind, size_t sz_in_granules) +GC_API void GC_CALL GC_print_free_list(int kind, size_t sz_in_granules) { - struct obj_kind * ok = &GC_obj_kinds[kind]; - ptr_t flh = ok -> ok_freelist[sz_in_granules]; + ptr_t flh; int n; + GC_ASSERT(kind < MAXOBJKINDS); + GC_ASSERT(sz_in_granules <= MAXOBJGRANULES); + flh = GC_obj_kinds[kind].ok_freelist[sz_in_granules]; for (n = 0; flh; n++) { struct hblk *block = HBLKPTR(flh); GC_printf("Free object in heap block %p [%d]: %p\n", - (void *)block, n, flh); + (void *)block, n, (void *)flh); flh = obj_link(flh); } } @@ -615,16 +623,16 @@ GC_INNER void GC_start_reclaim(GC_bool report_if_found) GC_atomic_in_use = 0; /* Clear reclaim- and free-lists */ for (kind = 0; kind < GC_n_kinds; kind++) { - void **fop; - void **lim; struct hblk ** rlist = GC_obj_kinds[kind].ok_reclaim_list; GC_bool should_clobber = (GC_obj_kinds[kind].ok_descriptor != 0); if (rlist == 0) continue; /* This kind not used. */ if (!report_if_found) { - lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJGRANULES+1]); + void **fop; + void **lim = &(GC_obj_kinds[kind].ok_freelist[MAXOBJGRANULES+1]); + for (fop = GC_obj_kinds[kind].ok_freelist; - (word)fop < (word)lim; fop++) { + (word)fop < (word)lim; (*(word **)&fop)++) { if (*fop != 0) { if (should_clobber) { GC_clear_fl_links(fop); @@ -702,7 +710,6 @@ GC_INNER GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old) struct hblk ** rlh; # ifndef SMALL_CONFIG CLOCK_TYPE start_time = 0; /* initialized to prevent warning. */ - CLOCK_TYPE done_time; if (GC_print_stats == VERBOSE) GET_TIME(start_time); @@ -720,7 +727,8 @@ GC_INNER GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old) } hhdr = HDR(hbp); *rlh = hhdr -> hb_next; - if (!ignore_old || hhdr -> hb_last_reclaimed == GC_gc_no - 1) { + if (!ignore_old + || (word)hhdr->hb_last_reclaimed == GC_gc_no - 1) { /* It's likely we'll need it this time, too */ /* It's been touched recently, so this */ /* shouldn't trigger paging. */ @@ -731,6 +739,8 @@ GC_INNER GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old) } # ifndef SMALL_CONFIG if (GC_print_stats == VERBOSE) { + CLOCK_TYPE done_time; + GET_TIME(done_time); GC_verbose_log_printf("Disposing of reclaim lists took %lu msecs\n", MS_TIME_DIFF(done_time,start_time)); @@ -772,3 +782,46 @@ GC_INNER GC_bool GC_reclaim_all(GC_stop_func stop_func, GC_bool ignore_old) } } #endif /* !EAGER_SWEEP && ENABLE_DISCLAIM */ + +struct enumerate_reachable_s { + GC_reachable_object_proc proc; + void *client_data; +}; + +STATIC void GC_do_enumerate_reachable_objects(struct hblk *hbp, word ped) +{ + struct hblkhdr *hhdr = HDR(hbp); + size_t sz = hhdr -> hb_sz; + size_t bit_no; + char *p, *plim; + + if (GC_block_empty(hhdr)) { + return; + } + + p = hbp->hb_body; + if (sz > MAXOBJBYTES) { /* one big object */ + plim = p; + } else { + plim = hbp->hb_body + HBLKSIZE - sz; + } + /* Go through all words in block. */ + for (bit_no = 0; p <= plim; bit_no += MARK_BIT_OFFSET(sz), p += sz) { + if (mark_bit_from_hdr(hhdr, bit_no)) { + ((struct enumerate_reachable_s *)ped)->proc(p, sz, + ((struct enumerate_reachable_s *)ped)->client_data); + } + } +} + +GC_API void GC_CALL GC_enumerate_reachable_objects_inner( + GC_reachable_object_proc proc, + void *client_data) +{ + struct enumerate_reachable_s ed; + + GC_ASSERT(I_HOLD_LOCK()); + ed.proc = proc; + ed.client_data = client_data; + GC_apply_to_all_blocks(GC_do_enumerate_reachable_objects, (word)&ed); +} diff --git a/src/bdwgc/specific.c b/src/bdwgc/specific.c index ba23e47d1..579be6f7b 100644 --- a/src/bdwgc/specific.c +++ b/src/bdwgc/specific.c @@ -46,13 +46,13 @@ GC_INNER int GC_key_create_inner(tsd ** key_ptr) return 0; } -/* Called with the lock held. */ GC_INNER int GC_setspecific(tsd * key, void * value) { pthread_t self = pthread_self(); int hash_val = HASH(self); volatile tse * entry; + GC_ASSERT(I_HOLD_LOCK()); GC_ASSERT(self != INVALID_THREADID); GC_dont_gc++; /* disable GC */ entry = (volatile tse *)MALLOC_CLEAR(sizeof(tse)); @@ -68,30 +68,44 @@ GC_INNER int GC_setspecific(tsd * key, void * value) /* There can only be one writer at a time, but this needs to be */ /* atomic with respect to concurrent readers. */ AO_store_release(&key->hash[hash_val].ao, (AO_t)entry); + GC_dirty((/* no volatile */ void *)entry); + GC_dirty(key->hash + hash_val); pthread_mutex_unlock(&(key -> lock)); return 0; } -/* Remove thread-specific data for this thread. Should be called on */ -/* thread exit. */ -GC_INNER void GC_remove_specific(tsd * key) +/* Remove thread-specific data for a given thread. This function is */ +/* called at fork from the child process for all threads except for the */ +/* survived one. GC_remove_specific() should be called on thread exit. */ +GC_INNER void GC_remove_specific_after_fork(tsd * key, pthread_t t) { - pthread_t self = pthread_self(); - unsigned hash_val = HASH(self); + unsigned hash_val = HASH(t); tse *entry; - tse **link = &key->hash[hash_val].p; + tse *prev = NULL; +# ifdef CAN_HANDLE_FORK + /* Both GC_setspecific and GC_remove_specific should be called */ + /* with the allocation lock held to ensure the consistency of */ + /* the hash table in the forked child. */ + GC_ASSERT(I_HOLD_LOCK()); +# endif pthread_mutex_lock(&(key -> lock)); - entry = *link; - while (entry != NULL && entry -> thread != self) { - link = &(entry -> next); - entry = *link; + entry = key->hash[hash_val].p; + while (entry != NULL && entry -> thread != t) { + prev = entry; + entry = entry->next; } /* Invalidate qtid field, since qtids may be reused, and a later */ /* cache lookup could otherwise find this entry. */ if (entry != NULL) { entry -> qtid = INVALID_QTID; - *link = entry -> next; + if (NULL == prev) { + key->hash[hash_val].p = entry->next; + GC_dirty(key->hash + hash_val); + } else { + prev->next = entry->next; + GC_dirty(prev); + } /* Atomic! concurrent accesses still work. */ /* They must, since readers don't lock. */ /* We shouldn't need a volatile access here, */ @@ -105,6 +119,9 @@ GC_INNER void GC_remove_specific(tsd * key) /* cache lookup, which should still be examining deallocated memory.*/ /* This can only happen if the concurrent access is from another */ /* thread, and hence has missed the cache, but still... */ +# ifdef LINT2 + GC_noop1((word)entry); +# endif /* With GC, we're done, since the pointers from the cache will */ /* be overwritten, all local pointers to the entries will be */ @@ -151,14 +168,16 @@ GC_INNER void * GC_slow_getspecific(tsd * key, word qtid, for (i = 0; i < TS_HASH_SIZE; ++i) { for (p = key->hash[i].p; p != 0; p = p -> next) { if (!GC_is_marked(GC_base(p))) { - ABORT_ARG1("Unmarked thread-specific-data entry", " at %p", p); + ABORT_ARG1("Unmarked thread-specific-data entry", + " at %p", (void *)p); } } } for (i = 0; i < TS_CACHE_SIZE; ++i) { p = key -> cache[i]; if (p != &invalid_tse && !GC_is_marked(GC_base(p))) { - ABORT_ARG1("Unmarked cached thread-specific-data entry", " at %p", p); + ABORT_ARG1("Unmarked cached thread-specific-data entry", + " at %p", (void *)p); } } } diff --git a/src/bdwgc/stubborn.c b/src/bdwgc/stubborn.c index cc5d08ae5..a8edd05af 100644 --- a/src/bdwgc/stubborn.c +++ b/src/bdwgc/stubborn.c @@ -22,8 +22,6 @@ /* written, but not yet GC_dirty()ed objects must be referenced */ /* by a stack. */ - void GC_dirty(ptr_t p); - GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_stubborn(size_t lb) { return(GC_malloc(lb)); @@ -31,7 +29,7 @@ GC_API void GC_CALL GC_end_stubborn_change(const void *p) { - GC_dirty((ptr_t)p); + GC_dirty(p); /* entire object */ } GC_API void GC_CALL GC_change_stubborn(const void *p GC_ATTR_UNUSED) diff --git a/src/bdwgc/tests/CMakeLists.txt b/src/bdwgc/tests/CMakeLists.txt index 0f4d455f6..26663493f 100644 --- a/src/bdwgc/tests/CMakeLists.txt +++ b/src/bdwgc/tests/CMakeLists.txt @@ -15,5 +15,27 @@ ## ADD_DEFINITIONS(-DGC_NOT_DLL) + ADD_EXECUTABLE(gctest WIN32 test.c) TARGET_LINK_LIBRARIES(gctest gc-lib) +ADD_TEST(NAME gctest COMMAND gctest) + +ADD_EXECUTABLE(hugetest huge_test.c) +TARGET_LINK_LIBRARIES(hugetest gc-lib) +ADD_TEST(NAME hugetest COMMAND hugetest) + +ADD_EXECUTABLE(leaktest leak_test.c) +TARGET_LINK_LIBRARIES(leaktest gc-lib) +ADD_TEST(NAME leaktest COMMAND leaktest) + +ADD_EXECUTABLE(middletest middle.c) +TARGET_LINK_LIBRARIES(middletest gc-lib) +ADD_TEST(NAME middletest COMMAND middletest) + +ADD_EXECUTABLE(realloc_test realloc_test.c) +TARGET_LINK_LIBRARIES(realloc_test gc-lib) +ADD_TEST(NAME realloc_test COMMAND realloc_test) + +ADD_EXECUTABLE(smashtest smash_test.c) +TARGET_LINK_LIBRARIES(smashtest gc-lib) +ADD_TEST(NAME smashtest COMMAND smashtest) diff --git a/src/bdwgc/tests/disclaim_bench.c b/src/bdwgc/tests/disclaim_bench.c index f9bfc5805..cf9523245 100644 --- a/src/bdwgc/tests/disclaim_bench.c +++ b/src/bdwgc/tests/disclaim_bench.c @@ -16,10 +16,21 @@ #include #include -#include "private/gc_priv.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include "gc_disclaim.h" +/* Include gc_priv.h is done after including GC public headers, so */ +/* that GC_BUILD has no effect on the public prototypes. */ +#include "private/gc_priv.h" /* for CLOCK_TYPE, COVERT_DATAFLOW, GC_random */ + +#ifdef LINT2 +# undef rand +# define rand() (int)GC_random() +#endif + #define my_assert(e) \ if (!(e)) { \ fprintf(stderr, "Assertion failure, line %d: " #e "\n", __LINE__); \ @@ -54,7 +65,7 @@ testobj_t testobj_new(int model) case 0: obj = GC_MALLOC(sizeof(struct testobj_s)); if (obj != NULL) - GC_register_finalizer_no_order(obj, testobj_finalize, + GC_REGISTER_FINALIZER_NO_ORDER(obj, testobj_finalize, &free_count, NULL, NULL); break; case 1: @@ -92,9 +103,6 @@ int main(int argc, char **argv) GC_INIT(); GC_init_finalized_malloc(); - - keep_arr = GC_MALLOC(sizeof(void *)*KEEP_CNT); - if (argc == 2 && strcmp(argv[1], "--help") == 0) { fprintf(stderr, "Usage: %s [FINALIZATION_MODEL]\n" @@ -104,7 +112,7 @@ int main(int argc, char **argv) return 1; } if (argc == 2) { - model_min = model_max = atoi(argv[1]); + model_min = model_max = (int)COVERT_DATAFLOW(atoi(argv[1])); if (model_min < 0 || model_max > 2) exit(2); } @@ -113,30 +121,36 @@ int main(int argc, char **argv) model_max = 2; } + keep_arr = GC_MALLOC(sizeof(void *) * KEEP_CNT); + if (NULL == keep_arr) { + fprintf(stderr, "Out of memory!\n"); + exit(3); + } + printf("\t\t\tfin. ratio time/s time/fin.\n"); for (model = model_min; model <= model_max; ++model) { double t = 0.0; - free_count = 0; - -# ifdef CLOCK_TYPE +# ifndef NO_CLOCK CLOCK_TYPE tI, tF; + GET_TIME(tI); # endif + free_count = 0; for (i = 0; i < ALLOC_CNT; ++i) { int k = rand() % KEEP_CNT; keep_arr[k] = testobj_new(model); } GC_gcollect(); -# ifdef CLOCK_TYPE +# ifndef NO_CLOCK GET_TIME(tF); t = MS_TIME_DIFF(tF, tI)*1e-3; # endif - if (model < 2) - printf("%20s: %12.4lf %12lg %12lg\n", model_str[model], + if (model < 2 && free_count > 0) + printf("%20s: %12.4f %12g %12g\n", model_str[model], free_count/(double)ALLOC_CNT, t, t/free_count); else - printf("%20s: %12.4lf %12lg %12s\n", + printf("%20s: %12.4f %12g %12s\n", model_str[model], 0.0, t, "N/A"); } return 0; diff --git a/src/bdwgc/tests/disclaim_test.c b/src/bdwgc/tests/disclaim_test.c index 659bf106c..a82d2b5de 100644 --- a/src/bdwgc/tests/disclaim_test.c +++ b/src/bdwgc/tests/disclaim_test.c @@ -25,8 +25,19 @@ # include "config.h" #endif +#undef GC_NO_THREAD_REDIRECTS #include "gc_disclaim.h" +#ifdef LINT2 + /* Avoid include gc_priv.h. */ +# ifndef GC_API_PRIV +# define GC_API_PRIV GC_API +# endif + GC_API_PRIV long GC_random(void); +# undef rand +# define rand() (int)GC_random() +#endif /* LINT2 */ + #define my_assert(e) \ if (!(e)) { \ fflush(stdout); \ @@ -80,7 +91,7 @@ struct pair_s { pair_t cdr; }; -static const char *pair_magic = "PAIR_MAGIC_BYTES"; +static const char * const pair_magic = "PAIR_MAGIC_BYTES"; int is_pair(pair_t p) { @@ -111,6 +122,8 @@ void GC_CALLBACK pair_dct(void *obj, void *cd) p->checksum = 0; p->car = cd; p->cdr = NULL; + GC_end_stubborn_change(p); + GC_reachable_here(cd); } pair_t @@ -120,16 +133,19 @@ pair_new(pair_t car, pair_t cdr) static const struct GC_finalizer_closure fc = { pair_dct, NULL }; p = GC_finalized_malloc(sizeof(struct pair_s), &fc); - my_assert(!is_pair(p)); if (p == NULL) { fprintf(stderr, "Out of memory!\n"); exit(3); } + my_assert(!is_pair(p)); my_assert(memeq(p, 0, sizeof(struct pair_s))); memcpy(p->magic, pair_magic, sizeof(p->magic)); p->checksum = 782 + (car? car->checksum : 0) + (cdr? cdr->checksum : 0); p->car = car; p->cdr = cdr; + GC_end_stubborn_change(p); + GC_reachable_here(car); + GC_reachable_here(cdr); # ifdef DEBUG_DISCLAIM_DESTRUCT printf("Construct %p = (%p, %p)\n", (void *)p, (void *)p->car, (void *)p->cdr); @@ -165,7 +181,7 @@ pair_check_rec(pair_t p) #else # define MUTATE_CNT 10000000 #endif -#define GROW_LIMIT 10000000 +#define GROW_LIMIT (MUTATE_CNT/10) void *test(void *data) { diff --git a/src/bdwgc/tests/huge_test.c b/src/bdwgc/tests/huge_test.c index bde9836d5..bd3ad6c74 100644 --- a/src/bdwgc/tests/huge_test.c +++ b/src/bdwgc/tests/huge_test.c @@ -5,11 +5,26 @@ #ifndef GC_IGNORE_WARN /* Ignore misleading "Out of Memory!" warning (which is printed on */ - /* every GC_MALLOC(LONG_MAX) call) by defining this macro before */ - /* "gc.h" inclusion. */ + /* every GC_MALLOC call below) by defining this macro before "gc.h" */ + /* inclusion. */ # define GC_IGNORE_WARN #endif +#ifndef GC_MAXIMUM_HEAP_SIZE +# define GC_MAXIMUM_HEAP_SIZE 100 * 1024 * 1024 +# define GC_INITIAL_HEAP_SIZE GC_MAXIMUM_HEAP_SIZE / 20 + /* Otherwise heap expansion aborts when deallocating large block. */ + /* That's OK. We test this corner case mostly to make sure that */ + /* it fails predictably. */ +#endif + +#ifndef GC_ATTR_ALLOC_SIZE + /* Omit alloc_size attribute to avoid compiler warnings about */ + /* exceeding maximum object size when values close to GC_SWORD_MAX */ + /* are passed to GC_MALLOC. */ +# define GC_ATTR_ALLOC_SIZE(argnum) /* empty */ +#endif + #include "gc.h" /* @@ -19,34 +34,31 @@ * expected manner. */ +#define CHECK_ALLOC_FAILED(r, sz_str) \ + do { \ + if (NULL != (r)) { \ + fprintf(stderr, \ + "Size " sz_str " allocation unexpectedly succeeded\n"); \ + exit(1); \ + } \ + } while (0) + +#define GC_WORD_MAX ((GC_word)-1) +#define GC_SWORD_MAX ((GC_signed_word)(GC_WORD_MAX >> 1)) + int main(void) { GC_INIT(); - GC_set_max_heap_size(100*1024*1024); - /* Otherwise heap expansion aborts when deallocating large block. */ - /* That's OK. We test this corner case mostly to make sure that */ - /* it fails predictably. */ - GC_expand_hp(1024*1024*5); - if (sizeof(long) == sizeof(void *)) { - void *r = GC_MALLOC(LONG_MAX-1024); - if (0 != r) { - fprintf(stderr, - "Size LONG_MAX-1024 allocation unexpectedly succeeded\n"); - exit(1); - } - r = GC_MALLOC(LONG_MAX); - if (0 != r) { - fprintf(stderr, - "Size LONG_MAX allocation unexpectedly succeeded\n"); - exit(1); - } - r = GC_MALLOC((size_t)LONG_MAX + 1024); - if (0 != r) { - fprintf(stderr, - "Size LONG_MAX+1024 allocation unexpectedly succeeded\n"); - exit(1); - } - } + CHECK_ALLOC_FAILED(GC_MALLOC(GC_SWORD_MAX - 1024), "SWORD_MAX-1024"); + CHECK_ALLOC_FAILED(GC_MALLOC(GC_SWORD_MAX), "SWORD_MAX"); + CHECK_ALLOC_FAILED(GC_MALLOC((GC_word)GC_SWORD_MAX + 1), "SWORD_MAX+1"); + CHECK_ALLOC_FAILED(GC_MALLOC((GC_word)GC_SWORD_MAX + 1024), + "SWORD_MAX+1024"); + CHECK_ALLOC_FAILED(GC_MALLOC(GC_WORD_MAX - 1024), "WORD_MAX-1024"); + CHECK_ALLOC_FAILED(GC_MALLOC(GC_WORD_MAX - 16), "WORD_MAX-16"); + CHECK_ALLOC_FAILED(GC_MALLOC(GC_WORD_MAX - 8), "WORD_MAX-8"); + CHECK_ALLOC_FAILED(GC_MALLOC(GC_WORD_MAX - 4), "WORD_MAX-4"); + CHECK_ALLOC_FAILED(GC_MALLOC(GC_WORD_MAX), "WORD_MAX"); return 0; } diff --git a/src/bdwgc/tests/initsecondarythread.c b/src/bdwgc/tests/initsecondarythread.c index 5f2140500..9893fb5c1 100644 --- a/src/bdwgc/tests/initsecondarythread.c +++ b/src/bdwgc/tests/initsecondarythread.c @@ -60,6 +60,10 @@ int main(void) # ifdef GC_PTHREADS int code; pthread_t t; + +# ifdef LINT2 + t = pthread_self(); /* explicitly initialize to some value */ +# endif # else HANDLE t; DWORD thread_id; @@ -67,13 +71,16 @@ int main(void) # if !(defined(BEOS) || defined(MSWIN32) || defined(MSWINCE) \ || defined(CYGWIN32) || defined(GC_OPENBSD_UTHREADS) \ || (defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP)) \ - || (defined(LINUX) && !defined(NACL)) \ + || ((defined(FREEBSD) || defined(LINUX) || defined(NETBSD) \ + || defined(PLATFORM_ANDROID)) && !defined(NO_PTHREAD_GETATTR_NP) \ + && !defined(NO_PTHREAD_ATTR_GET_NP)) \ || (defined(GC_SOLARIS_THREADS) && !defined(_STRICT_STDC)) \ || (!defined(STACKBOTTOM) && (defined(HEURISTIC1) \ || (!defined(LINUX_STACKBOTTOM) && !defined(FREEBSD_STACKBOTTOM))))) /* GC_INIT() must be called from main thread only. */ GC_INIT(); # endif + (void)GC_get_parallel(); /* linking fails if no threads support */ # ifdef GC_PTHREADS if ((code = pthread_create (&t, NULL, thread, NULL)) != 0) { fprintf(stderr, "Thread creation failed %d\n", code); diff --git a/src/bdwgc/tests/staticrootslib.c b/src/bdwgc/tests/staticrootslib.c index ef828c7be..3fd4f4f18 100644 --- a/src/bdwgc/tests/staticrootslib.c +++ b/src/bdwgc/tests/staticrootslib.c @@ -35,8 +35,15 @@ static struct treenode *root_nz[10] = { (void *)(GC_word)2 }; if (0 == i) return 0; if (1 == i) r = GC_MALLOC_ATOMIC(sizeof(struct treenode)); if (r) { - r -> x = libsrl_mktree(i-1); - r -> y = libsrl_mktree(i-1); + struct treenode *x = libsrl_mktree(i - 1); + struct treenode *y = libsrl_mktree(i - 1); + r -> x = x; + r -> y = y; + if (i != 1) { + GC_END_STUBBORN_CHANGE(r); + GC_reachable_here(x); + GC_reachable_here(y); + } } return r; } diff --git a/src/bdwgc/tests/staticrootstest.c b/src/bdwgc/tests/staticrootstest.c index 34ce9b40b..fc2b9b36a 100644 --- a/src/bdwgc/tests/staticrootstest.c +++ b/src/bdwgc/tests/staticrootstest.c @@ -25,7 +25,7 @@ struct treenode *root[10] = { NULL }; /* be placed to .data section instead of .bss). */ struct treenode *root_nz[10] = { (void *)(GC_word)1 }; -static char *staticroot = 0; +static char *staticroot; /* intentionally static */ GC_TEST_IMPORT_API struct treenode * libsrl_mktree(int i); GC_TEST_IMPORT_API void * libsrl_init(void); @@ -33,6 +33,14 @@ GC_TEST_IMPORT_API struct treenode ** libsrl_getpelem(int i, int j); GC_TEST_IMPORT_API struct treenode ** libsrl_getpelem2(int i, int j); +void init_staticroot(void) +{ + /* Intentionally put staticroot initialization in a function other */ + /* than main to prevent CSA warning that staticroot variable can be */ + /* changed to be a local one). */ + staticroot = libsrl_init(); +} + int main(void) { int i, j; @@ -40,7 +48,7 @@ int main(void) # ifdef STATICROOTSLIB_INIT_IN_MAIN GC_INIT(); # endif - staticroot = libsrl_init(); + init_staticroot(); if (NULL == staticroot) { fprintf(stderr, "GC_malloc returned NULL\n"); return 2; diff --git a/src/bdwgc/tests/subthread_create.c b/src/bdwgc/tests/subthread_create.c index 9a7095b6d..e67b3b1da 100644 --- a/src/bdwgc/tests/subthread_create.c +++ b/src/bdwgc/tests/subthread_create.c @@ -16,7 +16,7 @@ #include -#ifdef AO_HAVE_fetch_and_add +#ifdef AO_HAVE_fetch_and_add1 #ifdef GC_PTHREADS # include @@ -24,6 +24,10 @@ # include #endif +#if defined(__HAIKU__) +# include +#endif + #include #include @@ -48,26 +52,34 @@ volatile AO_t thread_ended_cnt = 0; DWORD WINAPI entry(LPVOID arg) #endif { - int thread_num = AO_fetch_and_add(&thread_created_cnt, 1); + int thread_num = AO_fetch_and_add1(&thread_created_cnt); GC_word my_depth = (GC_word)arg + 1; if (my_depth <= MAX_SUBTHREAD_DEPTH && thread_num < MAX_SUBTHREAD_COUNT && (thread_num % DECAY_DENOM) < DECAY_NUMER - && (int)(thread_num - AO_load(&thread_ended_cnt)) + && thread_num - (int)AO_load(&thread_ended_cnt) <= MAX_ALIVE_THREAD_COUNT) { # ifdef GC_PTHREADS int err; pthread_t th; + err = pthread_create(&th, NULL, entry, (void *)my_depth); - if (err) { - fprintf(stderr, "Thread #%d creation failed: %s", thread_num, + if (err != 0) { + fprintf(stderr, "Thread #%d creation failed: %s\n", thread_num, + strerror(err)); + exit(2); + } + err = pthread_detach(th); + if (err != 0) { + fprintf(stderr, "Thread #%d detach failed: %s\n", thread_num, strerror(err)); exit(2); } # else HANDLE th; DWORD thread_id; + th = CreateThread(NULL, 0, entry, (LPVOID)my_depth, 0, &thread_id); if (th == NULL) { fprintf(stderr, "Thread #%d creation failed: %d\n", thread_num, @@ -78,7 +90,7 @@ volatile AO_t thread_ended_cnt = 0; # endif } - AO_fetch_and_add(&thread_ended_cnt, 1); + (void)AO_fetch_and_add1(&thread_ended_cnt); return 0; } @@ -97,7 +109,7 @@ int main(void) # ifdef GC_PTHREADS err = pthread_create(&th[i], NULL, entry, 0); if (err) { - fprintf(stderr, "Thread creation failed: %s", strerror(err)); + fprintf(stderr, "Thread creation failed: %s\n", strerror(err)); exit(1); } # else @@ -116,7 +128,13 @@ int main(void) void *res; err = pthread_join(th[i], &res); if (err) { - fprintf(stderr, "Failed to join thread: %s", strerror(err)); + fprintf(stderr, "Failed to join thread: %s\n", strerror(err)); +# if defined(__HAIKU__) + /* The error is just ignored (and the test is ended) to */ + /* workaround some bug in Haiku pthread_join. */ + /* TODO: The thread is not deleted from GC_threads. */ + if (ESRCH == err) break; +# endif exit(1); } # else @@ -142,4 +160,4 @@ int main(void) return 0; } -#endif /* !AO_HAVE_fetch_and_add */ +#endif /* !AO_HAVE_fetch_and_add1 */ diff --git a/src/bdwgc/tests/test.c b/src/bdwgc/tests/test.c index 446a6b883..067ead4c1 100644 --- a/src/bdwgc/tests/test.c +++ b/src/bdwgc/tests/test.c @@ -24,10 +24,15 @@ # undef GC_BUILD -#if (defined(DBG_HDRS_ALL) || defined(MAKE_BACK_GRAPH)) && !defined(GC_DEBUG) +#if (defined(DBG_HDRS_ALL) || defined(MAKE_BACK_GRAPH)) \ + && !defined(GC_DEBUG) && !defined(CPPCHECK) # define GC_DEBUG #endif +#if defined(CPPCHECK) && defined(GC_PTHREADS) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE 1 +#endif +#undef GC_NO_THREAD_REDIRECTS #include "gc.h" #ifndef NTHREADS /* Number of additional threads to fork. */ @@ -82,8 +87,10 @@ # define GC_printf printf # endif -# if defined(GC_PTHREADS) +# if defined(GC_PTHREADS) && !defined(GC_WIN32_PTHREADS) # include +# else +# define NO_TEST_HANDLE_FORK # endif # if (!defined(THREADS) || !defined(HANDLE_FORK) \ @@ -96,6 +103,8 @@ # ifndef NO_TEST_HANDLE_FORK # include +# include +# include # ifdef HANDLE_FORK # define INIT_FORK_SUPPORT GC_set_handle_fork(1) /* Causes abort in GC_init on pthread_atfork failure. */ @@ -110,13 +119,25 @@ # define INIT_FORK_SUPPORT /* empty */ # endif -# if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) - static CRITICAL_SECTION incr_cs; -# endif +#ifdef PCR +# define FINALIZER_LOCK() PCR_ThCrSec_EnterSys() +# define FINALIZER_UNLOCK() PCR_ThCrSec_ExitSys() +#elif defined(GC_PTHREADS) + static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; +# define FINALIZER_LOCK() pthread_mutex_lock(&incr_lock) +# define FINALIZER_UNLOCK() pthread_mutex_unlock(&incr_lock) +#elif defined(GC_WIN32_THREADS) + static CRITICAL_SECTION incr_cs; +# define FINALIZER_LOCK() EnterCriticalSection(&incr_cs) +# define FINALIZER_UNLOCK() LeaveCriticalSection(&incr_cs) +#else +# define FINALIZER_LOCK() (void)0 +# define FINALIZER_UNLOCK() (void)0 +#endif /* !THREADS */ -# include +#include -#define CHECH_GCLIB_VERSION \ +#define CHECK_GCLIB_VERSION \ if (GC_get_version() != ((GC_VERSION_MAJOR<<16) \ | (GC_VERSION_MINOR<<8) \ | GC_VERSION_MICRO)) { \ @@ -126,16 +147,21 @@ /* Call GC_INIT only on platforms on which we think we really need it, */ /* so that we can test automatic initialization on the rest. */ -#if defined(CYGWIN32) || defined (AIX) || defined(DARWIN) \ - || defined(PLATFORM_ANDROID) || defined(THREAD_LOCAL_ALLOC) \ +#if defined(TEST_EXPLICIT_GC_INIT) || defined(AIX) || defined(CYGWIN32) \ + || defined(DARWIN) || defined(PLATFORM_ANDROID) \ || (defined(MSWINCE) && !defined(GC_WINMAIN_REDIRECT)) # define GC_OPT_INIT GC_INIT() #else # define GC_OPT_INIT /* empty */ #endif +#define INIT_FIND_LEAK \ + if (!GC_get_find_leak()) {} else \ + GC_printf("This test program is not designed for leak detection mode\n") + #define GC_COND_INIT() \ - INIT_FORK_SUPPORT; GC_OPT_INIT; CHECH_GCLIB_VERSION; INIT_PRINT_STATS + INIT_FORK_SUPPORT; GC_OPT_INIT; CHECK_GCLIB_VERSION; \ + INIT_PRINT_STATS; INIT_FIND_LEAK #define CHECK_OUT_OF_MEMORY(p) \ if ((p) == NULL) { \ @@ -143,19 +169,57 @@ exit(1); \ } -/* Allocation Statistics. Incremented without synchronization. */ -/* FIXME: We should be using synchronization. */ -int stubborn_count = 0; -int uncollectable_count = 0; -int collectable_count = 0; -int atomic_count = 0; -int realloc_count = 0; +#if defined(THREADS) && (defined(PARALLEL_MARK) \ + || !defined(GC_WIN32_THREADS)) +# include "atomic_ops.h" /* for counters */ +#endif + +/* Define AO primitives for a single-threaded mode. */ +#ifndef AO_CLEAR + /* AO_t not defined. */ +# define AO_t GC_word +#endif +#ifndef AO_HAVE_load_acquire + static AO_t AO_load_acquire(const volatile AO_t *addr) + { + AO_t result; + + FINALIZER_LOCK(); + result = *addr; + FINALIZER_UNLOCK(); + return result; + } +#endif +#ifndef AO_HAVE_store_release + /* Not a macro as new_val argument should be evaluated before the lock. */ + static void AO_store_release(volatile AO_t *addr, AO_t new_val) + { + FINALIZER_LOCK(); + *addr = new_val; + FINALIZER_UNLOCK(); + } +#endif +#ifndef AO_HAVE_fetch_and_add1 +# define AO_fetch_and_add1(p) ((*(p))++) + /* This is used only to update counters. */ +#endif + +/* Allocation Statistics. Synchronization is not strictly necessary. */ +volatile AO_t stubborn_count = 0; +volatile AO_t uncollectable_count = 0; +volatile AO_t collectable_count = 0; +volatile AO_t atomic_count = 0; +volatile AO_t realloc_count = 0; + +volatile AO_t extra_count = 0; /* Amount of space wasted in cons node; */ + /* also used in gcj_cons, mktree and */ + /* chktree (for other purposes). */ #if defined(GC_AMIGA_FASTALLOC) && defined(AMIGA) void GC_amiga_free_all_mem(void); void Amiga_Fail(void){GC_amiga_free_all_mem();abort();} -# define FAIL (void)Amiga_Fail() +# define FAIL Amiga_Fail() void *GC_amiga_gctest_malloc_explicitly_typed(size_t lb, GC_descr d){ void *ret=GC_malloc_explicitly_typed(lb,d); if(ret==NULL){ @@ -188,7 +252,7 @@ int realloc_count = 0; #else /* !AMIGA_FASTALLOC */ # if defined(PCR) || defined(LINT2) -# define FAIL (void)abort() +# define FAIL abort() # else # define FAIL ABORT("Test failed") # endif @@ -218,9 +282,6 @@ typedef struct SEXPR * sexpr; # define cdr(x) ((x) -> sexpr_cdr) # define is_nil(x) ((x) == nil) - -int extra_count = 0; /* Amount of space wasted in cons node */ - /* Silly implementation of Lisp cons. Intentionally wastes lots of space */ /* to test collector. */ # ifdef VERY_SMALL_CONFIG @@ -230,11 +291,11 @@ sexpr cons (sexpr x, sexpr y) { sexpr r; int *p; - int my_extra = extra_count; + unsigned my_extra = (unsigned)AO_fetch_and_add1(&extra_count) % 5000; - stubborn_count++; r = (sexpr) GC_MALLOC_STUBBORN(sizeof(struct SEXPR) + my_extra); CHECK_OUT_OF_MEMORY(r); + AO_fetch_and_add1(&stubborn_count); for (p = (int *)r; (word)p < (word)r + my_extra + sizeof(struct SEXPR); p++) { if (*p) { @@ -249,20 +310,17 @@ sexpr cons (sexpr x, sexpr y) # endif r -> sexpr_car = x; r -> sexpr_cdr = y; - my_extra++; - if ( my_extra >= 5000 ) { - extra_count = 0; - } else { - extra_count = my_extra; - } GC_END_STUBBORN_CHANGE(r); - return(r); + GC_reachable_here(x); + GC_reachable_here(y); + return r; } # endif +#include "gc_mark.h" + #ifdef GC_GCJ_SUPPORT -#include "gc_mark.h" #include "gc_gcj.h" /* The following struct emulates the vtable in gcj. */ @@ -304,46 +362,51 @@ struct GC_ms_entry * fake_gcj_mark_proc(word * addr, sexpr small_cons (sexpr x, sexpr y) { - sexpr r; + sexpr r = (sexpr)GC_MALLOC(sizeof(struct SEXPR)); - collectable_count++; - r = (sexpr) GC_MALLOC(sizeof(struct SEXPR)); CHECK_OUT_OF_MEMORY(r); + AO_fetch_and_add1(&collectable_count); r -> sexpr_car = x; r -> sexpr_cdr = y; - return(r); + GC_END_STUBBORN_CHANGE(r); + GC_reachable_here(x); + GC_reachable_here(y); + return r; } sexpr small_cons_uncollectable (sexpr x, sexpr y) { - sexpr r; + sexpr r = (sexpr)GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR)); - uncollectable_count++; - r = (sexpr) GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR)); CHECK_OUT_OF_MEMORY(r); + AO_fetch_and_add1(&uncollectable_count); r -> sexpr_car = x; r -> sexpr_cdr = (sexpr)(~(GC_word)y); - return(r); + GC_END_STUBBORN_CHANGE(r); + GC_reachable_here(x); + return r; } #ifdef GC_GCJ_SUPPORT - - -sexpr gcj_cons(sexpr x, sexpr y) -{ - GC_word * r; + sexpr gcj_cons(sexpr x, sexpr y) + { sexpr result; + GC_word * r = (GC_word *)GC_GCJ_MALLOC( + sizeof(struct SEXPR) + sizeof(struct fake_vtable*), + (AO_fetch_and_add1(&extra_count) & 1) != 0 + ? &gcj_class_struct1 + : &gcj_class_struct2); - r = (GC_word *) GC_GCJ_MALLOC(sizeof(struct SEXPR) - + sizeof(struct fake_vtable*), - &gcj_class_struct2); CHECK_OUT_OF_MEMORY(r); result = (sexpr)(r + 1); result -> sexpr_car = x; result -> sexpr_cdr = y; - return(result); -} -#endif + GC_END_STUBBORN_CHANGE(r); + GC_reachable_here(x); + GC_reachable_here(y); + return result; + } +#endif /* GC_GCJ_SUPPORT */ /* Return reverse(x) concatenated with y */ sexpr reverse1(sexpr x, sexpr y) @@ -358,7 +421,7 @@ sexpr reverse1(sexpr x, sexpr y) sexpr reverse(sexpr x) { # ifdef TEST_WITH_SYSTEM_MALLOC - malloc(100000); + GC_noop1(GC_HIDE_POINTER(malloc(100000))); # endif return( reverse1(x, nil) ); } @@ -412,6 +475,10 @@ sexpr uncollectable_ints(int low, int up) void check_ints(sexpr list, int low, int up) { + if (is_nil(list)) { + GC_printf("list is nil\n"); + FAIL; + } if (SEXPR_TO_INT(car(car(list))) != low) { GC_printf( "List reversal produced incorrect list - collector is broken\n"); @@ -505,18 +572,66 @@ void check_marks_int_list(sexpr x) check_ints(reverse(reverse(ints(1, TINY_REVERSE_UPPER_VALUE))), 1, TINY_REVERSE_UPPER_VALUE); } +# if defined(GC_ENABLE_SUSPEND_THREAD) + /* Force collection from a thread. */ + GC_gcollect(); +# endif return 0; } # if defined(GC_PTHREADS) +# if defined(GC_ENABLE_SUSPEND_THREAD) +# include "javaxfc.h" +# endif + void fork_a_thread(void) { pthread_t t; int code; - if ((code = pthread_create(&t, 0, tiny_reverse_test, 0)) != 0) { +# ifdef DEFAULT_STACK_MAYBE_SMALL + pthread_attr_t attr; + + code = pthread_attr_init(&attr); + if (code != 0) { + GC_printf("pthread_attr_init failed, error=%d\n", code); + FAIL; + } + code = pthread_attr_setstacksize(&attr, MIN_STACK_SIZE); + if (code != 0) { + GC_printf("pthread_attr_setstacksize(MIN_STACK_SIZE) failed," + " error=%d\n", code); + FAIL; + } + code = pthread_create(&t, &attr, tiny_reverse_test, 0); + (void)pthread_attr_destroy(&attr); +# else + code = pthread_create(&t, NULL, tiny_reverse_test, 0); +# endif + if (code != 0) { GC_printf("Small thread creation failed %d\n", code); FAIL; } +# if defined(GC_ENABLE_SUSPEND_THREAD) && !defined(GC_DARWIN_THREADS) \ + && !defined(GC_OPENBSD_UTHREADS) && !defined(GC_WIN32_THREADS) \ + && !defined(NACL) && !defined(GC_OSF1_THREADS) + if (GC_is_thread_suspended(t)) { + GC_printf("Running thread should be not suspended\n"); + FAIL; + } + /* Thread could be running or already terminated (but not joined). */ + GC_suspend_thread(t); + if (!GC_is_thread_suspended(t)) { + GC_printf("Thread expected to be suspended\n"); + FAIL; + } + GC_suspend_thread(t); /* should be no-op */ + GC_resume_thread(t); + if (GC_is_thread_suspended(t)) { + GC_printf("Resumed thread should be not suspended\n"); + FAIL; + } + GC_resume_thread(t); /* should be no-op */ +# endif if ((code = pthread_join(t, 0)) != 0) { GC_printf("Small thread join failed %d\n", code); FAIL; @@ -568,11 +683,12 @@ void test_generic_malloc_or_special(void *p) { } /* Try to force a to be strangely aligned */ -struct { +volatile struct { char dummy; - sexpr aa; + AO_t aa; } A; -#define a A.aa +#define a_set(p) AO_store_release(&A.aa, (AO_t)(p)) +#define a_get() (sexpr)AO_load_acquire(&A.aa) /* * Repeatedly reverse lists built out of very different sized cons cells. @@ -586,14 +702,16 @@ void *GC_CALLBACK reverse_test_inner(void *data) sexpr d; sexpr e; sexpr *f, *g, *h; + sexpr tmp; if (data == 0) { /* This stack frame is not guaranteed to be scanned. */ return GC_call_with_gc_active(reverse_test_inner, (void*)(word)1); } -# if /*defined(MSWIN32) ||*/ defined(MACOS) - /* Win32S only allows 128K stacks */ +# if defined(MACOS) \ + || (defined(UNIX_LIKE) && defined(NO_GETCONTEXT)) /* e.g. musl */ + /* Assume 128K stacks at least. */ # define BIG 1000 # elif defined(PCR) /* PCR default stack is 100K. Stack frames are up to 120 bytes. */ @@ -610,39 +728,54 @@ void *GC_CALLBACK reverse_test_inner(void *data) # define BIG 4500 # endif - A.dummy = 17; - a = ints(1, 49); + a_set(ints(1, 49)); b = ints(1, 50); c = ints(1, BIG); d = uncollectable_ints(1, 100); test_generic_malloc_or_special(d); e = uncollectable_ints(1, 1); /* Check that realloc updates object descriptors correctly */ - collectable_count++; + AO_fetch_and_add1(&collectable_count); f = (sexpr *)GC_MALLOC(4 * sizeof(sexpr)); - realloc_count++; f = (sexpr *)GC_REALLOC((void *)f, 6 * sizeof(sexpr)); CHECK_OUT_OF_MEMORY(f); - f[5] = ints(1,17); - collectable_count++; + AO_fetch_and_add1(&realloc_count); + tmp = ints(1,17); + f[5] = tmp; + GC_END_STUBBORN_CHANGE(f + 5); + GC_reachable_here(tmp); + AO_fetch_and_add1(&collectable_count); g = (sexpr *)GC_MALLOC(513 * sizeof(sexpr)); test_generic_malloc_or_special(g); - realloc_count++; g = (sexpr *)GC_REALLOC((void *)g, 800 * sizeof(sexpr)); CHECK_OUT_OF_MEMORY(g); - g[799] = ints(1,18); - collectable_count++; + AO_fetch_and_add1(&realloc_count); + tmp = ints(1,18); + g[799] = tmp; + GC_END_STUBBORN_CHANGE(g + 799); + GC_reachable_here(tmp); + AO_fetch_and_add1(&collectable_count); h = (sexpr *)GC_MALLOC(1025 * sizeof(sexpr)); - realloc_count++; h = (sexpr *)GC_REALLOC((void *)h, 2000 * sizeof(sexpr)); CHECK_OUT_OF_MEMORY(h); + AO_fetch_and_add1(&realloc_count); # ifdef GC_GCJ_SUPPORT - h[1999] = gcj_ints(1,200); - for (i = 0; i < 51; ++i) - h[1999] = gcj_reverse(h[1999]); + tmp = gcj_ints(1,200); + h[1999] = tmp; + GC_END_STUBBORN_CHANGE(h + 1999); + GC_reachable_here(tmp); + for (i = 0; i < 51; ++i) { + tmp = gcj_reverse(h[1999]); + h[1999] = tmp; + GC_END_STUBBORN_CHANGE(h + 1999); + GC_reachable_here(tmp); + } /* Leave it as the reversed list for now. */ # else - h[1999] = ints(1,200); + tmp = ints(1,200); + h[1999] = tmp; + GC_END_STUBBORN_CHANGE(h + 1999); + GC_reachable_here(tmp); # endif /* Try to force some collections and reuse of small list elements */ for (i = 0; i < 10; i++) { @@ -655,31 +788,31 @@ void *GC_CALLBACK reverse_test_inner(void *data) GC_FREE((void *)e); check_ints(b,1,50); - check_ints(a,1,49); + check_ints(a_get(),1,49); for (i = 0; i < 50; i++) { check_ints(b,1,50); b = reverse(reverse(b)); } check_ints(b,1,50); - check_ints(a,1,49); + check_ints(a_get(),1,49); for (i = 0; i < 60; i++) { -# if defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) +# if (defined(GC_PTHREADS) || defined(GC_WIN32_THREADS)) \ + && (NTHREADS > 0) if (i % 10 == 0) fork_a_thread(); # endif - /* This maintains the invariant that a always points to a list of */ - /* 49 integers. Thus this is thread safe without locks, */ - /* assuming atomic pointer assignments. */ - a = reverse(reverse(a)); + /* This maintains the invariant that a always points to a list */ + /* of 49 integers. Thus, this is thread safe without locks, */ + /* assuming acquire/release barriers in a_get/set() and atomic */ + /* pointer assignments (otherwise, e.g., check_ints() may see */ + /* an uninitialized object returned by GC_MALLOC_STUBBORN). */ + a_set(reverse(reverse(a_get()))); # if !defined(AT_END) && !defined(THREADS) /* This is not thread safe, since realloc explicitly deallocates */ - if (i & 1) { - a = (sexpr)GC_REALLOC((void *)a, 500); - } else { - a = (sexpr)GC_REALLOC((void *)a, 8200); - } + a_set(GC_REALLOC(a_get(), (i & 1) != 0 ? 500 : 8200)); + AO_fetch_and_add1(&realloc_count); # endif } - check_ints(a,1,49); + check_ints(a_get(),1,49); check_ints(b,1,50); /* Restore c and d values. */ @@ -691,11 +824,14 @@ void *GC_CALLBACK reverse_test_inner(void *data) check_ints(f[5], 1,17); check_ints(g[799], 1,18); # ifdef GC_GCJ_SUPPORT - h[1999] = gcj_reverse(h[1999]); + tmp = gcj_reverse(h[1999]); + h[1999] = tmp; + GC_END_STUBBORN_CHANGE(h + 1999); + GC_reachable_here(tmp); # endif check_ints(h[1999], 1,200); # ifndef THREADS - a = 0; + a_set(NULL); # endif *(sexpr volatile *)&b = 0; *(sexpr volatile *)&c = 0; @@ -708,8 +844,6 @@ void reverse_test(void) (void)GC_do_blocking(reverse_test_inner, 0); } -#undef a - /* * The rest of this builds balanced binary trees, checks that they don't * disappear, and tests finalization. @@ -722,45 +856,28 @@ typedef struct treenode { int finalizable_count = 0; int finalized_count = 0; -volatile int dropped_something = 0; +int dropped_something = 0; void GC_CALLBACK finalizer(void * obj, void * client_data) { tn * t = (tn *)obj; -# ifdef PCR - PCR_ThCrSec_EnterSys(); -# endif -# if defined(GC_PTHREADS) - static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&incr_lock); -# elif defined(GC_WIN32_THREADS) - EnterCriticalSection(&incr_cs); -# endif + FINALIZER_LOCK(); if ((int)(GC_word)client_data != t -> level) { GC_printf("Wrong finalization data - collector is broken\n"); FAIL; } finalized_count++; t -> level = -1; /* detect duplicate finalization immediately */ -# ifdef PCR - PCR_ThCrSec_ExitSys(); -# endif -# if defined(GC_PTHREADS) - pthread_mutex_unlock(&incr_lock); -# elif defined(GC_WIN32_THREADS) - LeaveCriticalSection(&incr_cs); -# endif + FINALIZER_UNLOCK(); } -size_t counter = 0; - -# define MAX_FINALIZED (NTHREADS*4000) +# define MAX_FINALIZED ((NTHREADS+1)*4000) # if !defined(MACOS) GC_FAR GC_word live_indicators[MAX_FINALIZED] = {0}; # ifndef GC_LONG_REFS_NOT_NEEDED - GC_FAR void *live_long_refs[MAX_FINALIZED] = { NULL }; + GC_FAR void *live_long_refs[MAX_FINALIZED] = { NULL }; # endif #else /* Too big for THINK_C. have to allocate it dynamically. */ @@ -775,8 +892,9 @@ int live_indicators_count = 0; tn * mktree(int n) { tn * result = (tn *)GC_MALLOC(sizeof(tn)); + tn * left, * right; - collectable_count++; + AO_fetch_and_add1(&collectable_count); # if defined(MACOS) /* get around static data limitations. */ if (!live_indicators) { @@ -788,49 +906,40 @@ tn * mktree(int n) if (n == 0) return(0); CHECK_OUT_OF_MEMORY(result); result -> level = n; - result -> lchild = mktree(n-1); - result -> rchild = mktree(n-1); - if (counter++ % 17 == 0 && n >= 2) { - tn * tmp; + result -> lchild = left = mktree(n - 1); + result -> rchild = right = mktree(n - 1); + if (AO_fetch_and_add1(&extra_count) % 17 == 0 && n >= 2) { + tn * tmp, * right_left; - CHECK_OUT_OF_MEMORY(result->lchild); - tmp = result -> lchild -> rchild; - CHECK_OUT_OF_MEMORY(result->rchild); - result -> lchild -> rchild = result -> rchild -> lchild; - result -> rchild -> lchild = tmp; + CHECK_OUT_OF_MEMORY(left); + tmp = left -> rchild; + CHECK_OUT_OF_MEMORY(right); + right_left = right -> lchild; + left -> rchild = right_left; + right -> lchild = tmp; + GC_END_STUBBORN_CHANGE(left); + GC_reachable_here(right_left); + GC_END_STUBBORN_CHANGE(right); + GC_reachable_here(tmp); } - if (counter++ % 119 == 0) { + if (AO_fetch_and_add1(&extra_count) % 119 == 0) { # ifndef GC_NO_FINALIZATION int my_index; void *new_link; # endif { -# ifdef PCR - PCR_ThCrSec_EnterSys(); -# endif -# if defined(GC_PTHREADS) - static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_lock(&incr_lock); -# elif defined(GC_WIN32_THREADS) - EnterCriticalSection(&incr_cs); -# endif + FINALIZER_LOCK(); /* Losing a count here causes erroneous report of failure. */ finalizable_count++; # ifndef GC_NO_FINALIZATION my_index = live_indicators_count++; # endif -# ifdef PCR - PCR_ThCrSec_ExitSys(); -# endif -# if defined(GC_PTHREADS) - pthread_mutex_unlock(&incr_lock); -# elif defined(GC_WIN32_THREADS) - LeaveCriticalSection(&incr_cs); -# endif + FINALIZER_UNLOCK(); } -# ifndef GC_NO_FINALIZATION +# ifndef GC_NO_FINALIZATION + if (!GC_get_find_leak()) { GC_REGISTER_FINALIZER((void *)result, finalizer, (void *)(GC_word)n, (GC_finalization_proc *)0, (void * *)0); if (my_index >= MAX_FINALIZED) { @@ -898,31 +1007,36 @@ tn * mktree(int n) FAIL; } # endif -# endif - GC_reachable_here(result); + } +# endif + GC_reachable_here(result); } + GC_END_STUBBORN_CHANGE(result); + GC_reachable_here(left); + GC_reachable_here(right); return(result); } void chktree(tn *t, int n) { - if (n == 0 && t != 0) { + if (0 == n) { + if (NULL == t) /* is a leaf? */ + return; GC_printf("Clobbered a leaf - collector is broken\n"); FAIL; } - if (n == 0) return; if (t -> level != n) { GC_printf("Lost a node at level %d - collector is broken\n", n); FAIL; } - if (counter++ % 373 == 0) { - collectable_count++; - (void) GC_MALLOC(counter%5001); + if (AO_fetch_and_add1(&extra_count) % 373 == 0) { + (void)GC_MALLOC((unsigned)AO_fetch_and_add1(&extra_count) % 5001); + AO_fetch_and_add1(&collectable_count); } chktree(t -> lchild, n-1); - if (counter++ % 73 == 0) { - collectable_count++; - (void) GC_MALLOC(counter%373); + if (AO_fetch_and_add1(&extra_count) % 73 == 0) { + (void)GC_MALLOC((unsigned)AO_fetch_and_add1(&extra_count) % 373); + AO_fetch_and_add1(&collectable_count); } chktree(t -> rchild, n-1); } @@ -934,17 +1048,18 @@ pthread_key_t fl_key; void * alloc8bytes(void) { # if defined(SMALL_CONFIG) || defined(GC_DEBUG) - collectable_count++; + AO_fetch_and_add1(&collectable_count); return(GC_MALLOC(8)); # else void ** my_free_list_ptr; void * my_free_list; + void * next; my_free_list_ptr = (void **)pthread_getspecific(fl_key); if (my_free_list_ptr == 0) { - uncollectable_count++; my_free_list_ptr = GC_NEW_UNCOLLECTABLE(void *); CHECK_OUT_OF_MEMORY(my_free_list_ptr); + AO_fetch_and_add1(&uncollectable_count); if (pthread_setspecific(fl_key, my_free_list_ptr) != 0) { GC_printf("pthread_setspecific failed\n"); FAIL; @@ -955,9 +1070,12 @@ void * alloc8bytes(void) my_free_list = GC_malloc_many(8); CHECK_OUT_OF_MEMORY(my_free_list); } - *my_free_list_ptr = GC_NEXT(my_free_list); + next = GC_NEXT(my_free_list); + *my_free_list_ptr = next; GC_NEXT(my_free_list) = 0; - collectable_count++; + GC_END_STUBBORN_CHANGE(my_free_list_ptr); + GC_reachable_here(next); + AO_fetch_and_add1(&collectable_count); return(my_free_list); # endif } @@ -966,16 +1084,33 @@ void * alloc8bytes(void) # define alloc8bytes() GC_MALLOC_ATOMIC(8) #endif +#include "gc_inline.h" + +void test_tinyfl(void) +{ + void *results[3]; + void *tfls[3][GC_TINY_FREELISTS]; + +# ifndef DONT_ADD_BYTE_AT_END + if (GC_get_all_interior_pointers()) return; /* skip */ +# endif + BZERO(tfls, sizeof(tfls)); + /* TODO: Improve testing of FAST_MALLOC functionality. */ + GC_MALLOC_WORDS(results[0], 11, tfls[0]); + GC_MALLOC_ATOMIC_WORDS(results[1], 20, tfls[1]); + GC_CONS(results[2], results[0], results[1], tfls[2]); +} + void alloc_small(int n) { int i; for (i = 0; i < n; i += 8) { - atomic_count++; if (alloc8bytes() == 0) { GC_printf("Out of memory\n"); FAIL; } + AO_fetch_and_add1(&atomic_count); } } @@ -1002,12 +1137,14 @@ void tree_test(void) alloc_small(5000000); # endif chktree(root, TREE_HEIGHT); - if (finalized_count && ! dropped_something) { + FINALIZER_LOCK(); + if (finalized_count && !dropped_something) { GC_printf("Premature finalization - collector is broken\n"); FAIL; } dropped_something = 1; - GC_noop1((word)root); /* Root needs to remain live until */ + FINALIZER_UNLOCK(); + GC_reachable_here(root); /* Root needs to remain live until */ /* dropped_something is set. */ root = mktree(TREE_HEIGHT); chktree(root, TREE_HEIGHT); @@ -1022,69 +1159,90 @@ void tree_test(void) unsigned n_tests = 0; -const GC_word bm_huge[10] = { +const GC_word bm_huge[320 / CPP_WORDSZ] = { +# if CPP_WORDSZ == 32 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, - 0xffffffff, - 0xffffffff, - 0xffffffff, - 0x00ffffff, +# endif + (GC_word)((GC_signed_word)-1), + (GC_word)((GC_signed_word)-1), + (GC_word)((GC_signed_word)-1), + (GC_word)((GC_signed_word)-1), + ((GC_word)((GC_signed_word)-1)) >> 8 /* highest byte is zero */ }; /* A very simple test of explicitly typed allocation */ void typed_test(void) { GC_word * old, * new; - GC_word bm3 = 0x3; - GC_word bm2 = 0x2; - GC_word bm_large = 0xf7ff7fff; - GC_descr d1 = GC_make_descriptor(&bm3, 2); - GC_descr d2 = GC_make_descriptor(&bm2, 2); - GC_descr d3 = GC_make_descriptor(&bm_large, 32); + GC_word bm3[1] = {0}; + GC_word bm2[1] = {0}; + GC_word bm_large[1] = { 0xf7ff7fff }; + GC_descr d1; + GC_descr d2; + GC_descr d3 = GC_make_descriptor(bm_large, 32); GC_descr d4 = GC_make_descriptor(bm_huge, 320); - GC_word * x = (GC_word *)GC_malloc_explicitly_typed(2000, d4); + GC_word * x = (GC_word *)GC_malloc_explicitly_typed( + 320 * sizeof(GC_word) + 123, d4); int i; + AO_fetch_and_add1(&collectable_count); # ifndef LINT - (void)GC_make_descriptor(&bm_large, 32); + (void)GC_make_descriptor(bm_large, 32); # endif - collectable_count++; + if (GC_get_bit(bm_huge, 32) == 0 || GC_get_bit(bm_huge, 311) == 0 + || GC_get_bit(bm_huge, 319) != 0) { + GC_printf("Bad GC_get_bit() or bm_huge initialization\n"); + FAIL; + } + GC_set_bit(bm3, 0); + GC_set_bit(bm3, 1); + d1 = GC_make_descriptor(bm3, 2); + GC_set_bit(bm2, 1); + d2 = GC_make_descriptor(bm2, 2); old = 0; for (i = 0; i < 4000; i++) { - collectable_count++; new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d1); CHECK_OUT_OF_MEMORY(new); + AO_fetch_and_add1(&collectable_count); if (0 != new[0] || 0 != new[1]) { GC_printf("Bad initialization by GC_malloc_explicitly_typed\n"); FAIL; } new[0] = 17; new[1] = (GC_word)old; + GC_END_STUBBORN_CHANGE(new); + GC_reachable_here(old); old = new; - collectable_count++; + AO_fetch_and_add1(&collectable_count); new = (GC_word *) GC_malloc_explicitly_typed(4 * sizeof(GC_word), d2); CHECK_OUT_OF_MEMORY(new); new[0] = 17; new[1] = (GC_word)old; + GC_END_STUBBORN_CHANGE(new); + GC_reachable_here(old); old = new; - collectable_count++; + AO_fetch_and_add1(&collectable_count); new = (GC_word *) GC_malloc_explicitly_typed(33 * sizeof(GC_word), d3); CHECK_OUT_OF_MEMORY(new); new[0] = 17; new[1] = (GC_word)old; + GC_END_STUBBORN_CHANGE(new); + GC_reachable_here(old); old = new; - collectable_count++; + AO_fetch_and_add1(&collectable_count); new = (GC_word *) GC_calloc_explicitly_typed(4, 2 * sizeof(GC_word), d1); CHECK_OUT_OF_MEMORY(new); new[0] = 17; new[1] = (GC_word)old; + GC_END_STUBBORN_CHANGE(new); + GC_reachable_here(old); old = new; - collectable_count++; + AO_fetch_and_add1(&collectable_count); if (i & 0xff) { new = (GC_word *) GC_calloc_explicitly_typed(7, 3 * sizeof(GC_word), d2); @@ -1100,11 +1258,13 @@ void typed_test(void) CHECK_OUT_OF_MEMORY(new); new[0] = 17; new[1] = (GC_word)old; + GC_END_STUBBORN_CHANGE(new); + GC_reachable_here(old); old = new; } for (i = 0; i < 20000; i++) { if (new[0] != 17) { - GC_printf("typed alloc failed at %lu\n", (unsigned long)i); + GC_printf("Typed alloc failed at %d\n", i); FAIL; } new[0] = 0; @@ -1115,12 +1275,30 @@ void typed_test(void) GC_noop1((word)x); } -int fail_count = 0; +#ifdef DBG_HDRS_ALL +# define set_print_procs() (void)(A.dummy = 17) +#else + int fail_count = 0; -void GC_CALLBACK fail_proc1(void *x GC_ATTR_UNUSED) -{ + void GC_CALLBACK fail_proc1(void *x GC_ATTR_UNUSED) + { fail_count++; -} + } + + void set_print_procs(void) + { + /* Set these global variables just once to avoid TSan false positives. */ + A.dummy = 17; + GC_is_valid_displacement_print_proc = fail_proc1; + GC_is_visible_print_proc = fail_proc1; + } + +# ifdef THREADS +# define TEST_FAIL_COUNT(n) 1 +# else +# define TEST_FAIL_COUNT(n) (fail_count >= (n)) +# endif +#endif /* !DBG_HDRS_ALL */ static void uniq(void *p, ...) { va_list a; @@ -1141,12 +1319,6 @@ static void uniq(void *p, ...) { } } -#ifdef THREADS -# define TEST_FAIL_COUNT(n) 1 -#else -# define TEST_FAIL_COUNT(n) (fail_count >= (n)) -#endif - void * GC_CALLBACK inc_int_counter(void *pcounter) { ++(*(int *)pcounter); @@ -1163,47 +1335,45 @@ void run_one_test(void) # else char *y = (char *)(GC_word)fail_proc1; # endif - CLOCK_TYPE typed_time; # endif CLOCK_TYPE start_time; CLOCK_TYPE reverse_time; - CLOCK_TYPE tree_time; unsigned long time_diff; - -# ifdef FIND_LEAK - GC_printf( - "This test program is not designed for leak detection mode\n"); - GC_printf("Expect lots of problems\n"); +# ifndef NO_TEST_HANDLE_FORK + pid_t pid; + int wstatus; # endif + GC_FREE(0); # ifdef THREADS - if (!GC_thread_is_registered()) { + if (!GC_thread_is_registered() && GC_is_init_called()) { GC_printf("Current thread is not registered with GC\n"); FAIL; } # endif + test_tinyfl(); # ifndef DBG_HDRS_ALL - collectable_count += 3; + AO_fetch_and_add1(&collectable_count); /* 1 */ + AO_fetch_and_add1(&collectable_count); /* 2 */ + AO_fetch_and_add1(&collectable_count); /* 3 */ if ((GC_size(GC_malloc(7)) != 8 && GC_size(GC_malloc(7)) != MIN_WORDS * sizeof(GC_word)) || GC_size(GC_malloc(15)) != 16) { GC_printf("GC_size produced unexpected results\n"); FAIL; } - collectable_count += 1; + AO_fetch_and_add1(&collectable_count); if (GC_size(GC_malloc(0)) != MIN_WORDS * sizeof(GC_word)) { GC_printf("GC_malloc(0) failed: GC_size returns %lu\n", (unsigned long)GC_size(GC_malloc(0))); FAIL; } - collectable_count += 1; + AO_fetch_and_add1(&uncollectable_count); if (GC_size(GC_malloc_uncollectable(0)) != MIN_WORDS * sizeof(GC_word)) { GC_printf("GC_malloc_uncollectable(0) failed\n"); FAIL; } - GC_is_valid_displacement_print_proc = fail_proc1; - GC_is_visible_print_proc = fail_proc1; - collectable_count += 1; + AO_fetch_and_add1(&collectable_count); x = GC_malloc(16); if (GC_base(GC_PTR_ADD(x, 13)) != x) { GC_printf("GC_base(heap ptr) produced incorrect result\n"); @@ -1243,7 +1413,10 @@ void run_one_test(void) FAIL; } z = GC_malloc(8); + CHECK_OUT_OF_MEMORY(z); + AO_fetch_and_add1(&collectable_count); GC_PTR_STORE(z, x); + GC_end_stubborn_change(z); if (*z != x) { GC_printf("GC_PTR_STORE failed: %p != %p\n", (void *)(*z), (void *)x); FAIL; @@ -1268,6 +1441,7 @@ void run_one_test(void) size_t i; (void)GC_malloc(17); + AO_fetch_and_add1(&collectable_count); for (i = sizeof(GC_word); i < 512; i *= 2) { GC_word result = (GC_word) GC_memalign(i, 17); if (result % i != 0 || result == 0 || *(int *)result != 0) FAIL; @@ -1287,13 +1461,14 @@ void run_one_test(void) # endif # endif /* DBG_HDRS_ALL */ /* Test floating point alignment */ - collectable_count += 2; { double *dp = GC_MALLOC(sizeof(double)); CHECK_OUT_OF_MEMORY(dp); + AO_fetch_and_add1(&collectable_count); *dp = 1.0; dp = GC_MALLOC(sizeof(double)); CHECK_OUT_OF_MEMORY(dp); + AO_fetch_and_add1(&collectable_count); *dp = 1.0; } /* Test size 0 allocation a bit more */ @@ -1301,10 +1476,13 @@ void run_one_test(void) size_t i; for (i = 0; i < 10000; ++i) { (void)GC_MALLOC(0); + AO_fetch_and_add1(&collectable_count); GC_FREE(GC_MALLOC(0)); (void)GC_MALLOC_ATOMIC(0); + AO_fetch_and_add1(&atomic_count); GC_FREE(GC_MALLOC_ATOMIC(0)); test_generic_malloc_or_special(GC_malloc_atomic(1)); + AO_fetch_and_add1(&atomic_count); } } # ifdef GC_GCJ_SUPPORT @@ -1331,10 +1509,23 @@ void run_one_test(void) GC_free(GC_malloc_atomic(0)); # ifndef NO_TEST_HANDLE_FORK GC_atfork_prepare(); - if (fork() != 0) { + pid = fork(); + if (pid != 0) { GC_atfork_parent(); + if (pid == -1) { + GC_printf("Process fork failed\n"); + FAIL; + } if (print_stats) - GC_log_printf("Forked child process (or failed)\n"); + GC_log_printf("Forked child process\n"); + if (waitpid(pid, &wstatus, 0) == -1) { + GC_printf("Wait for child process failed\n"); + FAIL; + } + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) { + GC_printf("Child process failed, status= 0x%x\n", wstatus); + FAIL; + } } else { GC_atfork_child(); if (print_stats) @@ -1367,6 +1558,8 @@ void run_one_test(void) # ifndef DBG_HDRS_ALL typed_test(); if (print_stats) { + CLOCK_TYPE typed_time; + GET_TIME(typed_time); time_diff = MS_TIME_DIFF(typed_time, start_time); GC_log_printf("-------------Finished typed_test at time %u (%p)\n", @@ -1375,6 +1568,8 @@ void run_one_test(void) # endif /* DBG_HDRS_ALL */ tree_test(); if (print_stats) { + CLOCK_TYPE tree_time; + GET_TIME(tree_time); time_diff = MS_TIME_DIFF(tree_time, start_time); GC_log_printf("-------------Finished tree_test at time %u (%p)\n", @@ -1396,6 +1591,32 @@ void run_one_test(void) GC_log_printf("Finished %p\n", (void *)&start_time); } +void GC_CALLBACK reachable_objs_counter(void *obj, size_t size, + void *pcounter) +{ + if (0 == size) { + GC_printf("Reachable object has zero size\n"); + FAIL; + } + if (GC_base(obj) != obj) { + GC_printf("Invalid reachable object base passed by enumerator: %p\n", + obj); + FAIL; + } + if (GC_size(obj) != size) { + GC_printf("Invalid reachable object size passed by enumerator: %lu\n", + (unsigned long)size); + FAIL; + } + (*(unsigned *)pcounter)++; +} + +void * GC_CALLBACK reachable_objs_count_enumerator(void *pcounter) +{ + GC_enumerate_reachable_objects_inner(reachable_objs_counter, pcounter); + return NULL; +} + #define NUMBER_ROUND_UP(v, bound) ((((v) + (bound) - 1) / (bound)) * (bound)) void check_heap_stats(void) @@ -1403,15 +1624,16 @@ void check_heap_stats(void) size_t max_heap_sz; int i; # ifndef GC_NO_FINALIZATION - int still_live; -# ifndef GC_LONG_REFS_NOT_NEEDED - int still_long_live = 0; -# endif # ifdef FINALIZE_ON_DEMAND int late_finalize_count = 0; # endif # endif + unsigned obj_count = 0; + if (!GC_is_init_called()) { + GC_printf("GC should be initialized!\n"); + FAIL; + } # ifdef VERY_SMALL_CONFIG /* The upper bounds are a guess, which has been empirically */ /* adjusted. On low end uniprocessors with incremental GC */ @@ -1435,9 +1657,15 @@ void check_heap_stats(void) # ifdef SAVE_CALL_CHAIN max_heap_sz *= 3; # ifdef SAVE_CALL_COUNT - max_heap_sz += max_heap_sz * SAVE_CALL_COUNT/4; + max_heap_sz += max_heap_sz * NFRAMES / 4; # endif # endif +# endif +# if defined(ADDRESS_SANITIZER) && !defined(__clang__) + max_heap_sz = max_heap_sz * 2 - max_heap_sz / 3; +# endif +# ifdef MEMORY_SANITIZER + max_heap_sz += max_heap_sz / 4; # endif max_heap_sz *= n_tests; # if defined(USE_MMAP) || defined(MSWIN32) @@ -1468,15 +1696,24 @@ void check_heap_stats(void) FAIL; } } + (void)GC_call_with_alloc_lock(reachable_objs_count_enumerator, + &obj_count); GC_printf("Completed %u tests\n", n_tests); - GC_printf("Allocated %d collectable objects\n", collectable_count); + GC_printf("Allocated %d collectable objects\n", (int)collectable_count); GC_printf("Allocated %d uncollectable objects\n", - uncollectable_count); - GC_printf("Allocated %d atomic objects\n", atomic_count); - GC_printf("Allocated %d stubborn objects\n", stubborn_count); + (int)uncollectable_count); + GC_printf("Allocated %d atomic objects\n", (int)atomic_count); + GC_printf("Allocated %d stubborn objects\n", (int)stubborn_count); + GC_printf("Reallocated %d objects\n", (int)realloc_count); GC_printf("Finalized %d/%d objects - ", finalized_count, finalizable_count); -# ifndef GC_NO_FINALIZATION +# ifndef GC_NO_FINALIZATION + if (!GC_get_find_leak()) { + int still_live = 0; +# ifndef GC_LONG_REFS_NOT_NEEDED + int still_long_live = 0; +# endif + # ifdef FINALIZE_ON_DEMAND if (finalized_count != late_finalize_count) { GC_printf("Demand finalization error\n"); @@ -1490,7 +1727,6 @@ void check_heap_stats(void) } else { GC_printf("finalization is probably ok\n"); } - still_live = 0; for (i = 0; i < MAX_FINALIZED; i++) { if (live_indicators[i] != 0) { still_live++; @@ -1516,12 +1752,15 @@ void check_heap_stats(void) GC_printf("%d 'long' links remain\n", still_long_live); } # endif -# endif + } +# endif GC_printf("Total number of bytes allocated is %lu\n", (unsigned long)GC_get_total_bytes()); + GC_printf("Total memory use by allocated blocks is %lu bytes\n", + (unsigned long)GC_get_memory_use()); GC_printf("Final heap size is %lu bytes\n", (unsigned long)GC_get_heap_size()); - if (GC_get_total_bytes() < n_tests * + if (GC_get_total_bytes() < (size_t)n_tests * # ifdef VERY_SMALL_CONFIG 2700000 # else @@ -1531,13 +1770,15 @@ void check_heap_stats(void) GC_printf("Incorrect execution - missed some allocations\n"); FAIL; } - if (GC_get_heap_size() + GC_get_unmapped_bytes() > max_heap_sz) { + if (GC_get_heap_size() + GC_get_unmapped_bytes() > max_heap_sz + && !GC_get_find_leak()) { GC_printf("Unexpected heap growth - collector may be broken" " (heapsize: %lu, expected: %lu)\n", (unsigned long)(GC_get_heap_size() + GC_get_unmapped_bytes()), (unsigned long)max_heap_sz); FAIL; } + GC_printf("Final number of reachable objects is %u\n", obj_count); # ifndef GC_GET_HEAP_USAGE_NOT_NEEDED /* Get global counters (just to check the functions work). */ @@ -1564,12 +1805,10 @@ void check_heap_stats(void) #if defined(MACOS) void SetMinimumStack(long minSize) { - long newApplLimit; - if (minSize > LMGetDefltStack()) { - newApplLimit = (long) GetApplLimit() - - (minSize - LMGetDefltStack()); + long newApplLimit = (long) GetApplLimit() + - (minSize - LMGetDefltStack()); SetApplLimit((Ptr) newApplLimit); MaxApplZone(); } @@ -1585,6 +1824,11 @@ void GC_CALLBACK warn_proc(char *msg, GC_word p) /*FAIL;*/ } +#if defined(CPPCHECK) +# include "javaxfc.h" /* for GC_finalize_all */ +# define UNTESTED(sym) GC_noop1((word)&sym) +#endif + #if defined(MSWINCE) && defined(UNDER_CE) # define WINMAIN_LPTSTR LPWSTR #else @@ -1593,7 +1837,8 @@ void GC_CALLBACK warn_proc(char *msg, GC_word p) #if !defined(PCR) && !defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) \ || defined(LINT) -#if defined(MSWIN32) && !defined(__MINGW32__) || defined(MSWINCE) +#if ((defined(MSWIN32) && !defined(__MINGW32__)) || defined(MSWINCE)) \ + && !defined(NO_WINMAIN_ENTRY) int APIENTRY WinMain(HINSTANCE instance GC_ATTR_UNUSED, HINSTANCE prev GC_ATTR_UNUSED, WINMAIN_LPTSTR cmd GC_ATTR_UNUSED, @@ -1612,6 +1857,12 @@ void GC_CALLBACK warn_proc(char *msg, GC_word p) int main(void) #endif { +# if defined(CPPCHECK) && !defined(NO_WINMAIN_ENTRY) \ + && ((defined(MSWIN32) && !defined(__MINGW32__)) || defined(MSWINCE)) + GC_noop1((GC_word)&WinMain); +# elif defined(CPPCHECK) && defined(RTEMS) + GC_noop1((GC_word)&Init); +# endif n_tests = 0; # if defined(MACOS) /* Make sure we have lots and lots of stack space. */ @@ -1621,27 +1872,163 @@ void GC_CALLBACK warn_proc(char *msg, GC_word p) # endif GC_COND_INIT(); GC_set_warn_proc(warn_proc); -# if (defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(GWW_VDB)) \ - && !defined(MAKE_BACK_GRAPH) && !defined(NO_INCREMENTAL) +# if !defined(GC_DISABLE_INCREMENTAL) && !defined(DEFAULT_VDB) \ + && !defined(MAKE_BACK_GRAPH) && !defined(NO_INCREMENTAL) \ + && !(defined(MPROTECT_VDB) && defined(USE_MUNMAP)) GC_enable_incremental(); GC_printf("Switched to incremental mode\n"); -# if defined(MPROTECT_VDB) - GC_printf("Emulating dirty bits with mprotect/signals\n"); -# else -# ifdef PROC_VDB - GC_printf("Reading dirty bits from /proc\n"); -# elif defined(GWW_VDB) - GC_printf("Using GetWriteWatch-based implementation\n"); -# else - GC_printf("Using DEFAULT_VDB dirty bit implementation\n"); +# ifdef PROC_VDB + GC_printf("Reading dirty bits from /proc\n"); +# elif defined(GWW_VDB) + GC_printf("Using GetWriteWatch-based implementation\n"); +# ifdef MPROTECT_VDB + GC_printf("Or emulating dirty bits with mprotect/signals\n"); # endif -# endif +# elif defined(MPROTECT_VDB) + GC_printf("Emulating dirty bits with mprotect/signals\n"); +# endif /* MPROTECT_VDB && !GWW_VDB */ # endif + set_print_procs(); run_one_test(); check_heap_stats(); # ifndef MSWINCE fflush(stdout); # endif +# if defined(CPPCHECK) + /* Entry points we should be testing, but aren't. */ +# ifndef GC_DEBUG + UNTESTED(GC_debug_generic_or_special_malloc); + UNTESTED(GC_debug_register_displacement); + UNTESTED(GC_post_incr); + UNTESTED(GC_pre_incr); +# ifdef GC_GCJ_SUPPORT + UNTESTED(GC_debug_gcj_malloc); +# endif +# endif +# ifdef AMIGA +# ifdef GC_AMIGA_FASTALLOC + UNTESTED(GC_amiga_get_mem); +# endif +# ifndef GC_AMIGA_ONLYFAST + UNTESTED(GC_amiga_set_toany); +# endif +# endif +# if defined(MACOS) && defined(USE_TEMPORARY_MEMORY) + UNTESTED(GC_MacTemporaryNewPtr); +# endif +# if !defined(_M_AMD64) && defined(_MSC_VER) + UNTESTED(GetFileLineFromStack); + UNTESTED(GetModuleNameFromStack); + UNTESTED(GetSymbolNameFromStack); +# endif + UNTESTED(GC_abort_on_oom); + UNTESTED(GC_get_bytes_since_gc); + UNTESTED(GC_get_dont_expand); + UNTESTED(GC_get_dont_precollect); + UNTESTED(GC_get_finalize_on_demand); + UNTESTED(GC_get_finalizer_notifier); + UNTESTED(GC_get_force_unmap_on_gcollect); + UNTESTED(GC_get_free_bytes); + UNTESTED(GC_get_free_space_divisor); + UNTESTED(GC_get_full_freq); + UNTESTED(GC_get_java_finalization); + UNTESTED(GC_get_max_retries); + UNTESTED(GC_get_no_dls); + UNTESTED(GC_get_non_gc_bytes); + UNTESTED(GC_get_on_collection_event); + UNTESTED(GC_get_on_heap_resize); + UNTESTED(GC_get_pages_executable); + UNTESTED(GC_get_push_other_roots); + UNTESTED(GC_get_start_callback); + UNTESTED(GC_get_stop_func); + UNTESTED(GC_get_time_limit); + UNTESTED(GC_get_warn_proc); + UNTESTED(GC_is_disabled); + UNTESTED(GC_set_dont_precollect); + UNTESTED(GC_set_finalize_on_demand); + UNTESTED(GC_set_finalizer_notifier); + UNTESTED(GC_set_free_space_divisor); + UNTESTED(GC_set_full_freq); + UNTESTED(GC_set_java_finalization); + UNTESTED(GC_set_max_retries); + UNTESTED(GC_set_no_dls); + UNTESTED(GC_set_non_gc_bytes); + UNTESTED(GC_set_on_collection_event); + UNTESTED(GC_set_on_heap_resize); + UNTESTED(GC_set_oom_fn); + UNTESTED(GC_set_pages_executable); + UNTESTED(GC_set_push_other_roots); + UNTESTED(GC_set_start_callback); + UNTESTED(GC_set_stop_func); + UNTESTED(GC_set_time_limit); + UNTESTED(GC_malloc_explicitly_typed_ignore_off_page); + UNTESTED(GC_debug_change_stubborn); + UNTESTED(GC_debug_strndup); + UNTESTED(GC_strndup); + UNTESTED(GC_posix_memalign); + UNTESTED(GC_new_free_list); + UNTESTED(GC_new_kind); + UNTESTED(GC_new_proc); + UNTESTED(GC_clear_roots); + UNTESTED(GC_exclude_static_roots); + UNTESTED(GC_expand_hp); + UNTESTED(GC_register_describe_type_fn); + UNTESTED(GC_register_has_static_roots_callback); +# if !defined(PCR) && !defined(SMALL_CONFIG) + UNTESTED(GC_get_abort_func); + UNTESTED(GC_set_abort_func); +# endif +# ifdef GC_GCJ_SUPPORT + UNTESTED(GC_gcj_malloc_ignore_off_page); +# endif +# ifndef NO_DEBUGGING + UNTESTED(GC_dump_regions); + UNTESTED(GC_is_tmp_root); + UNTESTED(GC_print_free_list); +# endif +# ifdef TRACE_BUF + UNTESTED(GC_print_trace); +# endif +# ifndef GC_NO_FINALIZATION + UNTESTED(GC_debug_register_finalizer_unreachable); + UNTESTED(GC_get_await_finalize_proc); + UNTESTED(GC_register_disappearing_link); + UNTESTED(GC_set_await_finalize_proc); + UNTESTED(GC_should_invoke_finalizers); +# ifndef JAVA_FINALIZATION_NOT_NEEDED + UNTESTED(GC_finalize_all); +# endif +# ifndef NO_DEBUGGING + UNTESTED(GC_dump_finalization); +# endif +# ifndef GC_TOGGLE_REFS_NOT_NEEDED + UNTESTED(GC_get_toggleref_func); + UNTESTED(GC_set_toggleref_func); + UNTESTED(GC_toggleref_add); +# endif +# endif +# if !defined(OS2) && !defined(MACOS) && !defined(GC_ANDROID_LOG) \ + && !defined(MSWIN32) && !defined(MSWINCE) + UNTESTED(GC_set_log_fd); +# endif +# ifndef REDIRECT_MALLOC_IN_HEADER +# ifdef REDIRECT_MALLOC +# ifndef strndup + UNTESTED(strndup); +# endif +# ifndef strdup + UNTESTED(strdup); +# endif +# endif +# ifdef REDIRECT_REALLOC + UNTESTED(realloc); +# endif +# endif /* !REDIRECT_MALLOC_IN_HEADER */ +# ifdef GC_REQUIRE_WCSDUP + UNTESTED(GC_wcsdup); + UNTESTED(GC_debug_wcsdup); +# endif +# endif # ifdef MSWIN32 GC_win32_free_heap(); # endif @@ -1736,10 +2123,14 @@ DWORD __stdcall thr_window(void * arg GC_ATTR_UNUSED) } #endif -int APIENTRY WinMain(HINSTANCE instance GC_ATTR_UNUSED, - HINSTANCE prev GC_ATTR_UNUSED, - WINMAIN_LPTSTR cmd GC_ATTR_UNUSED, - int n GC_ATTR_UNUSED) +#if !defined(NO_WINMAIN_ENTRY) + int APIENTRY WinMain(HINSTANCE instance GC_ATTR_UNUSED, + HINSTANCE prev GC_ATTR_UNUSED, + WINMAIN_LPTSTR cmd GC_ATTR_UNUSED, + int n GC_ATTR_UNUSED) +#else + int main(void) +#endif { # if NTHREADS > 0 HANDLE h[NTHREADS]; @@ -1749,6 +2140,10 @@ int APIENTRY WinMain(HINSTANCE instance GC_ATTR_UNUSED, HANDLE win_thr_h; # endif DWORD thread_id; + +# if defined(CPPCHECK) && !defined(NO_WINMAIN_ENTRY) + GC_noop1((GC_word)&WinMain); +# endif # if defined(GC_DLL) && !defined(GC_NO_THREADS_DISCOVERY) \ && !defined(MSWINCE) && !defined(THREAD_LOCAL_ALLOC) \ && !defined(PARALLEL_MARK) @@ -1777,6 +2172,7 @@ int APIENTRY WinMain(HINSTANCE instance GC_ATTR_UNUSED, FAIL; CloseHandle(win_created_h); # endif + set_print_procs(); # if NTHREADS > 0 for (i = 0; i < NTHREADS; i++) { h[i] = GC_CreateThread(NULL, 0, thr_run_one_test, 0, 0, &thread_id); @@ -1801,6 +2197,13 @@ int APIENTRY WinMain(HINSTANCE instance GC_ATTR_UNUSED, FAIL; # endif check_heap_stats(); +# if defined(CPPCHECK) && defined(GC_WIN32_THREADS) + UNTESTED(GC_ExitThread); +# if !defined(MSWINCE) && !defined(CYGWIN32) + UNTESTED(GC_beginthreadex); + UNTESTED(GC_endthreadex); +# endif +# endif return(0); } @@ -1814,9 +2217,15 @@ int test(void) PCR_Th_T * th2; int code; +# if defined(CPPCHECK) + GC_noop1((word)&PCR_GC_Run); + GC_noop1((word)&PCR_GC_Setup); + GC_noop1((word)&test); +# endif n_tests = 0; /* GC_enable_incremental(); */ GC_set_warn_proc(warn_proc); + set_print_procs(); th1 = PCR_Th_Fork(run_one_test, 0); th2 = PCR_Th_Fork(run_one_test, 0); run_one_test(); @@ -1846,10 +2255,12 @@ void * thr_run_one_test(void * arg GC_ATTR_UNUSED) int main(void) { - pthread_t th[NTHREADS]; +# if NTHREADS > 0 + pthread_t th[NTHREADS]; + int i; +# endif pthread_attr_t attr; int code; - int i; # ifdef GC_IRIX_THREADS /* Force a larger stack to be preallocated */ /* Since the initial can't always grow later. */ @@ -1880,49 +2291,77 @@ int main(void) } # if defined(GC_IRIX_THREADS) || defined(GC_FREEBSD_THREADS) \ || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS) \ - || defined(GC_OPENBSD_THREADS) + || defined(GC_OPENBSD_THREADS) || defined(DEFAULT_STACK_MAYBE_SMALL) \ + || defined(NO_GETCONTEXT) /* e.g. musl libc */ if ((code = pthread_attr_setstacksize(&attr, 1000 * 1024)) != 0) { GC_printf("pthread_attr_setstacksize failed, error=%d\n", code); FAIL; } # endif n_tests = 0; -# if (defined(MPROTECT_VDB)) && !defined(REDIRECT_MALLOC) \ +# if !defined(GC_DISABLE_INCREMENTAL) && !defined(DEFAULT_VDB) \ + && !defined(REDIRECT_MALLOC) \ && !defined(MAKE_BACK_GRAPH) && !defined(USE_PROC_FOR_LIBRARIES) \ - && !defined(NO_INCREMENTAL) + && !defined(NO_INCREMENTAL) && !defined(USE_MUNMAP) GC_enable_incremental(); GC_printf("Switched to incremental mode\n"); -# if defined(MPROTECT_VDB) - GC_printf("Emulating dirty bits with mprotect/signals\n"); -# else -# ifdef PROC_VDB - GC_printf("Reading dirty bits from /proc\n"); -# else - GC_printf("Using DEFAULT_VDB dirty bit implementation\n"); +# ifdef MPROTECT_VDB + GC_printf("Emulating dirty bits with mprotect/signals\n"); # endif -# endif # endif GC_set_warn_proc(warn_proc); if ((code = pthread_key_create(&fl_key, 0)) != 0) { GC_printf("Key creation failed %d\n", code); FAIL; } - for (i = 0; i < NTHREADS; ++i) { - if ((code = pthread_create(th+i, &attr, thr_run_one_test, 0)) != 0) { - GC_printf("Thread %d creation failed %d\n", i, code); - FAIL; + set_print_procs(); +# if NTHREADS > 0 + for (i = 0; i < NTHREADS; ++i) { + if ((code = pthread_create(th+i, &attr, thr_run_one_test, 0)) != 0) { + GC_printf("Thread %d creation failed %d\n", i, code); + FAIL; + } } - } +# endif run_one_test(); - for (i = 0; i < NTHREADS; ++i) { - if ((code = pthread_join(th[i], 0)) != 0) { - GC_printf("Thread %d failed %d\n", i, code); - FAIL; +# if NTHREADS > 0 + for (i = 0; i < NTHREADS; ++i) { + if ((code = pthread_join(th[i], 0)) != 0) { + GC_printf("Thread %d failed %d\n", i, code); + FAIL; + } } - } +# endif check_heap_stats(); (void)fflush(stdout); (void)pthread_attr_destroy(&attr); +# if defined(CPPCHECK) + UNTESTED(GC_allow_register_threads); + UNTESTED(GC_get_on_thread_event); + UNTESTED(GC_register_altstack); + UNTESTED(GC_set_on_thread_event); + UNTESTED(GC_set_suspend_signal); + UNTESTED(GC_set_thr_restart_signal); +# ifndef GC_NO_DLOPEN + UNTESTED(GC_dlopen); +# endif +# ifndef GC_NO_PTHREAD_CANCEL + UNTESTED(GC_pthread_cancel); +# endif +# ifdef GC_HAVE_PTHREAD_EXIT + UNTESTED(GC_pthread_exit); +# endif +# ifndef GC_NO_PTHREAD_SIGMASK + UNTESTED(GC_pthread_sigmask); +# endif +# ifdef NO_TEST_HANDLE_FORK + UNTESTED(GC_atfork_child); + UNTESTED(GC_atfork_parent); + UNTESTED(GC_atfork_prepare); + UNTESTED(GC_set_handle_fork); + UNTESTED(GC_start_mark_threads); +# endif +# endif /* CPPCHECK */ # ifdef PTW32_STATIC_LIB pthread_win32_thread_detach_np (); pthread_win32_process_detach_np (); diff --git a/src/bdwgc/tests/test_cpp.cc b/src/bdwgc/tests/test_cpp.cc index 1a413774d..612cd1a5e 100644 --- a/src/bdwgc/tests/test_cpp.cc +++ b/src/bdwgc/tests/test_cpp.cc @@ -70,16 +70,18 @@ extern "C" { __LINE__ ); \ exit( 1 ); } -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# define ATTR_UNUSED __attribute__((__unused__)) -#else -# define ATTR_UNUSED /* empty */ +#ifndef GC_ATTR_EXPLICIT +# if (__cplusplus >= 201103L) || defined(CPPCHECK) +# define GC_ATTR_EXPLICIT explicit +# else +# define GC_ATTR_EXPLICIT /* empty */ +# endif #endif class A {public: /* An uncollectible class. */ - A( int iArg ): i( iArg ) {} + GC_ATTR_EXPLICIT A( int iArg ): i( iArg ) {} void Test( int iArg ) { my_assert( i == iArg );} int i;}; @@ -88,8 +90,8 @@ class A {public: class B: public GC_NS_QUALIFY(gc), public A { public: /* A collectible class. */ - B( int j ): A( j ) {} - ~B() { + GC_ATTR_EXPLICIT B( int j ): A( j ) {} + virtual ~B() { my_assert( deleting );} static void Deleting( int on ) { deleting = on;} @@ -97,16 +99,49 @@ class B: public GC_NS_QUALIFY(gc), public A { public: int B::deleting = 0; +#define C_INIT_LEFT_RIGHT(arg_l, arg_r) \ + { \ + C *l = new C(arg_l); \ + C *r = new C(arg_r); \ + left = l; \ + right = r; \ + if (GC_is_heap_ptr(this)) { \ + GC_END_STUBBORN_CHANGE(this); \ + GC_reachable_here(l); \ + GC_reachable_here(r); \ + } \ + } class C: public GC_NS_QUALIFY(gc_cleanup), public A { public: /* A collectible class with cleanup and virtual multiple inheritance. */ - C( int levelArg ): A( levelArg ), level( levelArg ) { + // The class uses dynamic memory/resource allocation, so provide both + // a copy constructor and an assignment operator to workaround a cppcheck + // warning. + C(const C& c) : A(c.i), level(c.level), left(0), right(0) { + if (level > 0) + C_INIT_LEFT_RIGHT(*c.left, *c.right); + } + + C& operator=(const C& c) { + if (this != &c) { + delete left; + delete right; + i = c.i; + level = c.level; + left = 0; + right = 0; + if (level > 0) + C_INIT_LEFT_RIGHT(*c.left, *c.right); + } + return *this; + } + + GC_ATTR_EXPLICIT C( int levelArg ): A( levelArg ), level( levelArg ) { nAllocated++; if (level > 0) { - left = new C( level - 1 ); - right = new C( level - 1 );} - else { + C_INIT_LEFT_RIGHT(level - 1, level - 1); + } else { left = right = 0;}} ~C() { this->A::Test( level ); @@ -133,12 +168,12 @@ class D: public GC_NS_QUALIFY(gc) { public: /* A collectible class with a static member function to be used as an explicit clean-up function supplied to ::new. */ - D( int iArg ): i( iArg ) { + GC_ATTR_EXPLICIT D( int iArg ): i( iArg ) { nAllocated++;} static void CleanUp( void* obj, void* data ) { - D* self = (D*) obj; + D* self = static_cast(obj); nFreed++; - my_assert( self->i == (int) (GC_word) data );} + my_assert( (GC_word)self->i == (GC_word)data );} static void Test() { my_assert( nFreed >= .8 * nAllocated );} @@ -170,19 +205,25 @@ class F: public E {public: member with clean-up. */ F() { - nAllocated++;} + nAllocatedF++; + } + ~F() { - nFreed++;} + nFreedF++; + } + static void Test() { - my_assert( nFreed >= .8 * nAllocated ); - my_assert( 2 * nFreed == E::nFreed );} + my_assert(nFreedF >= .8 * nAllocatedF); + my_assert(2 * nFreedF == nFreed); + } E e; - static int nFreed; - static int nAllocated;}; + static int nFreedF; + static int nAllocatedF; +}; -int F::nFreed = 0; -int F::nAllocated = 0; +int F::nFreedF = 0; +int F::nAllocatedF = 0; GC_word Disguise( void* p ) { @@ -191,20 +232,50 @@ GC_word Disguise( void* p ) { void* Undisguise( GC_word i ) { return (void*) ~ i;} -#ifdef MSWIN32 -int APIENTRY WinMain( HINSTANCE instance ATTR_UNUSED, - HINSTANCE prev ATTR_UNUSED, LPSTR cmd, int cmdShow ATTR_UNUSED ) -{ +#if ((defined(MSWIN32) && !defined(__MINGW32__)) || defined(MSWINCE)) \ + && !defined(NO_WINMAIN_ENTRY) + int APIENTRY WinMain( HINSTANCE /* instance */, HINSTANCE /* prev */, + LPSTR cmd, int /* cmdShow */) + { int argc = 0; char* argv[ 3 ]; +# if defined(CPPCHECK) + GC_noop1((GC_word)&WinMain); +# endif if (cmd != 0) for (argc = 1; argc < (int)(sizeof(argv) / sizeof(argv[0])); argc++) { - argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" ); - if (0 == argv[ argc ]) break;} + // Parse the command-line string. Non-reentrant strtok() is not used + // to avoid complains of static analysis tools. (And, strtok_r() is + // not available on some platforms.) The code is equivalent to: + // if (!(argv[argc] = strtok(argc == 1 ? cmd : 0, " \t"))) break; + if (NULL == cmd) { + argv[argc] = NULL; + break; + } + argv[argc] = cmd; + for (; *cmd != '\0'; cmd++) { + if (*cmd != ' ' && *cmd != '\t') + break; + } + if ('\0' == *cmd) { + argv[argc] = NULL; + break; + } + argv[argc] = cmd; + while (*(++cmd) != '\0') { + if (*cmd == ' ' || *cmd == '\t') + break; + } + if (*cmd != '\0') { + *(cmd++) = '\0'; + } else { + cmd = NULL; + } + } #elif defined(MACOS) int main() { - char* argv_[] = {"test_cpp", "10"}; // MacOS doesn't have a commandline + char* argv_[] = {"test_cpp", "10"}; // MacOS doesn't have a command line argv = argv_; argc = sizeof(argv_)/sizeof(argv_[0]); #else @@ -233,11 +304,16 @@ int APIENTRY WinMain( HINSTANCE instance ATTR_UNUSED, exit(3); } *xptr = x; + GC_END_STUBBORN_CHANGE(xptr); + GC_reachable_here(x); x = 0; # endif - if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) { - GC_printf( "usage: test_cpp number-of-iterations\nAssuming 10 iters\n" ); - n = 10;} + if (argc != 2 + || (n = (int)COVERT_DATAFLOW(atoi(argv[1]))) <= 0) { + GC_printf("usage: test_cpp number-of-iterations\n" + "Assuming 10 iters\n"); + n = 10; + } for (iters = 1; iters <= n; iters++) { GC_printf( "Starting iteration %d\n", iters ); @@ -261,7 +337,10 @@ int APIENTRY WinMain( HINSTANCE instance ATTR_UNUSED, d = ::new (USE_GC, D::CleanUp, (void*)(GC_word)i) D( i ); (void)d; f = new F; - (void)f; + F** fa = new F*[1]; + fa[0] = f; + (void)fa; + delete[] fa; if (0 == i % 10) delete c;} /* Allocate a very large number of collectible As and Bs and @@ -286,10 +365,17 @@ int APIENTRY WinMain( HINSTANCE instance ATTR_UNUSED, /* Make sure the uncollectible As and Bs are still there. */ for (i = 0; i < 1000; i++) { - A* a = (A*) Undisguise( as[ i ] ); - B* b = (B*) Undisguise( bs[ i ] ); + A* a = static_cast(Undisguise(as[i])); + B* b = static_cast(Undisguise(bs[i])); a->Test( i ); - delete a; +# if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) + // Workaround for ASan/MSan: the linker uses operator delete + // implementation from libclang_rt instead of gc_cpp (thus + // causing incompatible alloc/free). + GC_FREE(a); +# else + delete a; +# endif b->Test( i ); B::Deleting( 1 ); delete b; diff --git a/src/bdwgc/tests/tests.am b/src/bdwgc/tests/tests.am index 131d4e9ab..66f69b871 100644 --- a/src/bdwgc/tests/tests.am +++ b/src/bdwgc/tests/tests.am @@ -71,6 +71,7 @@ tracetest_LDADD = $(test_ldadd) endif if THREADS + TESTS += threadleaktest$(EXEEXT) check_PROGRAMS += threadleaktest threadleaktest_SOURCES = tests/thread_leak_test.c @@ -90,6 +91,7 @@ TESTS += initsecondarythread_test$(EXEEXT) check_PROGRAMS += initsecondarythread_test initsecondarythread_test_SOURCES = tests/initsecondarythread.c initsecondarythread_test_LDADD = $(test_ldadd) $(THREADDLLIBS) + endif if CPLUSPLUS @@ -104,7 +106,8 @@ endif endif if ENABLE_DISCLAIM -TESTS += disclaim_test + +TESTS += disclaim_test$(EXEEXT) check_PROGRAMS += disclaim_test disclaim_test_SOURCES = tests/disclaim_test.c disclaim_test_LDADD = $(test_ldadd) @@ -112,8 +115,9 @@ if THREADS disclaim_test_LDADD += $(THREADDLLIBS) endif -TESTS += disclaim_bench +TESTS += disclaim_bench$(EXEEXT) check_PROGRAMS += disclaim_bench disclaim_bench_SOURCES = tests/disclaim_bench.c disclaim_bench_LDADD = $(test_ldadd) + endif diff --git a/src/bdwgc/tests/thread_leak_test.c b/src/bdwgc/tests/thread_leak_test.c index 845de00ec..6cb7ab39e 100644 --- a/src/bdwgc/tests/thread_leak_test.c +++ b/src/bdwgc/tests/thread_leak_test.c @@ -7,6 +7,7 @@ # define GC_THREADS #endif +#undef GC_NO_THREAD_REDIRECTS #include "leak_detector.h" #ifdef GC_PTHREADS @@ -39,9 +40,12 @@ # endif } -#define NTHREADS 5 +#ifndef NTHREADS +# define NTHREADS 5 +#endif int main(void) { +# if NTHREADS > 0 int i; # ifdef GC_PTHREADS pthread_t t[NTHREADS]; @@ -50,11 +54,13 @@ int main(void) { DWORD thread_id; # endif int code; +# endif GC_set_find_leak(1); /* for new collect versions not compiled */ /* with -DFIND_LEAK. */ GC_INIT(); +# if NTHREADS > 0 for (i = 0; i < NTHREADS; ++i) { # ifdef GC_PTHREADS code = pthread_create(t + i, 0, test, 0); @@ -80,6 +86,7 @@ int main(void) { exit(2); } } +# endif CHECK_LEAKS(); CHECK_LEAKS(); diff --git a/src/bdwgc/tests/threadkey_test.c b/src/bdwgc/tests/threadkey_test.c index f87530e33..b08a0a946 100644 --- a/src/bdwgc/tests/threadkey_test.c +++ b/src/bdwgc/tests/threadkey_test.c @@ -11,6 +11,9 @@ #include "gc.h" +#include +#include + #if (!defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) \ || defined(__native_client__)) && !defined(SKIP_THREADKEY_TEST) /* FIXME: Skip this test on Solaris for now. The test may fail on */ @@ -21,8 +24,6 @@ #ifdef SKIP_THREADKEY_TEST -#include - int main (void) { printf("threadkey_test skipped\n"); @@ -54,8 +55,15 @@ void * GC_CALLBACK on_thread_exit_inner (struct GC_stack_base * sb, void * arg) pthread_t t; int creation_res; /* Used to suppress a warning about */ /* unchecked pthread_create() result. */ + pthread_attr_t attr; - creation_res = GC_pthread_create (&t, NULL, entry, NULL); + if (pthread_attr_init(&attr) != 0 + || pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) { + fprintf(stderr, "Thread attribute init or setdetachstate failed\n"); + exit(2); + } + creation_res = GC_pthread_create(&t, &attr, entry, NULL); + (void)pthread_attr_destroy(&attr); if (res == GC_SUCCESS) GC_unregister_my_thread (); @@ -88,10 +96,17 @@ int main (void) # endif for (i = 0; i < LIMIT; i++) { pthread_t t; - void *res; - if (GC_pthread_create (&t, NULL, entry, NULL) == 0 - && (i & 1) != 0) { - (void)GC_pthread_join(t, &res); + + if (GC_pthread_create(&t, NULL, entry, NULL) == 0) { + void *res; + int code = (i & 1) != 0 ? GC_pthread_join(t, &res) + : GC_pthread_detach(t); + + if (code != 0) { + fprintf(stderr, "Thread %s failed %d\n", + (i & 1) != 0 ? "join" : "detach", code); + exit(2); + } } } return 0; diff --git a/src/bdwgc/tests/trace_test.c b/src/bdwgc/tests/trace_test.c index 79c353f71..746f94e24 100644 --- a/src/bdwgc/tests/trace_test.c +++ b/src/bdwgc/tests/trace_test.c @@ -15,14 +15,22 @@ struct treenode { struct treenode * mktree(int i) { struct treenode * r = GC_MALLOC(sizeof(struct treenode)); + struct treenode *x, *y; if (0 == i) return 0; if (1 == i) r = GC_MALLOC_ATOMIC(sizeof(struct treenode)); if (r == NULL) { fprintf(stderr, "Out of memory\n"); exit(1); } - r -> x = mktree(i-1); - r -> y = mktree(i-1); + x = mktree(i - 1); + y = mktree(i - 1); + r -> x = x; + r -> y = y; + if (i != 1) { + GC_END_STUBBORN_CHANGE(r); + GC_reachable_here(x); + GC_reachable_here(y); + } return r; } diff --git a/src/bdwgc/thread_local_alloc.c b/src/bdwgc/thread_local_alloc.c index 8d184f51a..234c06de4 100644 --- a/src/bdwgc/thread_local_alloc.c +++ b/src/bdwgc/thread_local_alloc.c @@ -24,30 +24,24 @@ #include #if defined(USE_COMPILER_TLS) - __thread + __thread GC_ATTR_TLS_FAST #elif defined(USE_WIN32_COMPILER_TLS) - __declspec(thread) + __declspec(thread) GC_ATTR_TLS_FAST #endif GC_key_t GC_thread_key; static GC_bool keys_initialized; -#ifdef ENABLE_DISCLAIM - GC_INNER ptr_t * GC_finalized_objfreelist = NULL; - /* This variable is declared here to prevent linking of */ - /* fnlz_mlc module unless the client uses the latter one. */ -#endif - /* Return a single nonempty freelist fl to the global one pointed to */ /* by gfl. */ static void return_single_freelist(void *fl, void **gfl) { - void *q, **qptr; - if (*gfl == 0) { *gfl = fl; } else { + void *q, **qptr; + GC_ASSERT(GC_size(fl) == GC_size(*gfl)); /* Concatenate: */ qptr = &(obj_link(fl)); @@ -67,7 +61,7 @@ static void return_freelists(void **fl, void **gfl) for (i = 1; i < TINY_FREELISTS; ++i) { if ((word)(fl[i]) >= HBLKSIZE) { - return_single_freelist(fl[i], gfl+i); + return_single_freelist(fl[i], &gfl[i]); } /* Clear fl[i], since the thread structure may hang around. */ /* Do it in a way that is likely to trap if we access it. */ @@ -78,65 +72,73 @@ static void return_freelists(void **fl, void **gfl) if (fl[0] == ERROR_FL) return; # endif if ((word)(fl[0]) >= HBLKSIZE) { - return_single_freelist(fl[0], gfl+1); + return_single_freelist(fl[0], &gfl[1]); } } +#ifdef USE_PTHREAD_SPECIFIC + /* Re-set the TLS value on thread cleanup to allow thread-local */ + /* allocations to happen in the TLS destructors. */ + /* GC_unregister_my_thread (and similar routines) will finally set */ + /* the GC_thread_key to NULL preventing this destructor from being */ + /* called repeatedly. */ + static void reset_thread_key(void* v) { + pthread_setspecific(GC_thread_key, v); + } +#else +# define reset_thread_key 0 +#endif + /* Each thread structure must be initialized. */ /* This call must be made from the new thread. */ GC_INNER void GC_init_thread_local(GC_tlfs p) { - int i; + int i, j, res; GC_ASSERT(I_HOLD_LOCK()); if (!EXPECT(keys_initialized, TRUE)) { GC_ASSERT((word)&GC_thread_key % sizeof(word) == 0); - if (0 != GC_key_create(&GC_thread_key, 0)) { + res = GC_key_create(&GC_thread_key, reset_thread_key); + if (COVERT_DATAFLOW(res) != 0) { ABORT("Failed to create key for local allocator"); } keys_initialized = TRUE; } - if (0 != GC_setspecific(GC_thread_key, p)) { + res = GC_setspecific(GC_thread_key, p); + if (COVERT_DATAFLOW(res) != 0) { ABORT("Failed to set thread specific allocation pointers"); } - for (i = 1; i < TINY_FREELISTS; ++i) { - p -> ptrfree_freelists[i] = (void *)(word)1; - p -> normal_freelists[i] = (void *)(word)1; + for (j = 0; j < TINY_FREELISTS; ++j) { + for (i = 0; i < THREAD_FREELISTS_KINDS; ++i) { + p -> _freelists[i][j] = (void *)(word)1; + } # ifdef GC_GCJ_SUPPORT - p -> gcj_freelists[i] = (void *)(word)1; -# endif -# ifdef ENABLE_DISCLAIM - p -> finalized_freelists[i] = (void *)(word)1; + p -> gcj_freelists[j] = (void *)(word)1; # endif } - /* Set up the size 0 free lists. */ - /* We now handle most of them like regular free lists, to ensure */ - /* That explicit deallocation works. However, allocation of a */ - /* size 0 "gcj" object is always an error. */ - p -> ptrfree_freelists[0] = (void *)(word)1; - p -> normal_freelists[0] = (void *)(word)1; + /* The size 0 free lists are handled like the regular free lists, */ + /* to ensure that the explicit deallocation works. However, */ + /* allocation of a size 0 "gcj" object is always an error. */ # ifdef GC_GCJ_SUPPORT p -> gcj_freelists[0] = ERROR_FL; # endif -# ifdef ENABLE_DISCLAIM - p -> finalized_freelists[0] = (void *)(word)1; -# endif } /* We hold the allocator lock. */ GC_INNER void GC_destroy_thread_local(GC_tlfs p) { - /* We currently only do this from the thread itself or from */ - /* the fork handler for a child process. */ - return_freelists(p -> ptrfree_freelists, GC_aobjfreelist); - return_freelists(p -> normal_freelists, GC_objfreelist); + int k; + + /* We currently only do this from the thread itself. */ + GC_STATIC_ASSERT(THREAD_FREELISTS_KINDS <= MAXOBJKINDS); + for (k = 0; k < THREAD_FREELISTS_KINDS; ++k) { + if (k == (int)GC_n_kinds) + break; /* kind is not created */ + return_freelists(p -> _freelists[k], GC_obj_kinds[k].ok_freelist); + } # ifdef GC_GCJ_SUPPORT return_freelists(p -> gcj_freelists, (void **)GC_gcjobjfreelist); # endif -# ifdef ENABLE_DISCLAIM - return_freelists(p -> finalized_freelists, - (void **)GC_finalized_objfreelist); -# endif } #ifdef GC_ASSERTIONS @@ -144,78 +146,59 @@ GC_INNER void GC_destroy_thread_local(GC_tlfs p) GC_bool GC_is_thread_tsd_valid(void *tsd); #endif -GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc(size_t bytes) +GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_kind(size_t bytes, int knd) { - size_t granules = ROUNDED_UP_GRANULES(bytes); + size_t granules; void *tsd; void *result; - void **tiny_fl; +# if MAXOBJKINDS > THREAD_FREELISTS_KINDS + if (EXPECT(knd >= THREAD_FREELISTS_KINDS, FALSE)) { + return GC_malloc_kind_global(bytes, knd); + } +# endif # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) + { GC_key_t k = GC_thread_key; + if (EXPECT(0 == k, FALSE)) { /* We haven't yet run GC_init_parallel. That means */ /* we also aren't locking, so this is fairly cheap. */ - return GC_core_malloc(bytes); + return GC_malloc_kind_global(bytes, knd); } tsd = GC_getspecific(k); + } # else + if (!EXPECT(keys_initialized, TRUE)) + return GC_malloc_kind_global(bytes, knd); tsd = GC_getspecific(GC_thread_key); # endif # if !defined(USE_COMPILER_TLS) && !defined(USE_WIN32_COMPILER_TLS) if (EXPECT(0 == tsd, FALSE)) { - return GC_core_malloc(bytes); + return GC_malloc_kind_global(bytes, knd); } # endif GC_ASSERT(GC_is_initialized); - GC_ASSERT(GC_is_thread_tsd_valid(tsd)); - - tiny_fl = ((GC_tlfs)tsd) -> normal_freelists; - GC_FAST_MALLOC_GRANS(result, granules, tiny_fl, DIRECT_GRANULES, - NORMAL, GC_core_malloc(bytes), obj_link(result)=0); + granules = ROUNDED_UP_GRANULES(bytes); + GC_FAST_MALLOC_GRANS(result, granules, + ((GC_tlfs)tsd) -> _freelists[knd], DIRECT_GRANULES, + knd, GC_malloc_kind_global(bytes, knd), + (void)(knd == PTRFREE ? NULL + : (obj_link(result) = 0))); # ifdef LOG_ALLOCS - GC_log_printf("GC_malloc(%lu) returned %p, recent GC #%lu\n", - (unsigned long)bytes, result, (unsigned long)GC_gc_no); + GC_log_printf("GC_malloc_kind(%lu, %d) returned %p, recent GC #%lu\n", + (unsigned long)bytes, knd, result, + (unsigned long)GC_gc_no); # endif return result; } -GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_atomic(size_t bytes) -{ - size_t granules = ROUNDED_UP_GRANULES(bytes); - void *tsd; - void *result; - void **tiny_fl; - -# if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_WIN32_SPECIFIC) - GC_key_t k = GC_thread_key; - if (EXPECT(0 == k, FALSE)) { - /* We haven't yet run GC_init_parallel. That means */ - /* we also aren't locking, so this is fairly cheap. */ - return GC_core_malloc_atomic(bytes); - } - tsd = GC_getspecific(k); -# else - tsd = GC_getspecific(GC_thread_key); -# endif -# if !defined(USE_COMPILER_TLS) && !defined(USE_WIN32_COMPILER_TLS) - if (EXPECT(0 == tsd, FALSE)) { - return GC_core_malloc_atomic(bytes); - } -# endif - GC_ASSERT(GC_is_initialized); - tiny_fl = ((GC_tlfs)tsd) -> ptrfree_freelists; - GC_FAST_MALLOC_GRANS(result, granules, tiny_fl, DIRECT_GRANULES, PTRFREE, - GC_core_malloc_atomic(bytes), (void)0 /* no init */); - return result; -} - #ifdef GC_GCJ_SUPPORT # include "atomic_ops.h" /* for AO_compiler_barrier() */ -# include "include/gc_gcj.h" +# include "gc_gcj.h" /* Gcj-style allocation without locks is extremely tricky. The */ /* fundamental issue is that we may end up marking a free list, which */ @@ -285,23 +268,20 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_gcj_malloc(size_t bytes, GC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p) { ptr_t q; - int j; + int i, j; for (j = 0; j < TINY_FREELISTS; ++j) { - q = p -> ptrfree_freelists[j]; - if ((word)q > HBLKSIZE) GC_set_fl_marks(q); - q = p -> normal_freelists[j]; - if ((word)q > HBLKSIZE) GC_set_fl_marks(q); -# ifdef GC_GCJ_SUPPORT - if (j > 0) { - q = p -> gcj_freelists[j]; - if ((word)q > HBLKSIZE) GC_set_fl_marks(q); - } -# endif /* GC_GCJ_SUPPORT */ -# ifdef ENABLE_DISCLAIM - q = p -> finalized_freelists[j]; + for (i = 0; i < THREAD_FREELISTS_KINDS; ++i) { + q = p -> _freelists[i][j]; if ((word)q > HBLKSIZE) GC_set_fl_marks(q); + } +# ifdef GC_GCJ_SUPPORT + if (EXPECT(j > 0, TRUE)) { + q = p -> gcj_freelists[j]; + if ((word)q > HBLKSIZE) + GC_set_fl_marks(q); + } # endif } } @@ -310,16 +290,14 @@ GC_INNER void GC_mark_thread_local_fls_for(GC_tlfs p) /* Check that all thread-local free-lists in p are completely marked. */ void GC_check_tls_for(GC_tlfs p) { - int j; + int i, j; for (j = 1; j < TINY_FREELISTS; ++j) { - GC_check_fl_marks(&p->ptrfree_freelists[j]); - GC_check_fl_marks(&p->normal_freelists[j]); + for (i = 0; i < THREAD_FREELISTS_KINDS; ++i) { + GC_check_fl_marks(&p->_freelists[i][j]); + } # ifdef GC_GCJ_SUPPORT GC_check_fl_marks(&p->gcj_freelists[j]); -# endif -# ifdef ENABLE_DISCLAIM - GC_check_fl_marks(&p->finalized_freelists[j]); # endif } } diff --git a/src/bdwgc/tools/if_mach.c b/src/bdwgc/tools/if_mach.c index 94053a666..18c40e553 100644 --- a/src/bdwgc/tools/if_mach.c +++ b/src/bdwgc/tools/if_mach.c @@ -9,11 +9,11 @@ int main(int argc, char **argv) { if (argc < 4) goto Usage; if (strcmp(MACH_TYPE, argv[1]) != 0) return(0); - if (strcmp(OS_TYPE, "") != 0 && strcmp(argv[2], "") != 0 + if (strlen(OS_TYPE) > 0 && strlen(argv[2]) > 0 && strcmp(OS_TYPE, argv[2]) != 0) return(0); fprintf(stderr, "^^^^Starting command^^^^\n"); fflush(stdout); - execvp(argv[3], argv+3); + execvp(TRUSTED_STRING(argv[3]), (void *)(argv + 3)); perror("Couldn't execute"); Usage: diff --git a/src/bdwgc/tools/if_not_there.c b/src/bdwgc/tools/if_not_there.c index c0f095d05..68946d239 100644 --- a/src/bdwgc/tools/if_not_there.c +++ b/src/bdwgc/tools/if_not_there.c @@ -15,21 +15,30 @@ int main(int argc, char **argv) #ifdef __DJGPP__ DIR * d; #endif /* __DJGPP__ */ + char *fname; + if (argc < 3) goto Usage; - if ((f = fopen(argv[1], "rb")) != 0 - || (f = fopen(argv[1], "r")) != 0) { + + fname = TRUSTED_STRING(argv[1]); + f = fopen(fname, "rb"); + if (f != NULL) { + fclose(f); + return(0); + } + f = fopen(fname, "r"); + if (f != NULL) { fclose(f); return(0); } #ifdef __DJGPP__ - if ((d = opendir(argv[1])) != 0) { + if ((d = opendir(fname)) != 0) { closedir(d); return(0); } #endif printf("^^^^Starting command^^^^\n"); fflush(stdout); - execvp(argv[2], argv+2); + execvp(TRUSTED_STRING(argv[2]), (void *)(argv + 2)); exit(1); Usage: diff --git a/src/bdwgc/tools/setjmp_t.c b/src/bdwgc/tools/setjmp_t.c index 1d9a1ad0a..012282ab6 100644 --- a/src/bdwgc/tools/setjmp_t.c +++ b/src/bdwgc/tools/setjmp_t.c @@ -60,24 +60,36 @@ struct { char * a_b; } a; -int * nested_sp(void) +word nested_sp(void) { +# if defined(__GNUC__) && (__GNUC__ >= 4) + return (word)__builtin_frame_address(0); +# else volatile word sp; sp = (word)(&sp); - return (int *)sp; + return sp; +# endif } +/* To prevent nested_sp inlining. */ +word (*volatile nested_sp_fn)(void) = nested_sp; + +int g(int x); + int main(void) { volatile word sp; - long ps = GETPAGESIZE(); + unsigned ps = GETPAGESIZE(); jmp_buf b; register int x = (int)strlen("a"); /* 1, slightly disguised */ - static int y = 0; + static volatile int y = 0; sp = (word)(&sp); printf("This appears to be a %s running %s\n", MACH_TYPE, OS_TYPE); - if ((word)nested_sp() < sp) { +# if defined(CPPCHECK) + (void)nested_sp(); /* to workaround a bug in cppcheck */ +# endif + if (nested_sp_fn() < sp) { printf("Stack appears to grow down, which is the default.\n"); printf("A good guess for STACKBOTTOM on this machine is 0x%lx.\n", ((unsigned long)sp + ps) & ~(ps-1)); @@ -90,7 +102,7 @@ int main(void) printf("Note that this may vary between machines of ostensibly\n"); printf("the same architecture (e.g. Sun 3/50s and 3/80s).\n"); printf("On many machines the value is not fixed.\n"); - printf("A good guess for ALIGNMENT on this machine is %ld.\n", + printf("A good guess for ALIGNMENT on this machine is %lu.\n", (unsigned long)((word)(&(a.a_b)) - (word)(&a))); printf("The following is a very dubious test of one root marking" @@ -103,7 +115,7 @@ int main(void) setjmp(b); if (y == 1) { if (x == 2) { - printf("Setjmp-based generic mark_regs code probably wont work.\n"); + printf("Setjmp-based generic mark_regs code probably won't work.\n"); printf("But we rarely try that anymore. If you have getcontect()\n"); printf("this probably doesn't matter.\n"); } else if (x == 1) { @@ -136,6 +148,7 @@ int main(void) # ifdef PARALLEL_MARK printf("Parallel marking enabled.\n"); # endif + (void)g(x); return(0); } diff --git a/src/bdwgc/tools/threadlibs.c b/src/bdwgc/tools/threadlibs.c index a97f91b8f..bebca5363 100644 --- a/src/bdwgc/tools/threadlibs.c +++ b/src/bdwgc/tools/threadlibs.c @@ -42,10 +42,10 @@ int main(void) # ifdef GC_USE_DLOPEN_WRAP printf("-ldl "); # endif -# if (__FREEBSD_version >= 500000) - printf("-lpthread\n"); -# else +# if (__FREEBSD_version < 500000) printf("-pthread\n"); +# else /* __FREEBSD__ || __DragonFly__ */ + printf("-lpthread\n"); # endif # endif # if defined(GC_NETBSD_THREADS) @@ -71,7 +71,7 @@ int main(void) # endif # endif # if defined(GC_OSF1_THREADS) - printf("-pthread -lrt"); /* DOB: must be -pthread, not -lpthread */ + printf("-pthread -lrt\n"); /* DOB: must be -pthread, not -lpthread */ # endif /* You need GCC 3.0.3 to build this one! */ /* DG/UX native gcc doesn't know what "-pthread" is */ diff --git a/src/bdwgc/typd_mlc.c b/src/bdwgc/typd_mlc.c index 30646a48f..22b980c55 100644 --- a/src/bdwgc/typd_mlc.c +++ b/src/bdwgc/typd_mlc.c @@ -14,6 +14,7 @@ */ #include "private/gc_pmark.h" +#include "gc_inline.h" /* for GC_malloc_kind */ /* * Some simple primitives for allocation with explicit type information. @@ -41,8 +42,6 @@ #define TYPD_EXTRA_BYTES (sizeof(word) - EXTRA_BYTES) -STATIC GC_bool GC_explicit_typing_initialized = FALSE; - STATIC int GC_explicit_kind = 0; /* Object kind for objects with indirect */ /* (possibly extended) descriptors. */ @@ -86,7 +85,7 @@ typedef union ComplexDescriptor { union ComplexDescriptor * sd_second; } sd; } complex_descriptor; -#define TAG ld.ld_tag +#define TAG ad.ad_tag STATIC ext_descr * GC_ext_descriptors = NULL; /* Points to array of extended */ @@ -100,17 +99,26 @@ STATIC size_t GC_avail_descr = 0; /* Next available slot. */ STATIC int GC_typed_mark_proc_index = 0; /* Indices of my mark */ STATIC int GC_array_mark_proc_index = 0; /* procedures. */ +#if !defined(AO_HAVE_load_acquire) && defined(GC_FORCE_INCLUDE_ATOMIC_OPS) +# include "atomic_ops.h" +#endif + +#ifdef AO_HAVE_load_acquire + STATIC volatile AO_t GC_explicit_typing_initialized = FALSE; +#else + STATIC GC_bool GC_explicit_typing_initialized = FALSE; +#endif + STATIC void GC_push_typed_structures_proc(void) { - GC_push_all((ptr_t)&GC_ext_descriptors, - (ptr_t)&GC_ext_descriptors + sizeof(word)); + GC_PUSH_ALL_SYM(GC_ext_descriptors); } /* Add a multiword bitmap to GC_ext_descriptors arrays. Return */ /* starting index. */ /* Returns -1 on failure. */ /* Caller does not hold allocation lock. */ -STATIC signed_word GC_add_ext_descriptor(const GC_word * bm, word nbits) +STATIC signed_word GC_add_ext_descriptor(const word * bm, word nbits) { size_t nwords = divWORDSZ(nbits + WORDSZ-1); signed_word result; @@ -126,7 +134,7 @@ STATIC signed_word GC_add_ext_descriptor(const GC_word * bm, word nbits) word ed_size = GC_ed_size; if (ed_size == 0) { - GC_ASSERT((word)&GC_ext_descriptors % sizeof(word) == 0); + GC_ASSERT((word)(&GC_ext_descriptors) % sizeof(word) == 0); GC_push_typed_structures = GC_push_typed_structures_proc; UNLOCK(); new_size = ED_INITIAL_SIZE; @@ -189,7 +197,7 @@ GC_make_sequence_descriptor(complex_descriptor *first, /* each of which can be described by a simple descriptor. */ /* We try to optimize some common cases. */ /* If the result is COMPLEX, then a complex_descr* is returned */ -/* in *complex_d. */ +/* in *complex_d. */ /* If the result is LEAF, then we built a LeafDescriptor in */ /* the structure pointed to by leaf. */ /* The tag in the leaf structure is not set. */ @@ -313,50 +321,26 @@ GC_make_sequence_descriptor(complex_descriptor *first, result -> sd_tag = SEQUENCE_TAG; result -> sd_first = first; result -> sd_second = second; + GC_dirty(result); + REACHABLE_AFTER_DIRTY(first); + REACHABLE_AFTER_DIRTY(second); } return((complex_descriptor *)result); } -#ifdef UNDEFINED - complex_descriptor * GC_make_complex_array_descriptor(word nelements, - complex_descriptor *descr) - { - struct ComplexArrayDescriptor * result = - (struct ComplexArrayDescriptor *) - GC_malloc(sizeof(struct ComplexArrayDescriptor)); - - if (result != 0) { - result -> ad_tag = ARRAY_TAG; - result -> ad_nelements = nelements; - result -> ad_element_descr = descr; - } - return((complex_descriptor *)result); - } -#endif - STATIC ptr_t * GC_eobjfreelist = NULL; -STATIC ptr_t * GC_arobjfreelist = NULL; - STATIC mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr, mse * mark_stack_limit, word env); STATIC mse * GC_array_mark_proc(word * addr, mse * mark_stack_ptr, mse * mark_stack_limit, word env); -/* Caller does not hold allocation lock. */ STATIC void GC_init_explicit_typing(void) { - register unsigned i; - DCL_LOCK_STATE; + unsigned i; GC_STATIC_ASSERT(sizeof(struct LeafDescriptor) % sizeof(word) == 0); - LOCK(); - if (GC_explicit_typing_initialized) { - UNLOCK(); - return; - } - GC_explicit_typing_initialized = TRUE; /* Set up object kind with simple indirect descriptor. */ GC_eobjfreelist = (ptr_t *)GC_new_free_list_inner(); GC_explicit_kind = GC_new_kind_inner( @@ -366,16 +350,14 @@ STATIC void GC_init_explicit_typing(void) /* Descriptors are in the last word of the object. */ GC_typed_mark_proc_index = GC_new_proc_inner(GC_typed_mark_proc); /* Set up object kind with array descriptor. */ - GC_arobjfreelist = (ptr_t *)GC_new_free_list_inner(); GC_array_mark_proc_index = GC_new_proc_inner(GC_array_mark_proc); - GC_array_kind = GC_new_kind_inner( - (void **)GC_arobjfreelist, + GC_array_kind = GC_new_kind_inner(GC_new_free_list_inner(), GC_MAKE_PROC(GC_array_mark_proc_index, 0), FALSE, TRUE); - for (i = 0; i < WORDSZ/2; i++) { + GC_bm_table[0] = GC_DS_BITMAP; + for (i = 1; i < WORDSZ/2; i++) { GC_bm_table[i] = (((word)-1) << (WORDSZ - i)) | GC_DS_BITMAP; } - UNLOCK(); } STATIC mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr, @@ -395,7 +377,7 @@ STATIC mse * GC_typed_mark_proc(word * addr, mse * mark_stack_ptr, FIXUP_POINTER(current); if (current >= (word)least_ha && current <= (word)greatest_ha) { PUSH_CONTENTS((ptr_t)current, mark_stack_ptr, - mark_stack_limit, (ptr_t)current_p, exit1); + mark_stack_limit, (ptr_t)current_p); } } } @@ -514,11 +496,20 @@ STATIC mse * GC_array_mark_proc(word * addr, mse * mark_stack_ptr, mark_stack_ptr, mark_stack_limit-1); if (new_mark_stack_ptr == 0) { + /* Explicitly instruct Clang Static Analyzer that ptr is non-null. */ + if (NULL == mark_stack_ptr) ABORT("Bad mark_stack_ptr"); + /* Doesn't fit. Conservatively push the whole array as a unit */ /* and request a mark stack expansion. */ /* This cannot cause a mark stack overflow, since it replaces */ /* the original array entry. */ - GC_mark_stack_too_small = TRUE; +# ifdef PARALLEL_MARK + /* We might be using a local_mark_stack in parallel mode. */ + if (GC_mark_stack + GC_mark_stack_size == mark_stack_limit) +# endif + { + GC_mark_stack_too_small = TRUE; + } new_mark_stack_ptr = orig_mark_stack_ptr + 1; new_mark_stack_ptr -> mse_start = (ptr_t)addr; new_mark_stack_ptr -> mse_descr.w = sz | GC_DS_LENGTH; @@ -535,31 +526,49 @@ GC_API GC_descr GC_CALL GC_make_descriptor(const GC_word * bm, size_t len) { signed_word last_set_bit = len - 1; GC_descr result; - signed_word i; # define HIGH_BIT (((word)1) << (WORDSZ - 1)) + DCL_LOCK_STATE; - if (!EXPECT(GC_explicit_typing_initialized, TRUE)) - GC_init_explicit_typing(); +# if defined(AO_HAVE_load_acquire) && defined(AO_HAVE_store_release) + if (!EXPECT(AO_load_acquire(&GC_explicit_typing_initialized), TRUE)) { + LOCK(); + if (!GC_explicit_typing_initialized) { + GC_init_explicit_typing(); + AO_store_release(&GC_explicit_typing_initialized, TRUE); + } + UNLOCK(); + } +# else + LOCK(); + if (!EXPECT(GC_explicit_typing_initialized, TRUE)) { + GC_init_explicit_typing(); + GC_explicit_typing_initialized = TRUE; + } + UNLOCK(); +# endif while (last_set_bit >= 0 && !GC_get_bit(bm, last_set_bit)) last_set_bit--; if (last_set_bit < 0) return(0 /* no pointers */); + # if ALIGNMENT == CPP_WORDSZ/8 { - register GC_bool all_bits_set = TRUE; + signed_word i; + for (i = 0; i < last_set_bit; i++) { if (!GC_get_bit(bm, i)) { - all_bits_set = FALSE; - break; + break; } } - if (all_bits_set) { + if (i == last_set_bit) { /* An initial section contains all pointers. Use length descriptor. */ return (WORDS_TO_BYTES(last_set_bit+1) | GC_DS_LENGTH); } } # endif if ((word)last_set_bit < BITMAP_BITS) { + signed_word i; + /* Hopefully the common case. */ /* Build bitmap descriptor (with bits reversed) */ result = HIGH_BIT; @@ -568,52 +577,34 @@ GC_API GC_descr GC_CALL GC_make_descriptor(const GC_word * bm, size_t len) if (GC_get_bit(bm, i)) result |= HIGH_BIT; } result |= GC_DS_BITMAP; - return(result); } else { - signed_word index; - - index = GC_add_ext_descriptor(bm, (word)last_set_bit+1); + signed_word index = GC_add_ext_descriptor(bm, (word)last_set_bit + 1); if (index == -1) return(WORDS_TO_BYTES(last_set_bit+1) | GC_DS_LENGTH); /* Out of memory: use conservative */ /* approximation. */ result = GC_MAKE_PROC(GC_typed_mark_proc_index, (word)index); - return result; } + return result; } GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_explicitly_typed(size_t lb, GC_descr d) { - ptr_t op; + word *op; size_t lg; - DCL_LOCK_STATE; - lb += TYPD_EXTRA_BYTES; - if(SMALL_OBJ(lb)) { - GC_DBG_COLLECT_AT_MALLOC(lb); - lg = GC_size_map[lb]; - LOCK(); - op = GC_eobjfreelist[lg]; - if (EXPECT(0 == op, FALSE)) { - UNLOCK(); - op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind); - if (0 == op) return 0; - lg = GC_size_map[lb]; /* May have been uninitialized. */ - } else { - GC_eobjfreelist[lg] = obj_link(op); - obj_link(op) = 0; - GC_bytes_allocd += GRANULES_TO_BYTES(lg); - UNLOCK(); - } - ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d; - } else { - op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind); - if (op != NULL) { - lg = BYTES_TO_GRANULES(GC_size(op)); - ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d; - } - } - return((void *) op); + GC_ASSERT(GC_explicit_typing_initialized); + lb = SIZET_SAT_ADD(lb, TYPD_EXTRA_BYTES); + op = GC_malloc_kind(lb, GC_explicit_kind); + if (EXPECT(NULL == op, FALSE)) + return NULL; + /* It is not safe to use GC_size_map[lb] to compute lg here as the */ + /* the former might be updated asynchronously. */ + lg = BYTES_TO_GRANULES(GC_size(op)); + op[GRANULES_TO_WORDS(lg) - 1] = d; + GC_dirty(op + GRANULES_TO_WORDS(lg) - 1); + REACHABLE_AFTER_DIRTY(d); + return op; } GC_API GC_ATTR_MALLOC void * GC_CALL @@ -623,7 +614,8 @@ GC_API GC_ATTR_MALLOC void * GC_CALL size_t lg; DCL_LOCK_STATE; - lb += TYPD_EXTRA_BYTES; + GC_ASSERT(GC_explicit_typing_initialized); + lb = SIZET_SAT_ADD(lb, TYPD_EXTRA_BYTES); if (SMALL_OBJ(lb)) { GC_DBG_COLLECT_AT_MALLOC(lb); lg = GC_size_map[lb]; @@ -633,98 +625,88 @@ GC_API GC_ATTR_MALLOC void * GC_CALL UNLOCK(); op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind); if (0 == op) return 0; - lg = GC_size_map[lb]; /* May have been uninitialized. */ + /* See the comment in GC_malloc_explicitly_typed. */ + lg = BYTES_TO_GRANULES(GC_size(op)); } else { GC_eobjfreelist[lg] = obj_link(op); obj_link(op) = 0; - GC_bytes_allocd += GRANULES_TO_BYTES(lg); + GC_bytes_allocd += GRANULES_TO_BYTES((word)lg); UNLOCK(); } - ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d; - } else { - op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind); - if (op != NULL) { - lg = BYTES_TO_GRANULES(GC_size(op)); - ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d; - } - } - return((void *) op); + } else { + op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind); + if (NULL == op) return NULL; + lg = BYTES_TO_GRANULES(GC_size(op)); + } + ((word *)op)[GRANULES_TO_WORDS(lg) - 1] = d; + GC_dirty(op + GRANULES_TO_WORDS(lg) - 1); + REACHABLE_AFTER_DIRTY(d); + return op; } GC_API GC_ATTR_MALLOC void * GC_CALL GC_calloc_explicitly_typed(size_t n, size_t lb, GC_descr d) { - ptr_t op; + word *op; size_t lg; GC_descr simple_descr; complex_descriptor *complex_descr; - register int descr_type; + int descr_type; struct LeafDescriptor leaf; - DCL_LOCK_STATE; - descr_type = GC_make_array_descriptor((word)n, (word)lb, d, - &simple_descr, &complex_descr, &leaf); + GC_ASSERT(GC_explicit_typing_initialized); + descr_type = GC_make_array_descriptor((word)n, (word)lb, d, &simple_descr, + &complex_descr, &leaf); + if ((lb | n) > GC_SQRT_SIZE_MAX /* fast initial check */ + && lb > 0 && n > GC_SIZE_MAX / lb) + return (*GC_get_oom_fn())(GC_SIZE_MAX); /* n*lb overflow */ + lb *= n; switch(descr_type) { case NO_MEM: return(0); - case SIMPLE: return(GC_malloc_explicitly_typed(n*lb, simple_descr)); + case SIMPLE: + return GC_malloc_explicitly_typed(lb, simple_descr); case LEAF: - lb *= n; - lb += sizeof(struct LeafDescriptor) + TYPD_EXTRA_BYTES; + lb = SIZET_SAT_ADD(lb, + sizeof(struct LeafDescriptor) + TYPD_EXTRA_BYTES); break; case COMPLEX: - lb *= n; - lb += TYPD_EXTRA_BYTES; + lb = SIZET_SAT_ADD(lb, TYPD_EXTRA_BYTES); break; } - if( SMALL_OBJ(lb) ) { - lg = GC_size_map[lb]; - LOCK(); - op = GC_arobjfreelist[lg]; - if (EXPECT(0 == op, FALSE)) { - UNLOCK(); - op = (ptr_t)GENERAL_MALLOC((word)lb, GC_array_kind); - if (0 == op) return(0); - lg = GC_size_map[lb]; /* May have been uninitialized. */ - } else { - GC_arobjfreelist[lg] = obj_link(op); - obj_link(op) = 0; - GC_bytes_allocd += GRANULES_TO_BYTES(lg); - UNLOCK(); + op = GC_malloc_kind(lb, GC_array_kind); + if (EXPECT(NULL == op, FALSE)) + return NULL; + lg = BYTES_TO_GRANULES(GC_size(op)); + if (descr_type == LEAF) { + /* Set up the descriptor inside the object itself. */ + volatile struct LeafDescriptor * lp = + (struct LeafDescriptor *) + (op + GRANULES_TO_WORDS(lg) + - (BYTES_TO_WORDS(sizeof(struct LeafDescriptor)) + 1)); + + lp -> ld_tag = LEAF_TAG; + lp -> ld_size = leaf.ld_size; + lp -> ld_nelements = leaf.ld_nelements; + lp -> ld_descriptor = leaf.ld_descriptor; + ((volatile word *)op)[GRANULES_TO_WORDS(lg) - 1] = (word)lp; + } else { +# ifndef GC_NO_FINALIZATION + size_t lw = GRANULES_TO_WORDS(lg); + + op[lw - 1] = (word)complex_descr; + GC_dirty(op + lw - 1); + REACHABLE_AFTER_DIRTY(complex_descr); + + /* Make sure the descriptor is cleared once there is any danger */ + /* it may have been collected. */ + if (EXPECT(GC_general_register_disappearing_link( + (void **)(op + lw - 1), op) + == GC_NO_MEMORY, FALSE)) +# endif + { + /* Couldn't register it due to lack of memory. Punt. */ + return (*GC_get_oom_fn())(lb); } - } else { - op = (ptr_t)GENERAL_MALLOC((word)lb, GC_array_kind); - if (0 == op) return(0); - lg = BYTES_TO_GRANULES(GC_size(op)); - } - if (descr_type == LEAF) { - /* Set up the descriptor inside the object itself. */ - volatile struct LeafDescriptor * lp = - (struct LeafDescriptor *) - ((word *)op - + GRANULES_TO_WORDS(lg) - - (BYTES_TO_WORDS(sizeof(struct LeafDescriptor)) + 1)); - - lp -> ld_tag = LEAF_TAG; - lp -> ld_size = leaf.ld_size; - lp -> ld_nelements = leaf.ld_nelements; - lp -> ld_descriptor = leaf.ld_descriptor; - ((volatile word *)op)[GRANULES_TO_WORDS(lg) - 1] = (word)lp; - } else { -# ifndef GC_NO_FINALIZATION - size_t lw = GRANULES_TO_WORDS(lg); - - ((word *)op)[lw - 1] = (word)complex_descr; - /* Make sure the descriptor is cleared once there is any danger */ - /* it may have been collected. */ - if (GC_general_register_disappearing_link((void * *)((word *)op+lw-1), - op) == GC_NO_MEMORY) -# endif - { - /* Couldn't register it due to lack of memory. Punt. */ - /* This will probably fail too, but gives the recovery code */ - /* a chance. */ - return(GC_malloc(n*lb)); - } - } - return((void *) op); + } + return op; } diff --git a/src/bdwgc/win32_threads.c b/src/bdwgc/win32_threads.c index 31d33b65c..3d2fe13ff 100644 --- a/src/bdwgc/win32_threads.c +++ b/src/bdwgc/win32_threads.c @@ -158,6 +158,8 @@ GC_API void GC_CALL GC_use_threads_discovery(void) # else /* Turn on GC_win32_dll_threads. */ GC_ASSERT(!parallel_initialized); + /* Note that GC_use_threads_discovery is expected to be called by */ + /* the client application (not from DllMain) at start-up. */ # ifndef GC_DISCOVER_TASK_THREADS GC_win32_dll_threads = TRUE; # endif @@ -272,7 +274,7 @@ typedef volatile struct GC_Thread_Rep * GC_vthread; STATIC volatile AO_t GC_attached_thread = FALSE; #endif -#if !defined(__GNUC__) +#if defined(WRAP_MARK_SOME) && !defined(GC_PTHREADS) /* Return TRUE if an thread was attached since we last asked or */ /* since GC_attached_thread was explicitly reset. */ GC_INNER GC_bool GC_started_thread_while_stopped(void) @@ -294,7 +296,7 @@ typedef volatile struct GC_Thread_Rep * GC_vthread; # endif return FALSE; } -#endif /* !__GNUC__ */ +#endif /* WRAP_MARK_SOME */ /* Thread table used if GC_win32_dll_threads is set. */ /* This is a fixed size array. */ @@ -318,7 +320,8 @@ STATIC volatile LONG GC_max_thread_index = 0; #ifndef THREAD_TABLE_SZ # define THREAD_TABLE_SZ 256 /* Power of 2 (for speed). */ #endif -#define THREAD_TABLE_INDEX(id) (((word)(id) >> 2) % THREAD_TABLE_SZ) +#define THREAD_TABLE_INDEX(id) /* id is of DWORD type */ \ + (int)((((id) >> 8) ^ (id)) % THREAD_TABLE_SZ) STATIC GC_thread GC_threads[THREAD_TABLE_SZ]; /* It may not be safe to allocate when we register the first thread. */ @@ -332,7 +335,7 @@ static GC_bool first_thread_used = FALSE; /* Unlike the pthreads version, the id field is set by the caller. */ STATIC GC_thread GC_new_thread(DWORD id) { - word hv = THREAD_TABLE_INDEX(id); + int hv = THREAD_TABLE_INDEX(id); GC_thread result; GC_ASSERT(I_HOLD_LOCK()); @@ -353,6 +356,8 @@ STATIC GC_thread GC_new_thread(DWORD id) GC_ASSERT(result -> flags == 0); # endif GC_ASSERT(result -> thread_blocked_sp == NULL); + if (EXPECT(result != &first_thread, TRUE)) + GC_dirty(result); return(result); } @@ -524,8 +529,7 @@ STATIC GC_thread GC_lookup_thread_inner(DWORD thread_id) } else # endif /* else */ { - word hv = THREAD_TABLE_INDEX(thread_id); - register GC_thread p = GC_threads[hv]; + GC_thread p = GC_threads[THREAD_TABLE_INDEX(thread_id)]; GC_ASSERT(I_HOLD_LOCK()); while (p != 0 && p -> id != thread_id) p = p -> tm.next; @@ -599,6 +603,14 @@ GC_API int GC_CALL GC_thread_is_registered(void) return me != NULL; } +GC_API void GC_CALL GC_register_altstack(void *stack GC_ATTR_UNUSED, + GC_word stack_size GC_ATTR_UNUSED, + void *altstack GC_ATTR_UNUSED, + GC_word altstack_size GC_ATTR_UNUSED) +{ + /* TODO: Implement */ +} + /* Make sure thread descriptor t is not protected by the VDB */ /* implementation. */ /* Used to prevent write faults when the world is (partially) stopped, */ @@ -606,8 +618,7 @@ GC_API int GC_CALL GC_thread_is_registered(void) /* lock may be required for fault handling. */ #if defined(MPROTECT_VDB) # define UNPROTECT_THREAD(t) \ - if (!GC_win32_dll_threads && GC_dirty_maintained \ - && t != &first_thread) { \ + if (!GC_win32_dll_threads && GC_incremental && t != &first_thread) { \ GC_ASSERT(SMALL_OBJ(GC_size(t))); \ GC_remove_protection(HBLKPTR(t), 1, FALSE); \ } else (void)0 @@ -656,7 +667,7 @@ STATIC void GC_delete_gc_thread_no_free(GC_vthread t) /* else */ { DWORD id = ((GC_thread)t) -> id; /* Cast away volatile qualifier, since we have lock. */ - word hv = THREAD_TABLE_INDEX(id); + int hv = THREAD_TABLE_INDEX(id); register GC_thread p = GC_threads[hv]; register GC_thread prev = 0; @@ -669,6 +680,7 @@ STATIC void GC_delete_gc_thread_no_free(GC_vthread t) GC_threads[hv] = p -> tm.next; } else { prev -> tm.next = p -> tm.next; + GC_dirty(prev); } } } @@ -690,7 +702,7 @@ STATIC void GC_delete_thread(DWORD id) GC_delete_gc_thread_no_free(t); } } else { - word hv = THREAD_TABLE_INDEX(id); + int hv = THREAD_TABLE_INDEX(id); register GC_thread p = GC_threads[hv]; register GC_thread prev = 0; @@ -706,6 +718,7 @@ STATIC void GC_delete_thread(DWORD id) GC_threads[hv] = p -> tm.next; } else { prev -> tm.next = p -> tm.next; + GC_dirty(prev); } if (p != &first_thread) { GC_INTERNAL_FREE(p); @@ -717,13 +730,12 @@ GC_API void GC_CALL GC_allow_register_threads(void) { /* Check GC is initialized and the current thread is registered. */ GC_ASSERT(GC_lookup_thread_inner(GetCurrentThreadId()) != 0); -# ifndef GC_ALWAYS_MULTITHREADED -# if !defined(GC_NO_THREADS_DISCOVERY) && !defined(PARALLEL_MARK) +# if !defined(GC_ALWAYS_MULTITHREADED) && !defined(PARALLEL_MARK) \ + && !defined(GC_NO_THREADS_DISCOVERY) /* GC_init() does not call GC_init_parallel() in this case. */ - parallel_initialized = TRUE; -# endif - GC_need_to_lock = TRUE; /* We are multi-threaded now. */ + parallel_initialized = TRUE; # endif + set_need_to_lock(); } GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) @@ -867,6 +879,9 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context GC_ATTR_UNUSED) UNLOCK(); d -> client_data = (d -> fn)(d -> client_data); LOCK(); /* This will block if the world is stopped. */ +# if defined(CPPCHECK) + GC_noop1((word)me->thread_blocked_sp); +# endif me -> thread_blocked_sp = NULL; UNLOCK(); } @@ -921,6 +936,9 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn, /* Restore original "stack section". */ LOCK(); +# if defined(CPPCHECK) + GC_noop1((word)me->traced_stack_sect); +# endif me -> traced_stack_sect = stacksect.prev; # ifdef IA64 me -> backing_store_ptr = stacksect.saved_backing_store_ptr; @@ -972,7 +990,8 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn, /* else */ { /* We first try the cache. If that fails, we use a very slow */ /* approach. */ - word hv_guess = THREAD_TABLE_INDEX(GET_PTHREAD_MAP_CACHE(id)); + DWORD win32_id = GET_PTHREAD_MAP_CACHE(id); + int hv_guess = THREAD_TABLE_INDEX(win32_id); int hv; GC_thread p; DCL_LOCK_STATE; @@ -1011,15 +1030,16 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn, for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) { for (p = GC_threads[hv]; 0 != p; p = next) { next = p -> tm.next; - if (THREAD_EQUAL(p -> pthread_id, pthread_id)) { - GC_ASSERT(me == NULL); + if (THREAD_EQUAL(p -> pthread_id, pthread_id) + && me == NULL) { /* ignore dead threads with the same id */ me = p; p -> tm.next = 0; } else { # ifdef THREAD_LOCAL_ALLOC if ((p -> flags & FINISHED) == 0) { - GC_destroy_thread_local(&p->tlfs); - GC_remove_specific(GC_thread_key); + /* Cannot call GC_destroy_thread_local here (see the */ + /* corresponding comment in pthread_support.c). */ + GC_remove_specific_after_fork(GC_thread_key, p -> pthread_id); } # endif if (&first_thread != p) @@ -1094,6 +1114,7 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn, /* Routines for fork handling by client (no-op if pthread_atfork works). */ GC_API void GC_CALL GC_atfork_prepare(void) { + if (!EXPECT(GC_is_initialized, TRUE)) GC_init(); if (GC_handle_fork <= 0) fork_prepare_proc(); } @@ -1124,11 +1145,10 @@ void GC_push_thread_structures(void) } else # endif /* else */ { - GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads)); + GC_PUSH_ALL_SYM(GC_threads); } # if defined(THREAD_LOCAL_ALLOC) - GC_push_all((ptr_t)(&GC_thread_key), - (ptr_t)(&GC_thread_key) + sizeof(GC_thread_key)); + GC_PUSH_ALL_SYM(GC_thread_key); /* Just in case we ever use our own TLS implementation. */ # endif } @@ -1180,6 +1200,8 @@ STATIC void GC_suspend(GC_thread t) # if defined(MPROTECT_VDB) AO_CLEAR(&GC_fault_handler_lock); # endif + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, THREAD_HANDLE(t)); } #if defined(GC_ASSERTIONS) && !defined(CYGWIN32) @@ -1266,11 +1288,12 @@ GC_INNER void GC_start_world(void) # ifdef GC_ASSERTIONS DWORD thread_id = GetCurrentThreadId(); # endif - int i; GC_ASSERT(I_HOLD_LOCK()); if (GC_win32_dll_threads) { LONG my_max = GC_get_max_thread_index(); + int i; + for (i = 0; i <= my_max; i++) { GC_thread t = (GC_thread)(dll_thread_table + i); if (t -> suspended) { @@ -1278,6 +1301,8 @@ GC_INNER void GC_start_world(void) if (ResumeThread(THREAD_HANDLE(t)) == (DWORD)-1) ABORT("ResumeThread failed"); t -> suspended = FALSE; + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, THREAD_HANDLE(t)); } } } else { @@ -1292,6 +1317,8 @@ GC_INNER void GC_start_world(void) ABORT("ResumeThread failed"); UNPROTECT_THREAD(t); t -> suspended = FALSE; + if (GC_on_thread_event) + GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, THREAD_HANDLE(t)); } } } @@ -1410,7 +1437,7 @@ STATIC word GC_push_stack_for(GC_thread thread, DWORD me) PUSH4(IntA0,IntA1,IntA2,IntA3), PUSH4(IntA4,IntA5,IntT8,IntT9); PUSH4(IntT10,IntT11,IntT12,IntAt); sp = (ptr_t)context.IntSp; -# else +# elif !defined(CPPCHECK) # error "architecture is not supported" # endif } /* ! current thread */ @@ -1474,7 +1501,8 @@ STATIC word GC_push_stack_for(GC_thread thread, DWORD me) if ((word)sp >= (word)stack_min && (word)sp < (word)thread->stack_base) { # ifdef DEBUG_THREADS GC_log_printf("Pushing stack for 0x%x from sp %p to %p from 0x%x\n", - (int)thread -> id, sp, thread -> stack_base, (int)me); + (int)thread->id, (void *)sp, (void *)thread->stack_base, + (int)me); # endif GC_push_all_stack_sections(sp, thread->stack_base, traced_stack_sect); } else { @@ -1487,7 +1515,8 @@ STATIC word GC_push_stack_for(GC_thread thread, DWORD me) sp); # ifdef DEBUG_THREADS GC_log_printf("Pushing stack for 0x%x from (min) %p to %p from 0x%x\n", - (int)thread->id, stack_min, thread->stack_base, (int)me); + (int)thread->id, (void *)stack_min, + (void *)thread->stack_base, (int)me); # endif /* Push everything - ignore "traced stack section" data. */ GC_push_all_stack(stack_min, thread->stack_base); @@ -1593,6 +1622,10 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, plast_stack_min = (ptr_t * /* no volatile */) &dll_thread_table[i].last_stack_min; current_min = s; +# if defined(CPPCHECK) + /* To avoid a warning that thread is always null. */ + thread = (GC_thread)&dll_thread_table[i]; +# endif } } } else { @@ -1671,7 +1704,12 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, # if defined(GC_PTHREADS) && !defined(GC_PTHREADS_PARAMARK) /* Use pthread-based parallel mark implementation. */ -# define GC_PTHREADS_PARAMARK + + /* Workaround a deadlock in winpthreads-3.0b internals (observed */ + /* with MinGW 32/64). */ +# if !defined(__MINGW32__) +# define GC_PTHREADS_PARAMARK +# endif # endif # if !defined(GC_PTHREADS_PARAMARK) @@ -1689,12 +1727,10 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, /* GC_mark_thread() is the same as in pthread_support.c */ # ifdef GC_PTHREADS_PARAMARK STATIC void * GC_mark_thread(void * id) +# elif defined(MSWINCE) + STATIC DWORD WINAPI GC_mark_thread(LPVOID id) # else -# ifdef MSWINCE - STATIC DWORD WINAPI GC_mark_thread(LPVOID id) -# else - STATIC unsigned __stdcall GC_mark_thread(void * id) -# endif + STATIC unsigned __stdcall GC_mark_thread(void * id) # endif { word my_mark_no = 0; @@ -1708,6 +1744,11 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, GC_marker_Id[(word)id] = GetCurrentThreadId(); # endif + /* Inform GC_start_mark_threads about completion of marker data init. */ + GC_acquire_mark_lock(); + if (0 == --GC_fl_builder_count) /* count may have a negative value */ + GC_notify_all_builder(); + for (;; ++my_mark_no) { if (my_mark_no - GC_mark_no > (word)2) { /* resynchronize if we get far off, e.g. because GC_mark_no */ @@ -1729,54 +1770,96 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, /* GC_mark_threads[] is unused here unlike that in pthread_support.c */ -# ifndef CAN_HANDLE_FORK +# ifdef CAN_HANDLE_FORK + static int available_markers_m1 = 0; +# else # define available_markers_m1 GC_markers_m1 # endif # ifdef GC_PTHREADS_PARAMARK # include -# ifndef NUMERIC_THREAD_ID -# define NUMERIC_THREAD_ID(id) (unsigned long)GC_PTHREAD_PTRVAL(id) +# if defined(GC_ASSERTIONS) && !defined(NUMERIC_THREAD_ID) +# define NUMERIC_THREAD_ID(id) (unsigned long)(word)GC_PTHREAD_PTRVAL(id) /* Id not guaranteed to be unique. */ # endif - /* start_mark_threads is the same as in pthread_support.c except */ - /* for thread stack that is assumed to be large enough. */ # ifdef CAN_HANDLE_FORK - static int available_markers_m1 = 0; -# define start_mark_threads GC_start_mark_threads - GC_API void GC_CALL + static pthread_cond_t mark_cv; + /* initialized by GC_start_mark_threads_inner */ # else - static void + static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER; # endif - start_mark_threads(void) + + /* GC_start_mark_threads is the same as in pthread_support.c except */ + /* for thread stack that is assumed to be large enough. */ + + GC_INNER void GC_start_mark_threads_inner(void) { int i; pthread_attr_t attr; pthread_t new_thread; - - GC_ASSERT(I_DONT_HOLD_LOCK()); -# ifdef CAN_HANDLE_FORK - if (available_markers_m1 <= 0 || GC_parallel) return; - /* Skip if parallel markers disabled or already started. */ +# ifndef NO_MARKER_SPECIAL_SIGMASK + sigset_t set, oldset; # endif + GC_ASSERT(I_DONT_HOLD_LOCK()); + if (available_markers_m1 <= 0) return; + /* Skip if parallel markers disabled or already started. */ +# ifdef CAN_HANDLE_FORK + if (GC_parallel) return; + + /* Reset mark_cv state after forking (as in pthread_support.c). */ + { + pthread_cond_t mark_cv_local = PTHREAD_COND_INITIALIZER; + BCOPY(&mark_cv_local, &mark_cv, sizeof(mark_cv)); + } +# endif + + GC_ASSERT(GC_fl_builder_count == 0); if (0 != pthread_attr_init(&attr)) ABORT("pthread_attr_init failed"); if (0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) ABORT("pthread_attr_setdetachstate failed"); +# ifndef NO_MARKER_SPECIAL_SIGMASK + /* Apply special signal mask to GC marker threads, and don't drop */ + /* user defined signals by GC marker threads. */ + if (sigfillset(&set) != 0) + ABORT("sigfillset failed"); + if (pthread_sigmask(SIG_BLOCK, &set, &oldset) < 0) { + WARN("pthread_sigmask set failed, no markers started," + " errno = %" WARN_PRIdPTR "\n", errno); + GC_markers_m1 = 0; + (void)pthread_attr_destroy(&attr); + return; + } +# endif /* !NO_MARKER_SPECIAL_SIGMASK */ + +# ifdef CAN_HANDLE_FORK + /* To have proper GC_parallel value in GC_help_marker. */ + GC_markers_m1 = available_markers_m1; +# endif for (i = 0; i < available_markers_m1; ++i) { marker_last_stack_min[i] = ADDR_LIMIT; if (0 != pthread_create(&new_thread, &attr, GC_mark_thread, (void *)(word)i)) { - WARN("Marker thread creation failed.\n", 0); + WARN("Marker thread creation failed\n", 0); /* Don't try to create other marker threads. */ + GC_markers_m1 = i; break; } } - GC_markers_m1 = i; + +# ifndef NO_MARKER_SPECIAL_SIGMASK + /* Restore previous signal mask. */ + if (pthread_sigmask(SIG_SETMASK, &oldset, NULL) < 0) { + WARN("pthread_sigmask restore failed, errno = %" WARN_PRIdPTR "\n", + errno); + } +# endif + (void)pthread_attr_destroy(&attr); + GC_wait_for_markers_init(); GC_COND_LOG_PRINTF("Started %d mark helper threads\n", GC_markers_m1); } @@ -1859,10 +1942,9 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, } } - static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER; - GC_INNER void GC_wait_marker(void) { + GC_ASSERT(GC_parallel); UNSET_MARK_LOCK_HOLDER; if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) { ABORT("pthread_cond_wait failed"); @@ -1873,6 +1955,7 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, GC_INNER void GC_notify_all_marker(void) { + GC_ASSERT(GC_parallel); if (pthread_cond_broadcast(&mark_cv) != 0) { ABORT("pthread_cond_broadcast failed"); } @@ -1889,17 +1972,14 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, static HANDLE builder_cv = (HANDLE)0; /* Event with manual reset. */ static HANDLE mark_cv = (HANDLE)0; /* Event with manual reset. */ - static void start_mark_threads(void) + GC_INNER void GC_start_mark_threads_inner(void) { int i; -# ifdef MSWINCE - HANDLE handle; - DWORD thread_id; -# else - GC_uintptr_t handle; - unsigned thread_id; -# endif + GC_ASSERT(I_DONT_HOLD_LOCK()); + if (available_markers_m1 <= 0) return; + + GC_ASSERT(GC_fl_builder_count == 0); /* Initialize GC_marker_cv[] fully before starting the */ /* first helper thread. */ for (i = 0; i < GC_markers_m1; ++i) { @@ -1911,8 +1991,11 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, } for (i = 0; i < GC_markers_m1; ++i) { - marker_last_stack_min[i] = ADDR_LIMIT; # ifdef MSWINCE + HANDLE handle; + DWORD thread_id; + + marker_last_stack_min[i] = ADDR_LIMIT; /* There is no _beginthreadex() in WinCE. */ handle = CreateThread(NULL /* lpsa */, MARK_THREAD_STACK_SIZE /* ignored */, @@ -1928,6 +2011,10 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, CloseHandle(handle); } # else + GC_uintptr_t handle; + unsigned thread_id; + + marker_last_stack_min[i] = ADDR_LIMIT; handle = _beginthreadex(NULL /* security_attr */, MARK_THREAD_STACK_SIZE, GC_mark_thread, (void *)(word)i, 0 /* flags */, &thread_id); @@ -1946,6 +2033,7 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, GC_markers_m1--; CloseHandle(GC_marker_cv[GC_markers_m1]); } + GC_wait_for_markers_init(); GC_COND_LOG_PRINTF("Started %d mark helper threads\n", GC_markers_m1); if (i == 0) { CloseHandle(mark_cv); @@ -2110,6 +2198,7 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, /* This is probably pointless, since an uncaught exception is */ /* supposed to result in the process being killed. */ # ifndef __GNUC__ + ret = NULL; /* to suppress "might be uninitialized" compiler warning */ __try # endif { @@ -2141,9 +2230,6 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) { - HANDLE thread_h; - thread_args *args; - if (!EXPECT(parallel_initialized, TRUE)) GC_init_parallel(); /* make sure GC is initialized (i.e. main thread is */ @@ -2157,8 +2243,10 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, return CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId); } else { - args = GC_malloc_uncollectable(sizeof(thread_args)); + thread_args *args = GC_malloc_uncollectable(sizeof(thread_args)); /* Handed off to and deallocated by child thread. */ + HANDLE thread_h; + if (0 == args) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; @@ -2167,10 +2255,10 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, /* set up thread arguments */ args -> start = lpStartAddress; args -> param = lpParameter; + GC_dirty(args); + REACHABLE_AFTER_DIRTY(lpParameter); -# ifndef GC_ALWAYS_MULTITHREADED - GC_need_to_lock = TRUE; -# endif + set_need_to_lock(); thread_h = CreateThread(lpThreadAttributes, dwStackSize, GC_win32_start, args, dwCreationFlags, lpThreadId); if (thread_h == 0) GC_free(args); @@ -2192,9 +2280,6 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, void *arglist, unsigned initflag, unsigned *thrdaddr) { - GC_uintptr_t thread_h; - thread_args *args; - if (!EXPECT(parallel_initialized, TRUE)) GC_init_parallel(); /* make sure GC is initialized (i.e. main thread is */ @@ -2208,8 +2293,10 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, return _beginthreadex(security, stack_size, start_address, arglist, initflag, thrdaddr); } else { - args = GC_malloc_uncollectable(sizeof(thread_args)); + GC_uintptr_t thread_h; + thread_args *args = GC_malloc_uncollectable(sizeof(thread_args)); /* Handed off to and deallocated by child thread. */ + if (0 == args) { /* MSDN docs say _beginthreadex() returns 0 on error and sets */ /* errno to either EAGAIN (too many threads) or EINVAL (the */ @@ -2222,10 +2309,10 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, /* set up thread arguments */ args -> start = (LPTHREAD_START_ROUTINE)start_address; args -> param = arglist; + GC_dirty(args); + REACHABLE_AFTER_DIRTY(arglist); -# ifndef GC_ALWAYS_MULTITHREADED - GC_need_to_lock = TRUE; -# endif + set_need_to_lock(); thread_h = _beginthreadex(security, stack_size, (unsigned (__stdcall *)(void *))GC_win32_start, args, initflag, thrdaddr); @@ -2319,7 +2406,6 @@ GC_INNER void GC_get_next_stack(char *start, char *limit, #endif /* GC_WINMAIN_REDIRECT */ -/* Called by GC_init() - we hold the allocation lock. */ GC_INNER void GC_thr_init(void) { struct GC_stack_base sb; @@ -2359,19 +2445,20 @@ GC_INNER void GC_thr_init(void) # if defined(PARALLEL_MARK) { char * markers_string = GETENV("GC_MARKERS"); - int markers_m1; + int markers; if (markers_string != NULL) { - markers_m1 = atoi(markers_string) - 1; - if (markers_m1 >= MAX_MARKERS) { - WARN("Limiting number of mark threads\n", 0); - markers_m1 = MAX_MARKERS - 1; + markers = atoi(markers_string); + if (markers <= 0 || markers > MAX_MARKERS) { + WARN("Too big or invalid number of mark threads: %" WARN_PRIdPTR + "; using maximum threads\n", (signed_word)markers); + markers = MAX_MARKERS; } } else { # ifdef MSWINCE /* There is no GetProcessAffinityMask() in WinCE. */ /* GC_sysinfo is already initialized. */ - markers_m1 = (int)GC_sysinfo.dwNumberOfProcessors - 1; + markers = (int)GC_sysinfo.dwNumberOfProcessors; # else # ifdef _WIN64 DWORD_PTR procMask = 0; @@ -2388,17 +2475,17 @@ GC_INNER void GC_thr_init(void) ncpu++; } while ((procMask &= procMask - 1) != 0); } - markers_m1 = ncpu - 1; + markers = ncpu; # endif -# ifdef GC_MIN_MARKERS +# if defined(GC_MIN_MARKERS) && !defined(CPPCHECK) /* This is primarily for testing on systems without getenv(). */ - if (markers_m1 < GC_MIN_MARKERS - 1) - markers_m1 = GC_MIN_MARKERS - 1; + if (markers < GC_MIN_MARKERS) + markers = GC_MIN_MARKERS; # endif - if (markers_m1 >= MAX_MARKERS) - markers_m1 = MAX_MARKERS - 1; /* silently limit the value */ + if (markers > MAX_MARKERS) + markers = MAX_MARKERS; /* silently limit the value */ } - available_markers_m1 = markers_m1; + available_markers_m1 = markers - 1; } /* Check whether parallel mode could be enabled. */ @@ -2431,16 +2518,6 @@ GC_INNER void GC_thr_init(void) GC_ASSERT(0 == GC_lookup_thread_inner(GC_main_thread)); GC_register_my_thread_inner(&sb, GC_main_thread); - -# ifdef PARALLEL_MARK -# ifndef CAN_HANDLE_FORK - if (GC_parallel) -# endif - { - /* If we are using a parallel marker, actually start helper threads. */ - start_mark_threads(); - } -# endif } #ifdef GC_PTHREADS @@ -2454,14 +2531,17 @@ GC_INNER void GC_thr_init(void) GC_API int GC_pthread_join(pthread_t pthread_id, void **retval) { int result; - GC_thread t; +# ifndef GC_WIN32_PTHREADS + GC_thread t; +# endif DCL_LOCK_STATE; GC_ASSERT(!GC_win32_dll_threads); # ifdef DEBUG_THREADS GC_log_printf("thread %p(0x%lx) is joining thread %p\n", - GC_PTHREAD_PTRVAL(pthread_self()), - (long)GetCurrentThreadId(), GC_PTHREAD_PTRVAL(pthread_id)); + (void *)GC_PTHREAD_PTRVAL(pthread_self()), + (long)GetCurrentThreadId(), + (void *)GC_PTHREAD_PTRVAL(pthread_id)); # endif /* Thread being joined might not have registered itself yet. */ @@ -2471,29 +2551,35 @@ GC_INNER void GC_thr_init(void) # ifndef GC_WIN32_PTHREADS while ((t = GC_lookup_pthread(pthread_id)) == 0) Sleep(10); - result = pthread_join(pthread_id, retval); -# else - result = pthread_join(pthread_id, retval); - /* pthreads-win32 and winpthreads id are unique (not recycled). */ - t = GC_lookup_pthread(pthread_id); - if (NULL == t) ABORT("Thread not registered"); # endif + result = pthread_join(pthread_id, retval); + if (0 == result) { +# ifdef GC_WIN32_PTHREADS + /* pthreads-win32 and winpthreads id are unique (not recycled). */ + GC_thread t = GC_lookup_pthread(pthread_id); + if (NULL == t) ABORT("Thread not registered"); +# endif - LOCK(); - GC_delete_gc_thread_no_free(t); - GC_INTERNAL_FREE(t); - UNLOCK(); + LOCK(); + if ((t -> flags & FINISHED) != 0) { + GC_delete_gc_thread_no_free(t); + GC_INTERNAL_FREE(t); + } + UNLOCK(); + } # ifdef DEBUG_THREADS - GC_log_printf("thread %p(0x%lx) completed join with thread %p\n", - GC_PTHREAD_PTRVAL(pthread_self()), - (long)GetCurrentThreadId(), GC_PTHREAD_PTRVAL(pthread_id)); + GC_log_printf("thread %p(0x%lx) join with thread %p %s\n", + (void *)GC_PTHREAD_PTRVAL(pthread_self()), + (long)GetCurrentThreadId(), + (void *)GC_PTHREAD_PTRVAL(pthread_id), + result != 0 ? "failed" : "succeeded"); # endif return result; } /* Cygwin-pthreads calls CreateThread internally, but it's not easily */ - /* interceptible by us..., so intercept pthread_create instead. */ + /* interceptable by us..., so intercept pthread_create instead. */ GC_API int GC_pthread_create(pthread_t *new_thread, GC_PTHREAD_CREATE_CONST pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) @@ -2513,6 +2599,8 @@ GC_INNER void GC_thr_init(void) si -> start_routine = start_routine; si -> arg = arg; + GC_dirty(si); + REACHABLE_AFTER_DIRTY(arg); if (attr != 0 && pthread_attr_getdetachstate(attr, &si->detached) == PTHREAD_CREATE_DETACHED) { @@ -2521,12 +2609,10 @@ GC_INNER void GC_thr_init(void) # ifdef DEBUG_THREADS GC_log_printf("About to create a thread from %p(0x%lx)\n", - GC_PTHREAD_PTRVAL(pthread_self()), + (void *)GC_PTHREAD_PTRVAL(pthread_self()), (long)GetCurrentThreadId()); # endif -# ifndef GC_ALWAYS_MULTITHREADED - GC_need_to_lock = TRUE; -# endif + set_need_to_lock(); result = pthread_create(new_thread, attr, GC_pthread_start, si); if (result) { /* failure */ @@ -2549,7 +2635,7 @@ GC_INNER void GC_thr_init(void) # ifdef DEBUG_THREADS GC_log_printf("thread %p(0x%x) starting...\n", - GC_PTHREAD_PTRVAL(pthread_id), (int)thread_id); + (void *)GC_PTHREAD_PTRVAL(pthread_id), (int)thread_id); # endif GC_ASSERT(!GC_win32_dll_threads); @@ -2574,11 +2660,12 @@ GC_INNER void GC_thr_init(void) pthread_cleanup_push(GC_thread_exit_proc, (void *)me); result = (*start)(start_arg); me -> status = result; + GC_dirty(me); pthread_cleanup_pop(1); # ifdef DEBUG_THREADS GC_log_printf("thread %p(0x%x) returned from start routine\n", - GC_PTHREAD_PTRVAL(pthread_id), (int)thread_id); + (void *)GC_PTHREAD_PTRVAL(pthread_id), (int)thread_id); # endif return(result); } @@ -2596,7 +2683,7 @@ GC_INNER void GC_thr_init(void) GC_ASSERT(!GC_win32_dll_threads); # ifdef DEBUG_THREADS GC_log_printf("thread %p(0x%lx) called pthread_exit()\n", - GC_PTHREAD_PTRVAL(pthread_self()), + (void *)GC_PTHREAD_PTRVAL(pthread_self()), (long)GetCurrentThreadId()); # endif @@ -2636,12 +2723,12 @@ GC_INNER void GC_thr_init(void) DCL_LOCK_STATE; GC_ASSERT(!GC_win32_dll_threads); - LOCK(); - t = GC_lookup_pthread(thread); - UNLOCK(); + /* The thread might not have registered itself yet. */ + /* TODO: Wait for registration of the created thread in pthread_create. */ + while ((t = GC_lookup_pthread(thread)) == NULL) + Sleep(10); result = pthread_detach(thread); if (result == 0) { - if (NULL == t) ABORT("Thread not registered"); LOCK(); t -> flags |= DETACHED; /* Here the pthread thread id may have been recycled. */ @@ -2672,8 +2759,12 @@ GC_INNER void GC_thr_init(void) LPVOID reserved GC_ATTR_UNUSED) { DWORD thread_id; - static int entry_count = 0; + /* Note that GC_use_threads_discovery should be called by the */ + /* client application at start-up to activate automatic thread */ + /* registration (it is the default GC behavior since v7.0alpha7); */ + /* to always have automatic thread registration turned on, the GC */ + /* should be compiled with -D GC_DISCOVER_TASK_THREADS. */ if (!GC_win32_dll_threads && parallel_initialized) return TRUE; switch (reason) { @@ -2685,8 +2776,7 @@ GC_INNER void GC_thr_init(void) break; } # endif - GC_ASSERT(entry_count == 0 || parallel_initialized); - ++entry_count; /* and fall through: */ + /* FALLTHRU */ case DLL_PROCESS_ATTACH: /* This may run with the collector uninitialized. */ thread_id = GetCurrentThreadId(); @@ -2748,15 +2838,16 @@ GC_INNER void GC_init_parallel(void) /* GC_init() calls us back, so set flag first. */ if (!GC_is_initialized) GC_init(); -# ifndef GC_ALWAYS_MULTITHREADED - if (GC_win32_dll_threads) { - GC_need_to_lock = TRUE; +# if defined(CPPCHECK) && !defined(GC_NO_THREADS_DISCOVERY) + GC_noop1((word)&GC_DllMain); +# endif + if (GC_win32_dll_threads) { + set_need_to_lock(); /* Cannot intercept thread creation. Hence we don't know if */ /* other threads exist. However, client is not allowed to */ /* create other threads before collector initialization. */ /* Thus it's OK not to lock before this. */ - } -# endif + } /* Initialize thread local free lists if used. */ # if defined(THREAD_LOCAL_ALLOC) LOCK(); @@ -2769,14 +2860,9 @@ GC_INNER void GC_init_parallel(void) #if defined(USE_PTHREAD_LOCKS) /* Support for pthread locking code. */ - /* Pthread_mutex_try_lock may not win here, */ + /* pthread_mutex_trylock may not win here, */ /* due to builtin support for spinning first? */ - GC_INNER volatile GC_bool GC_collecting = 0; - /* A hint that we're in the collector and */ - /* holding the allocation lock for an */ - /* extended period. */ - GC_INNER void GC_lock(void) { pthread_mutex_lock(&GC_allocate_ml); diff --git a/src/bdwgc/windows-untested/README b/src/bdwgc/windows-untested/README deleted file mode 100644 index 0de3ce74f..000000000 --- a/src/bdwgc/windows-untested/README +++ /dev/null @@ -1,4 +0,0 @@ -gc.def should probably be removed completely. - -I removed an apparently erroneous line for GC_CreateThread. Unfortunately -gc.def is referenced in various other places I cannot easily edit. -HB diff --git a/src/bdwgc/windows-untested/gc.def b/src/bdwgc/windows-untested/gc.def deleted file mode 100644 index 2853518fe..000000000 --- a/src/bdwgc/windows-untested/gc.def +++ /dev/null @@ -1,2 +0,0 @@ -EXPORTS - GC_version DATA diff --git a/src/bdwgc/windows-untested/gc.rc b/src/bdwgc/windows-untested/gc.rc deleted file mode 100644 index 7de7af497..000000000 --- a/src/bdwgc/windows-untested/gc.rc +++ /dev/null @@ -1 +0,0 @@ -#include "gc.ver" diff --git a/src/bdwgc/windows-untested/gc.ver b/src/bdwgc/windows-untested/gc.ver deleted file mode 100644 index 97920a27c..000000000 --- a/src/bdwgc/windows-untested/gc.ver +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "../include/../version.h" - -#define GC_VERSION_REVISION 0 - -#define GC_VERSION ((GC_VERSION_MAJOR) * 100 + GC_VERSION_MINOR) -#define GC_FULL_VERSION ((GC_VERSION) * 10000 + GC_VERSION_MICRO) - -#ifndef __T -# ifdef UNICODE -# define __T(x) L ## x -# else -# define __T(x) x -# endif -#endif - -#define PP_TSTR(x) __T(#x) -#define PP_EVAL_TSTR(x) PP_TSTR(x) - -#define GC_VERSION_STR PP_EVAL_TSTR(GC_VERSION_MAJOR) __T(".") PP_EVAL_TSTR(GC_VERSION_MINOR) -#define GC_FULL_VERSION_STR PP_EVAL_TSTR(GC_VERSION_MAJOR) __T(".") PP_EVAL_TSTR(GC_VERSION_MINOR) __T(".") PP_EVAL_TSTR(GC_VERSION_MICRO) __T(".") PP_EVAL_TSTR(GC_VERSION_REVISION) -#define GC_FULL_VERSION_CSV GC_VERSION_MAJOR, GC_VERSION_MINOR, GC_VERSION_MICRO, GC_VERSION_REVISION - -#ifdef _DEBUG -#define VER_DEBUG VS_FF_DEBUG -#else -#define VER_DEBUG 0 -#endif - -#ifdef _BETA -#define VER_PRERELEASE VS_FF_PRERELEASE -#else -#define VER_PRERELEASE 0 -#endif - -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) - -VS_VERSION_INFO VERSIONINFO - FILEVERSION GC_FULL_VERSION_CSV - PRODUCTVERSION GC_FULL_VERSION_CSV - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS VER_DEBUG | VER_PRERELEASE - FILEOS VOS__WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE VFT2_UNKNOWN -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "\ -Hans-J. Boehm, \ -Alan J. Demers, \ -Xerox Corporation, \ -Silicon Graphics, \ -and Hewlett-Packard Company. \ -\0" - VALUE "LegalCopyright", "\ -Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers. \ -Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. \ -Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. \ -Copyright (c) 1999-2004 by Hewlett-Packard. All rights reserved. \ -\0" - - VALUE "OriginalFilename", "GC.DLL\0" - VALUE "InternalName", "GC\0" - VALUE "FileDescription", "Conservative Garbage Collector for C and C++\0" - VALUE "FileVersion", GC_FULL_VERSION_STR - - VALUE "ProductName", "Conservative Garbage Collector for C and C++\0" - VALUE "ProductVersion", GC_FULL_VERSION_STR - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END diff --git a/src/bdwgc/windows-untested/stdafx.c b/src/bdwgc/windows-untested/stdafx.c deleted file mode 100644 index fd4f341c7..000000000 --- a/src/bdwgc/windows-untested/stdafx.c +++ /dev/null @@ -1 +0,0 @@ -#include "stdafx.h" diff --git a/src/bdwgc/windows-untested/stdafx.h b/src/bdwgc/windows-untested/stdafx.h deleted file mode 100644 index 7f5dcf1c3..000000000 --- a/src/bdwgc/windows-untested/stdafx.h +++ /dev/null @@ -1,15 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include - -#pragma warning(error: 4013) // function undefined; assuming extern returning int - -#ifdef _MT -# define GC_THREADS 1 -#endif - -#ifdef _DEBUG -# define GC_DEBUG -#endif - -#define SAVE_CALL_CHAIN -#define SAVE_CALL_COUNT 8 diff --git a/src/bdwgc/windows-untested/vc60/all.dsp b/src/bdwgc/windows-untested/vc60/all.dsp deleted file mode 100644 index b195df6d6..000000000 --- a/src/bdwgc/windows-untested/vc60/all.dsp +++ /dev/null @@ -1,63 +0,0 @@ -# Microsoft Developer Studio Project File - Name="all" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Generic Project" 0x010a - -CFG=all - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "all.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "all.mak" CFG="all - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "all - Win32 Release" (based on "Win32 (x86) Generic Project") -!MESSAGE "all - Win32 Debug" (based on "Win32 (x86) Generic Project") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -MTL=midl.exe - -!IF "$(CFG)" == "all - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Release" -# PROP Target_Dir "" - -!ELSEIF "$(CFG)" == "all - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Debug" -# PROP Target_Dir "" - -!ENDIF - -# Begin Target - -# Name "all - Win32 Release" -# Name "all - Win32 Debug" -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/gc.dsp b/src/bdwgc/windows-untested/vc60/gc.dsp deleted file mode 100644 index 762a22203..000000000 --- a/src/bdwgc/windows-untested/vc60/gc.dsp +++ /dev/null @@ -1,332 +0,0 @@ -# Microsoft Developer Studio Project File - Name="gc" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=gc - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "gc.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "gc.mak" CFG="gc - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "gc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "gc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "gc - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Release\gc" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GC_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "..\..\include" /FI"stdafx.h" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "GC_DLL" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /Yu"stdafx.h" /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /i "..\..\include" /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x37C30000" /subsystem:console /dll /debug /machine:I386 /out:"..\..\..\bin/gc60.dll" /implib:"..\..\..\lib/gc.lib" /opt:ref /release -# SUBTRACT LINK32 /pdb:none -# Begin Special Build Tool -OutDir=.\..\..\..\bin -SOURCE="$(InputPath)" -PostBuild_Cmds=del $(OutDir)\..\lib\gc.exp -# End Special Build Tool - -!ELSEIF "$(CFG)" == "gc - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Debug\gc" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GC_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /FI"stdafx.h" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "GC_DLL" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /Yu"stdafx.h" /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /i "..\..\include" /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\..\bin/gcd.bsc" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /base:"0x37C30000" /subsystem:console /dll /incremental:no /debug /machine:I386 /out:"..\..\..\bin/gc60d.dll" /implib:"..\..\..\lib/gcd.lib" /pdbtype:sept -# SUBTRACT LINK32 /pdb:none -# Begin Special Build Tool -OutDir=.\..\..\..\bin -SOURCE="$(InputPath)" -PostBuild_Cmds=del $(OutDir)\..\lib\gcd.exp -# End Special Build Tool - -!ENDIF - -# Begin Target - -# Name "gc - Win32 Release" -# Name "gc - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "c;cpp;cc;cxx;tcc;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\allchblk.c -# End Source File -# Begin Source File - -SOURCE=..\..\alloc.c -# End Source File -# Begin Source File - -SOURCE=..\..\backgraph.c -# End Source File -# Begin Source File - -SOURCE=..\..\blacklst.c -# End Source File -# Begin Source File - -SOURCE=..\..\checksums.c -# End Source File -# Begin Source File - -SOURCE=..\..\dbg_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\gcj_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\fnlz_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\dyn_load.c -# End Source File -# Begin Source File - -SOURCE=..\..\finalize.c -# End Source File -# Begin Source File - -SOURCE=..\..\headers.c -# End Source File -# Begin Source File - -SOURCE=..\..\mach_dep.c -# End Source File -# Begin Source File - -SOURCE=..\..\malloc.c -# End Source File -# Begin Source File - -SOURCE=..\..\mallocx.c -# End Source File -# Begin Source File - -SOURCE=..\..\mark.c -# End Source File -# Begin Source File - -SOURCE=..\..\mark_rts.c -# End Source File -# Begin Source File - -SOURCE=..\..\misc.c -# End Source File -# Begin Source File - -SOURCE=..\..\msvc_dbg.c -# End Source File -# Begin Source File - -SOURCE=..\..\new_hblk.c -# End Source File -# Begin Source File - -SOURCE=..\..\obj_map.c -# End Source File -# Begin Source File - -SOURCE=..\..\os_dep.c -# End Source File -# Begin Source File - -SOURCE=..\..\ptr_chck.c -# End Source File -# Begin Source File - -SOURCE=..\..\reclaim.c -# End Source File -# Begin Source File - -SOURCE=..\stdafx.c -# ADD CPP /Yc"stdafx.h" -# End Source File -# Begin Source File - -SOURCE=..\..\stubborn.c -# End Source File -# Begin Source File - -SOURCE=..\..\typd_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\win32_threads.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hh;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\include\gc.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_allocator.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_backptr.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_config_macros.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_cpp.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_gcj.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\private\gc_hdrs.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_inl.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_inline.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\private\gc_locks.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_mark.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_disclaim.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\private\gc_pmark.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\private\gc_priv.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_pthread_redirects.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_typed.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\private\gcconfig.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\javaxfc.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\leak_detector.h -# End Source File -# Begin Source File - -SOURCE=..\..\msvc_dbg.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\new_gc_alloc.h -# End Source File -# Begin Source File - -SOURCE=..\stdafx.h -# End Source File -# Begin Source File - -SOURCE=..\..\version.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\weakpointer.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# Begin Source File - -SOURCE=..\gc.def -# End Source File -# Begin Source File - -SOURCE=..\gc.rc -# End Source File -# Begin Source File - -SOURCE=..\gc.ver -# End Source File -# End Group -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/gc.dsw b/src/bdwgc/windows-untested/vc60/gc.dsw deleted file mode 100644 index c0f26184d..000000000 --- a/src/bdwgc/windows-untested/vc60/gc.dsw +++ /dev/null @@ -1,194 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "all"=".\all.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name gc - End Project Dependency - Begin Project Dependency - Project_Dep_Name libgc - End Project Dependency - Begin Project Dependency - Project_Dep_Name libgcmt - End Project Dependency -}}} - -############################################################################### - -Project: "gc"=".\gc.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "libgc"=".\libgc.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "libgcmt"=".\libgcmt.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "test"=".\test.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name test_gc - End Project Dependency - Begin Project Dependency - Project_Dep_Name test_libgc - End Project Dependency - Begin Project Dependency - Project_Dep_Name test_libgcmt - End Project Dependency - Begin Project Dependency - Project_Dep_Name test_leak_gc - End Project Dependency - Begin Project Dependency - Project_Dep_Name test_leak_libgc - End Project Dependency - Begin Project Dependency - Project_Dep_Name test_leak_libgcmt - End Project Dependency -}}} - -############################################################################### - -Project: "test_gc"=".\test_gc.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name gc - End Project Dependency -}}} - -############################################################################### - -Project: "test_leak_gc"=".\test_leak_gc.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name gc - End Project Dependency -}}} - -############################################################################### - -Project: "test_leak_libgc"=".\test_leak_libgc.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libgc - End Project Dependency -}}} - -############################################################################### - -Project: "test_leak_libgcmt"=".\test_leak_libgcmt.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libgcmt - End Project Dependency -}}} - -############################################################################### - -Project: "test_libgc"=".\test_libgc.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libgc - End Project Dependency -}}} - -############################################################################### - -Project: "test_libgcmt"=".\test_libgcmt.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libgcmt - End Project Dependency -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/src/bdwgc/windows-untested/vc60/libgc.dsp b/src/bdwgc/windows-untested/vc60/libgc.dsp deleted file mode 100644 index f7d77df53..000000000 --- a/src/bdwgc/windows-untested/vc60/libgc.dsp +++ /dev/null @@ -1,269 +0,0 @@ -# Microsoft Developer Studio Project File - Name="libgc" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=libgc - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "libgc.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libgc.mak" CFG="libgc - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libgc - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "libgc - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libgc - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\lib" -# PROP Intermediate_Dir "..\..\..\obj\Release\libgc" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /W3 /GX /Zi /O2 /I "..\..\include" /FI"stdafx.h" /D "NDEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /Yu"stdafx.h" /Fd"..\..\..\lib\libgc.pdb" /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo -# Begin Special Build Tool -OutDir=.\..\..\..\lib -TargetName=libgc -SOURCE="$(InputPath)" -PostBuild_Cmds=del $(OutDir)\$(TargetName).idb -# End Special Build Tool - -!ELSEIF "$(CFG)" == "libgc - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\lib" -# PROP Intermediate_Dir "..\..\..\obj\Debug\libgc" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /GX /Zi /Od /I "..\..\include" /FI"stdafx.h" /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /Yu"stdafx.h" /Fd"..\..\..\lib\libgcd.pdb" /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\..\lib/libgcd.bsc" -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\..\..\lib\libgcd.lib" -# Begin Special Build Tool -OutDir=.\..\..\..\lib -TargetName=libgcd -SOURCE="$(InputPath)" -PostBuild_Cmds=del $(OutDir)\$(TargetName).idb -# End Special Build Tool - -!ENDIF - -# Begin Target - -# Name "libgc - Win32 Release" -# Name "libgc - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "c;cpp;cc;cxx;tcc;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\allchblk.c -# End Source File -# Begin Source File - -SOURCE=..\..\alloc.c -# End Source File -# Begin Source File - -SOURCE=..\..\backgraph.c -# End Source File -# Begin Source File - -SOURCE=..\..\blacklst.c -# End Source File -# Begin Source File - -SOURCE=..\..\checksums.c -# End Source File -# Begin Source File - -SOURCE=..\..\dbg_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\gcj_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\fnlz_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\dyn_load.c -# End Source File -# Begin Source File - -SOURCE=..\..\finalize.c -# End Source File -# Begin Source File - -SOURCE=..\..\headers.c -# End Source File -# Begin Source File - -SOURCE=..\..\mach_dep.c -# End Source File -# Begin Source File - -SOURCE=..\..\malloc.c -# End Source File -# Begin Source File - -SOURCE=..\..\mallocx.c -# End Source File -# Begin Source File - -SOURCE=..\..\mark.c -# End Source File -# Begin Source File - -SOURCE=..\..\mark_rts.c -# End Source File -# Begin Source File - -SOURCE=..\..\misc.c -# End Source File -# Begin Source File - -SOURCE=..\..\msvc_dbg.c -# End Source File -# Begin Source File - -SOURCE=..\..\new_hblk.c -# End Source File -# Begin Source File - -SOURCE=..\..\obj_map.c -# End Source File -# Begin Source File - -SOURCE=..\..\os_dep.c -# End Source File -# Begin Source File - -SOURCE=..\..\ptr_chck.c -# End Source File -# Begin Source File - -SOURCE=..\..\reclaim.c -# End Source File -# Begin Source File - -SOURCE=..\stdafx.c -# ADD CPP /Yc"stdafx.h" -# End Source File -# Begin Source File - -SOURCE=..\..\stubborn.c -# End Source File -# Begin Source File - -SOURCE=..\..\typd_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\win32_threads.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hh;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\include\gc_allocator.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_backptr.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_cpp.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_gcj.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_inl.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_inline.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\gc_pthread_redirects.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\javaxfc.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\leak_detector.h -# End Source File -# Begin Source File - -SOURCE=..\..\msvc_dbg.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\new_gc_alloc.h -# End Source File -# Begin Source File - -SOURCE=..\stdafx.h -# End Source File -# Begin Source File - -SOURCE=..\..\version.h -# End Source File -# Begin Source File - -SOURCE=..\..\include\weakpointer.h -# End Source File -# End Group -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/libgcmt.dsp b/src/bdwgc/windows-untested/vc60/libgcmt.dsp deleted file mode 100644 index 72d3658c2..000000000 --- a/src/bdwgc/windows-untested/vc60/libgcmt.dsp +++ /dev/null @@ -1,225 +0,0 @@ -# Microsoft Developer Studio Project File - Name="libgcmt" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=libgcmt - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "libgcmt.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libgcmt.mak" CFG="libgcmt - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libgcmt - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "libgcmt - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libgcmt - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\lib" -# PROP Intermediate_Dir "..\..\..\obj\Release\libgcmt" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\..\include" /FI"stdafx.h" /D "NDEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /Yu"stdafx.h" /Fd"..\..\..\lib\libgcmt.pdb" /Zl /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo -# Begin Special Build Tool -OutDir=.\..\..\..\lib -TargetName=libgcmt -SOURCE="$(InputPath)" -PostBuild_Cmds=del $(OutDir)\$(TargetName).idb -# End Special Build Tool - -!ELSEIF "$(CFG)" == "libgcmt - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\lib" -# PROP Intermediate_Dir "..\..\..\obj\Debug\libgcmt" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /I "..\..\include" /FI"stdafx.h" /D "_DEBUG" /D "_LIB" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /Yu"stdafx.h" /Fd"..\..\..\lib\libgcmtd.pdb" /Zl /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\..\lib/libgcmtd.bsc" -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"..\..\..\lib\libgcmtd.lib" -# Begin Special Build Tool -OutDir=.\..\..\..\lib -TargetName=libgcmtd -SOURCE="$(InputPath)" -PostBuild_Cmds=del $(OutDir)\$(TargetName).idb -# End Special Build Tool - -!ENDIF - -# Begin Target - -# Name "libgcmt - Win32 Release" -# Name "libgcmt - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "c;cpp;cc;cxx;tcc;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\..\allchblk.c -# End Source File -# Begin Source File - -SOURCE=..\..\alloc.c -# End Source File -# Begin Source File - -SOURCE=..\..\backgraph.c -# End Source File -# Begin Source File - -SOURCE=..\..\blacklst.c -# End Source File -# Begin Source File - -SOURCE=..\..\checksums.c -# End Source File -# Begin Source File - -SOURCE=..\..\dbg_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\gcj_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\fnlz_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\dyn_load.c -# End Source File -# Begin Source File - -SOURCE=..\..\finalize.c -# End Source File -# Begin Source File - -SOURCE=..\..\headers.c -# End Source File -# Begin Source File - -SOURCE=..\..\mach_dep.c -# End Source File -# Begin Source File - -SOURCE=..\..\malloc.c -# End Source File -# Begin Source File - -SOURCE=..\..\mallocx.c -# End Source File -# Begin Source File - -SOURCE=..\..\mark.c -# End Source File -# Begin Source File - -SOURCE=..\..\mark_rts.c -# End Source File -# Begin Source File - -SOURCE=..\..\misc.c -# End Source File -# Begin Source File - -SOURCE=..\..\msvc_dbg.c -# End Source File -# Begin Source File - -SOURCE=..\..\new_hblk.c -# End Source File -# Begin Source File - -SOURCE=..\..\obj_map.c -# End Source File -# Begin Source File - -SOURCE=..\..\os_dep.c -# End Source File -# Begin Source File - -SOURCE=..\..\ptr_chck.c -# End Source File -# Begin Source File - -SOURCE=..\..\reclaim.c -# End Source File -# Begin Source File - -SOURCE=..\stdafx.c -# ADD CPP /Yc"stdafx.h" -# End Source File -# Begin Source File - -SOURCE=..\..\stubborn.c -# End Source File -# Begin Source File - -SOURCE=..\..\typd_mlc.c -# End Source File -# Begin Source File - -SOURCE=..\..\win32_threads.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hh;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\msvc_dbg.h -# End Source File -# Begin Source File - -SOURCE=..\stdafx.h -# End Source File -# Begin Source File - -SOURCE=..\..\version.h -# End Source File -# End Group -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/test.dsp b/src/bdwgc/windows-untested/vc60/test.dsp deleted file mode 100644 index 3648da48a..000000000 --- a/src/bdwgc/windows-untested/vc60/test.dsp +++ /dev/null @@ -1,63 +0,0 @@ -# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Generic Project" 0x010a - -CFG=test - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "test.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Generic Project") -!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Generic Project") -!MESSAGE - -# Begin Project -# PROP testowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -MTL=midl.exe - -!IF "$(CFG)" == "test - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Release" -# PROP Target_Dir "" - -!ELSEIF "$(CFG)" == "test - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Debug" -# PROP Target_Dir "" - -!ENDIF - -# Begin Target - -# Name "test - Win32 Release" -# Name "test - Win32 Debug" -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/test_gc.dsp b/src/bdwgc/windows-untested/vc60/test_gc.dsp deleted file mode 100644 index a92256312..000000000 --- a/src/bdwgc/windows-untested/vc60/test_gc.dsp +++ /dev/null @@ -1,93 +0,0 @@ -# Microsoft Developer Studio Project File - Name="test_gc" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=test_gc - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "test_gc.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "test_gc.mak" CFG="test_gc - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "test_gc - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "test_gc - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "test_gc - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Release\test_gc" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "..\..\include" /D "NDEBUG" /D "_CONSOLE" /D "GC_DLL" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /FD /c -# SUBTRACT CPP /Fr /YX -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /debug /machine:I386 /release /opt:ref -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "test_gc - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Debug\test_gc" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "_CONSOLE" /D "GC_DLL" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /YX /FD /GZ /c -# SUBTRACT CPP /Fr -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\..\bin/test_gcd.bsc" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /incremental:no /debug /machine:I386 /out:"..\..\..\bin/test_gcd.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "test_gc - Win32 Release" -# Name "test_gc - Win32 Debug" -# Begin Source File - -SOURCE=..\..\tests\test.c -# End Source File -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/test_leak_gc.dsp b/src/bdwgc/windows-untested/vc60/test_leak_gc.dsp deleted file mode 100644 index 273c27d84..000000000 --- a/src/bdwgc/windows-untested/vc60/test_leak_gc.dsp +++ /dev/null @@ -1,93 +0,0 @@ -# Microsoft Developer Studio Project File - Name="test_leak_gc" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=test_leak_gc - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "test_leak_gc.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "test_leak_gc.mak" CFG="test_leak_gc - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "test_leak_gc - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "test_leak_gc - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "test_leak_gc - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Release\test_leak_gc" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "..\..\include" /D "NDEBUG" /D "_CONSOLE" /D "GC_DLL" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /FD /c -# SUBTRACT CPP /Fr /YX -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /debug /machine:I386 /release /opt:ref -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "test_leak_gc - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Debug\test_leak_gc" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "_CONSOLE" /D "GC_DLL" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /YX /FD /GZ /c -# SUBTRACT CPP /Fr -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\..\bin/test_leak_gcd.bsc" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /incremental:no /debug /machine:I386 /out:"..\..\..\bin/test_leak_gcd.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "test_leak_gc - Win32 Release" -# Name "test_leak_gc - Win32 Debug" -# Begin Source File - -SOURCE=..\..\tests\leak_test.c -# End Source File -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/test_leak_libgc.dsp b/src/bdwgc/windows-untested/vc60/test_leak_libgc.dsp deleted file mode 100644 index 2d9225715..000000000 --- a/src/bdwgc/windows-untested/vc60/test_leak_libgc.dsp +++ /dev/null @@ -1,93 +0,0 @@ -# Microsoft Developer Studio Project File - Name="test_leak_libgc" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=test_leak_libgc - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "test_leak_libgc.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "test_leak_libgc.mak" CFG="test_leak_libgc - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "test_leak_libgc - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "test_leak_libgc - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "test_leak_libgc - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Release\test_leak_libgc" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /Zi /O2 /I "..\..\include" /D "NDEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /FD /c -# SUBTRACT CPP /Fr /YX -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /debug /machine:I386 /release /opt:ref -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "test_leak_libgc - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Debug\test_leak_libgc" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c -# SUBTRACT CPP /Fr -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\..\bin/test_leak_libgcd.bsc" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /incremental:no /debug /machine:I386 /out:"..\..\..\bin/test_leak_libgcd.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "test_leak_libgc - Win32 Release" -# Name "test_leak_libgc - Win32 Debug" -# Begin Source File - -SOURCE=..\..\tests\leak_test.c -# End Source File -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/test_leak_libgcmt.dsp b/src/bdwgc/windows-untested/vc60/test_leak_libgcmt.dsp deleted file mode 100644 index 42f97899e..000000000 --- a/src/bdwgc/windows-untested/vc60/test_leak_libgcmt.dsp +++ /dev/null @@ -1,93 +0,0 @@ -# Microsoft Developer Studio Project File - Name="test_leak_libgcmt" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=test_leak_libgcmt - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "test_leak_libgcmt.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "test_leak_libgcmt.mak" CFG="test_leak_libgcmt - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "test_leak_libgcmt - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "test_leak_libgcmt - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "test_leak_libgcmt - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Release\test_leak_libgcmt" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\..\include" /D "NDEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /FD /c -# SUBTRACT CPP /Fr /YX -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /debug /machine:I386 /release /opt:ref -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "test_leak_libgcmt - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Debug\test_leak_libgcmt" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /YX /FD /GZ /c -# SUBTRACT CPP /Fr -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\..\bin/test_leak_libgcmtd.bsc" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /incremental:no /debug /machine:I386 /out:"..\..\..\bin/test_leak_libgcmtd.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "test_leak_libgcmt - Win32 Release" -# Name "test_leak_libgcmt - Win32 Debug" -# Begin Source File - -SOURCE=..\..\tests\leak_test.c -# End Source File -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/test_libgc.dsp b/src/bdwgc/windows-untested/vc60/test_libgc.dsp deleted file mode 100644 index d7fa50aab..000000000 --- a/src/bdwgc/windows-untested/vc60/test_libgc.dsp +++ /dev/null @@ -1,93 +0,0 @@ -# Microsoft Developer Studio Project File - Name="test_libgc" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=test_libgc - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "test_libgc.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "test_libgc.mak" CFG="test_libgc - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "test_libgc - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "test_libgc - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "test_libgc - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Release\test_libgc" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /Zi /O2 /I "..\..\include" /D "NDEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /FD /c -# SUBTRACT CPP /Fr /YX -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /debug /machine:I386 /release /opt:ref -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "test_libgc - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Debug\test_libgc" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /YX /FD /GZ /c -# SUBTRACT CPP /Fr -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\..\bin/test_libgcd.bsc" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /incremental:no /debug /machine:I386 /out:"..\..\..\bin/test_libgcd.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "test_libgc - Win32 Release" -# Name "test_libgc - Win32 Debug" -# Begin Source File - -SOURCE=..\..\tests\test.c -# End Source File -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/test_libgcmt.dsp b/src/bdwgc/windows-untested/vc60/test_libgcmt.dsp deleted file mode 100644 index 6f81a3466..000000000 --- a/src/bdwgc/windows-untested/vc60/test_libgcmt.dsp +++ /dev/null @@ -1,93 +0,0 @@ -# Microsoft Developer Studio Project File - Name="test_libgcmt" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=test_libgcmt - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "test_libgcmt.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "test_libgcmt.mak" CFG="test_libgcmt - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "test_libgcmt - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "test_libgcmt - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "test_libgcmt - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Release\test_libgcmt" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\..\include" /D "NDEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /FD /c -# SUBTRACT CPP /Fr /YX -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /debug /machine:I386 /release /opt:ref -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "test_libgcmt - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\bin" -# PROP Intermediate_Dir "..\..\..\obj\Debug\test_libgcmt" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "_CONSOLE" /D "WIN32" /D "_MBCS" /D "GC_THREADS" /YX /FD /GZ /c -# SUBTRACT CPP /Fr -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo /o"..\..\..\bin/test_libgcmtd.bsc" -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /incremental:no /debug /machine:I386 /out:"..\..\..\bin/test_libgcmtd.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "test_libgcmt - Win32 Release" -# Name "test_libgcmt - Win32 Debug" -# Begin Source File - -SOURCE=..\..\tests\test.c -# End Source File -# End Target -# End Project diff --git a/src/bdwgc/windows-untested/vc60/vc60crlf.cmd b/src/bdwgc/windows-untested/vc60/vc60crlf.cmd deleted file mode 100755 index 28ec5360c..000000000 --- a/src/bdwgc/windows-untested/vc60/vc60crlf.cmd +++ /dev/null @@ -1,15 +0,0 @@ -@echo off -rem This script will convert Unix-style line endings into Windows format. - -for %%P in (*.ds?) do call :fixline %%P -goto :eof - -:fixline -@echo on -if exist "%~1.new" del "%~1.new" -for /f %%S in (%1) do ( - echo %%S>>"%~1.new" -) -ren %1 "%~1.bak" -ren "%~1.new" %1 -goto :eof diff --git a/src/bdwgc/windows-untested/vc70/all.vcproj b/src/bdwgc/windows-untested/vc70/all.vcproj deleted file mode 100644 index 512e9a062..000000000 --- a/src/bdwgc/windows-untested/vc70/all.vcproj +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc70/gc.sln b/src/bdwgc/windows-untested/vc70/gc.sln deleted file mode 100644 index aaa1be64e..000000000 --- a/src/bdwgc/windows-untested/vc70/gc.sln +++ /dev/null @@ -1,96 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 7.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "all", "all.vcproj", "{CED9D953-AC1A-4795-9853-6D60857509EE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gc", "gc.vcproj", "{D7ADAD9A-14FF-4C93-9BF1-ACD03FB6A2FA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgc", "libgc.vcproj", "{F80C47A7-2B2D-4BA9-BEED-AAFA7541650D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgcmt", "libgcmt.vcproj", "{39802D97-BEF7-499D-8570-294AEA39ED7D}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{997208FE-7A7D-435A-945A-C61C57D8070C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_gc", "test_gc.vcproj", "{D1F56655-8C27-4320-9436-2A11729A337B}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_leak_gc", "test_leak_gc.vcproj", "{6E545988-1AE7-41FB-A981-D256A84F4C3A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_leak_libgc", "test_leak_libgc.vcproj", "{A561AE5C-33FE-4DBC-A4D4-52B7F196D20F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_leak_libgcmt", "test_leak_libgcmt.vcproj", "{92046CBF-2EF9-408D-B997-8445E945D687}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_libgc", "test_libgc.vcproj", "{8CFE55AA-676C-4B5A-B133-390B4BF02AB8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_libgcmt", "test_libgcmt.vcproj", "{8C63DB39-DBF4-49D3-A908-172ADA21753B}" -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - ConfigName.0 = Debug - ConfigName.1 = Release - EndGlobalSection - GlobalSection(ProjectDependencies) = postSolution - {CED9D953-AC1A-4795-9853-6D60857509EE}.0 = {39802D97-BEF7-499D-8570-294AEA39ED7D} - {CED9D953-AC1A-4795-9853-6D60857509EE}.1 = {F80C47A7-2B2D-4BA9-BEED-AAFA7541650D} - {CED9D953-AC1A-4795-9853-6D60857509EE}.2 = {D7ADAD9A-14FF-4C93-9BF1-ACD03FB6A2FA} - {997208FE-7A7D-435A-945A-C61C57D8070C}.0 = {92046CBF-2EF9-408D-B997-8445E945D687} - {997208FE-7A7D-435A-945A-C61C57D8070C}.1 = {A561AE5C-33FE-4DBC-A4D4-52B7F196D20F} - {997208FE-7A7D-435A-945A-C61C57D8070C}.2 = {6E545988-1AE7-41FB-A981-D256A84F4C3A} - {997208FE-7A7D-435A-945A-C61C57D8070C}.3 = {8C63DB39-DBF4-49D3-A908-172ADA21753B} - {997208FE-7A7D-435A-945A-C61C57D8070C}.4 = {8CFE55AA-676C-4B5A-B133-390B4BF02AB8} - {997208FE-7A7D-435A-945A-C61C57D8070C}.5 = {D1F56655-8C27-4320-9436-2A11729A337B} - {D1F56655-8C27-4320-9436-2A11729A337B}.0 = {D7ADAD9A-14FF-4C93-9BF1-ACD03FB6A2FA} - {6E545988-1AE7-41FB-A981-D256A84F4C3A}.0 = {D7ADAD9A-14FF-4C93-9BF1-ACD03FB6A2FA} - {A561AE5C-33FE-4DBC-A4D4-52B7F196D20F}.0 = {F80C47A7-2B2D-4BA9-BEED-AAFA7541650D} - {92046CBF-2EF9-408D-B997-8445E945D687}.0 = {39802D97-BEF7-499D-8570-294AEA39ED7D} - {8CFE55AA-676C-4B5A-B133-390B4BF02AB8}.0 = {F80C47A7-2B2D-4BA9-BEED-AAFA7541650D} - {8C63DB39-DBF4-49D3-A908-172ADA21753B}.0 = {39802D97-BEF7-499D-8570-294AEA39ED7D} - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {CED9D953-AC1A-4795-9853-6D60857509EE}.Debug.ActiveCfg = Debug|Win32 - {CED9D953-AC1A-4795-9853-6D60857509EE}.Debug.Build.0 = Debug|Win32 - {CED9D953-AC1A-4795-9853-6D60857509EE}.Release.ActiveCfg = Release|Win32 - {CED9D953-AC1A-4795-9853-6D60857509EE}.Release.Build.0 = Release|Win32 - {D7ADAD9A-14FF-4C93-9BF1-ACD03FB6A2FA}.Debug.ActiveCfg = Debug|Win32 - {D7ADAD9A-14FF-4C93-9BF1-ACD03FB6A2FA}.Debug.Build.0 = Debug|Win32 - {D7ADAD9A-14FF-4C93-9BF1-ACD03FB6A2FA}.Release.ActiveCfg = Release|Win32 - {D7ADAD9A-14FF-4C93-9BF1-ACD03FB6A2FA}.Release.Build.0 = Release|Win32 - {F80C47A7-2B2D-4BA9-BEED-AAFA7541650D}.Debug.ActiveCfg = Debug|Win32 - {F80C47A7-2B2D-4BA9-BEED-AAFA7541650D}.Debug.Build.0 = Debug|Win32 - {F80C47A7-2B2D-4BA9-BEED-AAFA7541650D}.Release.ActiveCfg = Release|Win32 - {F80C47A7-2B2D-4BA9-BEED-AAFA7541650D}.Release.Build.0 = Release|Win32 - {39802D97-BEF7-499D-8570-294AEA39ED7D}.Debug.ActiveCfg = Debug|Win32 - {39802D97-BEF7-499D-8570-294AEA39ED7D}.Debug.Build.0 = Debug|Win32 - {39802D97-BEF7-499D-8570-294AEA39ED7D}.Release.ActiveCfg = Release|Win32 - {39802D97-BEF7-499D-8570-294AEA39ED7D}.Release.Build.0 = Release|Win32 - {997208FE-7A7D-435A-945A-C61C57D8070C}.Debug.ActiveCfg = Debug|Win32 - {997208FE-7A7D-435A-945A-C61C57D8070C}.Debug.Build.0 = Debug|Win32 - {997208FE-7A7D-435A-945A-C61C57D8070C}.Release.ActiveCfg = Release|Win32 - {997208FE-7A7D-435A-945A-C61C57D8070C}.Release.Build.0 = Release|Win32 - {D1F56655-8C27-4320-9436-2A11729A337B}.Debug.ActiveCfg = Debug|Win32 - {D1F56655-8C27-4320-9436-2A11729A337B}.Debug.Build.0 = Debug|Win32 - {D1F56655-8C27-4320-9436-2A11729A337B}.Release.ActiveCfg = Release|Win32 - {D1F56655-8C27-4320-9436-2A11729A337B}.Release.Build.0 = Release|Win32 - {6E545988-1AE7-41FB-A981-D256A84F4C3A}.Debug.ActiveCfg = Debug|Win32 - {6E545988-1AE7-41FB-A981-D256A84F4C3A}.Debug.Build.0 = Debug|Win32 - {6E545988-1AE7-41FB-A981-D256A84F4C3A}.Release.ActiveCfg = Release|Win32 - {6E545988-1AE7-41FB-A981-D256A84F4C3A}.Release.Build.0 = Release|Win32 - {A561AE5C-33FE-4DBC-A4D4-52B7F196D20F}.Debug.ActiveCfg = Debug|Win32 - {A561AE5C-33FE-4DBC-A4D4-52B7F196D20F}.Debug.Build.0 = Debug|Win32 - {A561AE5C-33FE-4DBC-A4D4-52B7F196D20F}.Release.ActiveCfg = Release|Win32 - {A561AE5C-33FE-4DBC-A4D4-52B7F196D20F}.Release.Build.0 = Release|Win32 - {92046CBF-2EF9-408D-B997-8445E945D687}.Debug.ActiveCfg = Debug|Win32 - {92046CBF-2EF9-408D-B997-8445E945D687}.Debug.Build.0 = Debug|Win32 - {92046CBF-2EF9-408D-B997-8445E945D687}.Release.ActiveCfg = Release|Win32 - {92046CBF-2EF9-408D-B997-8445E945D687}.Release.Build.0 = Release|Win32 - {8CFE55AA-676C-4B5A-B133-390B4BF02AB8}.Debug.ActiveCfg = Debug|Win32 - {8CFE55AA-676C-4B5A-B133-390B4BF02AB8}.Debug.Build.0 = Debug|Win32 - {8CFE55AA-676C-4B5A-B133-390B4BF02AB8}.Release.ActiveCfg = Release|Win32 - {8CFE55AA-676C-4B5A-B133-390B4BF02AB8}.Release.Build.0 = Release|Win32 - {8C63DB39-DBF4-49D3-A908-172ADA21753B}.Debug.ActiveCfg = Debug|Win32 - {8C63DB39-DBF4-49D3-A908-172ADA21753B}.Debug.Build.0 = Debug|Win32 - {8C63DB39-DBF4-49D3-A908-172ADA21753B}.Release.ActiveCfg = Release|Win32 - {8C63DB39-DBF4-49D3-A908-172ADA21753B}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/src/bdwgc/windows-untested/vc70/gc.vcproj b/src/bdwgc/windows-untested/vc70/gc.vcproj deleted file mode 100644 index 9f18300e8..000000000 --- a/src/bdwgc/windows-untested/vc70/gc.vcproj +++ /dev/null @@ -1,347 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc70/libgc.vcproj b/src/bdwgc/windows-untested/vc70/libgc.vcproj deleted file mode 100644 index 56847eb98..000000000 --- a/src/bdwgc/windows-untested/vc70/libgc.vcproj +++ /dev/null @@ -1,258 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc70/libgcmt.vcproj b/src/bdwgc/windows-untested/vc70/libgcmt.vcproj deleted file mode 100644 index ab5740076..000000000 --- a/src/bdwgc/windows-untested/vc70/libgcmt.vcproj +++ /dev/null @@ -1,225 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc70/test.vcproj b/src/bdwgc/windows-untested/vc70/test.vcproj deleted file mode 100644 index 4b6170ddd..000000000 --- a/src/bdwgc/windows-untested/vc70/test.vcproj +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc70/test_gc.vcproj b/src/bdwgc/windows-untested/vc70/test_gc.vcproj deleted file mode 100644 index 8802cf6d9..000000000 --- a/src/bdwgc/windows-untested/vc70/test_gc.vcproj +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc70/test_leak_gc.vcproj b/src/bdwgc/windows-untested/vc70/test_leak_gc.vcproj deleted file mode 100644 index 4b12168ee..000000000 --- a/src/bdwgc/windows-untested/vc70/test_leak_gc.vcproj +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc70/test_leak_libgc.vcproj b/src/bdwgc/windows-untested/vc70/test_leak_libgc.vcproj deleted file mode 100644 index 05a1be4e5..000000000 --- a/src/bdwgc/windows-untested/vc70/test_leak_libgc.vcproj +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc70/test_leak_libgcmt.vcproj b/src/bdwgc/windows-untested/vc70/test_leak_libgcmt.vcproj deleted file mode 100644 index 8f4f8bd78..000000000 --- a/src/bdwgc/windows-untested/vc70/test_leak_libgcmt.vcproj +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc70/test_libgc.vcproj b/src/bdwgc/windows-untested/vc70/test_libgc.vcproj deleted file mode 100644 index 110c39621..000000000 --- a/src/bdwgc/windows-untested/vc70/test_libgc.vcproj +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc70/test_libgcmt.vcproj b/src/bdwgc/windows-untested/vc70/test_libgcmt.vcproj deleted file mode 100644 index 1353cdf02..000000000 --- a/src/bdwgc/windows-untested/vc70/test_libgcmt.vcproj +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/all.vcproj b/src/bdwgc/windows-untested/vc71/all.vcproj deleted file mode 100644 index 2f4d7ae52..000000000 --- a/src/bdwgc/windows-untested/vc71/all.vcproj +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/gc.sln b/src/bdwgc/windows-untested/vc71/gc.sln deleted file mode 100644 index fa1acc8d6..000000000 --- a/src/bdwgc/windows-untested/vc71/gc.sln +++ /dev/null @@ -1,116 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "all", "all.vcproj", "{684E465A-3944-4BA0-BA8D-52A064B43A5D}" - ProjectSection(ProjectDependencies) = postProject - {EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16} = {EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16} - {1C32FB8B-6F91-4190-9F05-CE1E772BB5E0} = {1C32FB8B-6F91-4190-9F05-CE1E772BB5E0} - {93622AAF-633A-4D02-B023-674D4CDA266B} = {93622AAF-633A-4D02-B023-674D4CDA266B} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gc", "gc.vcproj", "{93622AAF-633A-4D02-B023-674D4CDA266B}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgc", "libgc.vcproj", "{1C32FB8B-6F91-4190-9F05-CE1E772BB5E0}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgcmt", "libgcmt.vcproj", "{EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{1891ADD8-C39B-494B-B69D-D64F76729E5A}" - ProjectSection(ProjectDependencies) = postProject - {8A595901-33E6-4959-A8E9-6DACC2D57330} = {8A595901-33E6-4959-A8E9-6DACC2D57330} - {EB1D2ECA-926D-4B6E-BF65-B429C713381C} = {EB1D2ECA-926D-4B6E-BF65-B429C713381C} - {500B7CE2-FD16-42C5-B738-1406C13A68B4} = {500B7CE2-FD16-42C5-B738-1406C13A68B4} - {9551B5E4-94A5-4B04-ACA1-9FB28DFD28AA} = {9551B5E4-94A5-4B04-ACA1-9FB28DFD28AA} - {B0F6C137-5153-48E3-ABED-6C02D3912EDA} = {B0F6C137-5153-48E3-ABED-6C02D3912EDA} - {1911057C-30C3-41CE-AF9E-232AEB37BCD3} = {1911057C-30C3-41CE-AF9E-232AEB37BCD3} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_gc", "test_gc.vcproj", "{1911057C-30C3-41CE-AF9E-232AEB37BCD3}" - ProjectSection(ProjectDependencies) = postProject - {93622AAF-633A-4D02-B023-674D4CDA266B} = {93622AAF-633A-4D02-B023-674D4CDA266B} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_leak_gc", "test_leak_gc.vcproj", "{500B7CE2-FD16-42C5-B738-1406C13A68B4}" - ProjectSection(ProjectDependencies) = postProject - {93622AAF-633A-4D02-B023-674D4CDA266B} = {93622AAF-633A-4D02-B023-674D4CDA266B} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_leak_libgc", "test_leak_libgc.vcproj", "{EB1D2ECA-926D-4B6E-BF65-B429C713381C}" - ProjectSection(ProjectDependencies) = postProject - {1C32FB8B-6F91-4190-9F05-CE1E772BB5E0} = {1C32FB8B-6F91-4190-9F05-CE1E772BB5E0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_leak_libgcmt", "test_leak_libgcmt.vcproj", "{8A595901-33E6-4959-A8E9-6DACC2D57330}" - ProjectSection(ProjectDependencies) = postProject - {EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16} = {EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_libgc", "test_libgc.vcproj", "{B0F6C137-5153-48E3-ABED-6C02D3912EDA}" - ProjectSection(ProjectDependencies) = postProject - {1C32FB8B-6F91-4190-9F05-CE1E772BB5E0} = {1C32FB8B-6F91-4190-9F05-CE1E772BB5E0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_libgcmt", "test_libgcmt.vcproj", "{9551B5E4-94A5-4B04-ACA1-9FB28DFD28AA}" - ProjectSection(ProjectDependencies) = postProject - {EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16} = {EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {684E465A-3944-4BA0-BA8D-52A064B43A5D}.Debug.ActiveCfg = Debug|Win32 - {684E465A-3944-4BA0-BA8D-52A064B43A5D}.Debug.Build.0 = Debug|Win32 - {684E465A-3944-4BA0-BA8D-52A064B43A5D}.Release.ActiveCfg = Release|Win32 - {684E465A-3944-4BA0-BA8D-52A064B43A5D}.Release.Build.0 = Release|Win32 - {93622AAF-633A-4D02-B023-674D4CDA266B}.Debug.ActiveCfg = Debug|Win32 - {93622AAF-633A-4D02-B023-674D4CDA266B}.Debug.Build.0 = Debug|Win32 - {93622AAF-633A-4D02-B023-674D4CDA266B}.Release.ActiveCfg = Release|Win32 - {93622AAF-633A-4D02-B023-674D4CDA266B}.Release.Build.0 = Release|Win32 - {1C32FB8B-6F91-4190-9F05-CE1E772BB5E0}.Debug.ActiveCfg = Debug|Win32 - {1C32FB8B-6F91-4190-9F05-CE1E772BB5E0}.Debug.Build.0 = Debug|Win32 - {1C32FB8B-6F91-4190-9F05-CE1E772BB5E0}.Release.ActiveCfg = Release|Win32 - {1C32FB8B-6F91-4190-9F05-CE1E772BB5E0}.Release.Build.0 = Release|Win32 - {EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16}.Debug.ActiveCfg = Debug|Win32 - {EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16}.Debug.Build.0 = Debug|Win32 - {EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16}.Release.ActiveCfg = Release|Win32 - {EDA8C8B6-2538-4F1E-9C9A-F5C4FAF1EC16}.Release.Build.0 = Release|Win32 - {1891ADD8-C39B-494B-B69D-D64F76729E5A}.Debug.ActiveCfg = Debug|Win32 - {1891ADD8-C39B-494B-B69D-D64F76729E5A}.Debug.Build.0 = Debug|Win32 - {1891ADD8-C39B-494B-B69D-D64F76729E5A}.Release.ActiveCfg = Release|Win32 - {1891ADD8-C39B-494B-B69D-D64F76729E5A}.Release.Build.0 = Release|Win32 - {1911057C-30C3-41CE-AF9E-232AEB37BCD3}.Debug.ActiveCfg = Debug|Win32 - {1911057C-30C3-41CE-AF9E-232AEB37BCD3}.Debug.Build.0 = Debug|Win32 - {1911057C-30C3-41CE-AF9E-232AEB37BCD3}.Release.ActiveCfg = Release|Win32 - {1911057C-30C3-41CE-AF9E-232AEB37BCD3}.Release.Build.0 = Release|Win32 - {500B7CE2-FD16-42C5-B738-1406C13A68B4}.Debug.ActiveCfg = Debug|Win32 - {500B7CE2-FD16-42C5-B738-1406C13A68B4}.Debug.Build.0 = Debug|Win32 - {500B7CE2-FD16-42C5-B738-1406C13A68B4}.Release.ActiveCfg = Release|Win32 - {500B7CE2-FD16-42C5-B738-1406C13A68B4}.Release.Build.0 = Release|Win32 - {EB1D2ECA-926D-4B6E-BF65-B429C713381C}.Debug.ActiveCfg = Debug|Win32 - {EB1D2ECA-926D-4B6E-BF65-B429C713381C}.Debug.Build.0 = Debug|Win32 - {EB1D2ECA-926D-4B6E-BF65-B429C713381C}.Release.ActiveCfg = Release|Win32 - {EB1D2ECA-926D-4B6E-BF65-B429C713381C}.Release.Build.0 = Release|Win32 - {8A595901-33E6-4959-A8E9-6DACC2D57330}.Debug.ActiveCfg = Debug|Win32 - {8A595901-33E6-4959-A8E9-6DACC2D57330}.Debug.Build.0 = Debug|Win32 - {8A595901-33E6-4959-A8E9-6DACC2D57330}.Release.ActiveCfg = Release|Win32 - {8A595901-33E6-4959-A8E9-6DACC2D57330}.Release.Build.0 = Release|Win32 - {B0F6C137-5153-48E3-ABED-6C02D3912EDA}.Debug.ActiveCfg = Debug|Win32 - {B0F6C137-5153-48E3-ABED-6C02D3912EDA}.Debug.Build.0 = Debug|Win32 - {B0F6C137-5153-48E3-ABED-6C02D3912EDA}.Release.ActiveCfg = Release|Win32 - {B0F6C137-5153-48E3-ABED-6C02D3912EDA}.Release.Build.0 = Release|Win32 - {9551B5E4-94A5-4B04-ACA1-9FB28DFD28AA}.Debug.ActiveCfg = Debug|Win32 - {9551B5E4-94A5-4B04-ACA1-9FB28DFD28AA}.Debug.Build.0 = Debug|Win32 - {9551B5E4-94A5-4B04-ACA1-9FB28DFD28AA}.Release.ActiveCfg = Release|Win32 - {9551B5E4-94A5-4B04-ACA1-9FB28DFD28AA}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/src/bdwgc/windows-untested/vc71/gc.vcproj b/src/bdwgc/windows-untested/vc71/gc.vcproj deleted file mode 100644 index af5598f8f..000000000 --- a/src/bdwgc/windows-untested/vc71/gc.vcproj +++ /dev/null @@ -1,869 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/libgc.vcproj b/src/bdwgc/windows-untested/vc71/libgc.vcproj deleted file mode 100644 index f0cc90861..000000000 --- a/src/bdwgc/windows-untested/vc71/libgc.vcproj +++ /dev/null @@ -1,776 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/libgcmt.vcproj b/src/bdwgc/windows-untested/vc71/libgcmt.vcproj deleted file mode 100644 index 1005eb976..000000000 --- a/src/bdwgc/windows-untested/vc71/libgcmt.vcproj +++ /dev/null @@ -1,743 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/test.vcproj b/src/bdwgc/windows-untested/vc71/test.vcproj deleted file mode 100644 index 41681979f..000000000 --- a/src/bdwgc/windows-untested/vc71/test.vcproj +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/test_gc.vcproj b/src/bdwgc/windows-untested/vc71/test_gc.vcproj deleted file mode 100644 index d477d70a6..000000000 --- a/src/bdwgc/windows-untested/vc71/test_gc.vcproj +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/test_leak_gc.vcproj b/src/bdwgc/windows-untested/vc71/test_leak_gc.vcproj deleted file mode 100644 index b6c980cf7..000000000 --- a/src/bdwgc/windows-untested/vc71/test_leak_gc.vcproj +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/test_leak_libgc.vcproj b/src/bdwgc/windows-untested/vc71/test_leak_libgc.vcproj deleted file mode 100644 index 0486f1ef6..000000000 --- a/src/bdwgc/windows-untested/vc71/test_leak_libgc.vcproj +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/test_leak_libgcmt.vcproj b/src/bdwgc/windows-untested/vc71/test_leak_libgcmt.vcproj deleted file mode 100644 index 297464d43..000000000 --- a/src/bdwgc/windows-untested/vc71/test_leak_libgcmt.vcproj +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/test_libgc.vcproj b/src/bdwgc/windows-untested/vc71/test_libgc.vcproj deleted file mode 100644 index 93d35f46d..000000000 --- a/src/bdwgc/windows-untested/vc71/test_libgc.vcproj +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/bdwgc/windows-untested/vc71/test_libgcmt.vcproj b/src/bdwgc/windows-untested/vc71/test_libgcmt.vcproj deleted file mode 100644 index 276aed5b1..000000000 --- a/src/bdwgc/windows-untested/vc71/test_libgcmt.vcproj +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -