diff -Nrc3pad gcc-3.3.3/ABOUT-NLS gcc-3.4.0/ABOUT-NLS *** gcc-3.3.3/ABOUT-NLS 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/ABOUT-NLS 2003-07-04 18:18:42.000000000 +0000 *************** *** 0 **** --- 1,625 ---- + Notes on the Free Translation Project + ************************************* + + Free software is going international! The Free Translation Project + is a way to get maintainers of free software, translators, and users all + together, so that will gradually become able to speak many languages. + A few packages already provide translations for their messages. + + If you found this `ABOUT-NLS' file inside a distribution, you may + assume that the distributed package does use GNU `gettext' internally, + itself available at your nearest GNU archive site. But you do _not_ + need to install GNU `gettext' prior to configuring, installing or using + this package with messages translated. + + Installers will find here some useful hints. These notes also + explain how users should proceed for getting the programs to use the + available translations. They tell how people wanting to contribute and + work at translations should contact the appropriate team. + + When reporting bugs in the `intl/' directory or bugs which may be + related to internationalization, you should tell about the version of + `gettext' which is used. The information can be found in the + `intl/VERSION' file, in internationalized packages. + + Quick configuration advice + ========================== + + If you want to exploit the full power of internationalization, you + should configure it using + + ./configure --with-included-gettext + + to force usage of internationalizing routines provided within this + package, despite the existence of internationalizing capabilities in the + operating system where this package is being installed. So far, only + the `gettext' implementation in the GNU C library version 2 provides as + many features (such as locale alias, message inheritance, automatic + charset conversion or plural form handling) as the implementation here. + It is also not possible to offer this additional functionality on top + of a `catgets' implementation. Future versions of GNU `gettext' will + very likely convey even more functionality. So it might be a good idea + to change to GNU `gettext' as soon as possible. + + So you need _not_ provide this option if you are using GNU libc 2 or + you have installed a recent copy of the GNU gettext package with the + included `libintl'. + + INSTALL Matters + =============== + + Some packages are "localizable" when properly installed; the + programs they contain can be made to speak your own native language. + Most such packages use GNU `gettext'. Other packages have their own + ways to internationalization, predating GNU `gettext'. + + By default, this package will be installed to allow translation of + messages. It will automatically detect whether the system already + provides the GNU `gettext' functions. If not, the GNU `gettext' own + library will be used. This library is wholly contained within this + package, usually in the `intl/' subdirectory, so prior installation of + the GNU `gettext' package is _not_ required. Installers may use + special options at configuration time for changing the default + behaviour. The commands: + + ./configure --with-included-gettext + ./configure --disable-nls + + will respectively bypass any pre-existing `gettext' to use the + internationalizing routines provided within this package, or else, + _totally_ disable translation of messages. + + When you already have GNU `gettext' installed on your system and run + configure without an option for your new package, `configure' will + probably detect the previously built and installed `libintl.a' file and + will decide to use this. This might be not what is desirable. You + should use the more recent version of the GNU `gettext' library. I.e. + if the file `intl/VERSION' shows that the library which comes with this + package is more recent, you should use + + ./configure --with-included-gettext + + to prevent auto-detection. + + The configuration process will not test for the `catgets' function + and therefore it will not be used. The reason is that even an + emulation of `gettext' on top of `catgets' could not provide all the + extensions of the GNU `gettext' library. + + Internationalized packages have usually many `po/LL.po' files, where + LL gives an ISO 639 two-letter code identifying the language. Unless + translations have been forbidden at `configure' time by using the + `--disable-nls' switch, all available translations are installed + together with the package. However, the environment variable `LINGUAS' + may be set, prior to configuration, to limit the installed set. + `LINGUAS' should then contain a space separated list of two-letter + codes, stating which languages are allowed. + + Using This Package + ================== + + As a user, if your language has been installed for this package, you + only have to set the `LANG' environment variable to the appropriate + `LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, + and `CC' is an ISO 3166 two-letter country code. For example, let's + suppose that you speak German and live in Germany. At the shell + prompt, merely execute `setenv LANG de_DE' (in `csh'), + `export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). + This can be done from your `.login' or `.profile' file, once and for + all. + + You might think that the country code specification is redundant. + But in fact, some languages have dialects in different countries. For + example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The + country code serves to distinguish the dialects. + + The locale naming convention of `LL_CC', with `LL' denoting the + language and `CC' denoting the country, is the one use on systems based + on GNU libc. On other systems, some variations of this scheme are + used, such as `LL' or `LL_CC.ENCODING'. You can get the list of + locales supported by your system for your country by running the command + `locale -a | grep '^LL''. + + Not all programs have translations for all languages. By default, an + English message is shown in place of a nonexistent translation. If you + understand other languages, you can set up a priority list of languages. + This is done through a different environment variable, called + `LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' + for the purpose of message handling, but you still need to have `LANG' + set to the primary language; this is required by other parts of the + system libraries. For example, some Swedish users who would rather + read translations in German than English for when Swedish is not + available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. + + In the `LANGUAGE' environment variable, but not in the `LANG' + environment variable, `LL_CC' combinations can be abbreviated as `LL' + to denote the language's main dialect. For example, `de' is equivalent + to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' + (Portuguese as spoken in Portugal) in this context. + + Translating Teams + ================= + + For the Free Translation Project to be a success, we need interested + people who like their own language and write it well, and who are also + able to synergize with other translators speaking the same language. + Each translation team has its own mailing list. The up-to-date list of + teams can be found at the Free Translation Project's homepage, + `http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" + area. + + If you'd like to volunteer to _work_ at translating messages, you + should become a member of the translating team for your own language. + The subscribing address is _not_ the same as the list itself, it has + `-request' appended. For example, speakers of Swedish can send a + message to `sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate + _actively_ in translations, or at solving translational difficulties, + rather than merely lurking around. If your team does not exist yet and + you want to start one, or if you are unsure about what to do or how to + get started, please write to `translation@iro.umontreal.ca' to reach the + coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing + the terminology in use. Proven linguistic skill are praised more than + programming skill, here. + + Available Packages + ================== + + Languages are not equally supported in all packages. The following + matrix shows the current state of internationalization, as of May 2003. + The matrix shows, in regard of each package, for which languages PO + files have been submitted to translation coordination, with a + translation percentage of at least 50%. + + Ready PO files am az be bg ca cs da de el en en_GB eo es + +-------------------------------------------+ + a2ps | [] [] [] [] | + aegis | () | + anubis | | + ap-utils | | + bash | [] [] [] | + batchelor | | + bfd | [] [] | + binutils | [] [] | + bison | [] [] [] | + bluez-pin | [] [] | + clisp | | + clisp | [] [] [] | + coreutils | [] [] [] [] | + cpio | [] [] [] | + darkstat | () [] | + diffutils | [] [] [] [] [] [] [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] | + error | [] [] [] [] [] | + fetchmail | [] () [] [] [] [] | + fileutils | [] [] [] | + findutils | [] [] [] [] [] [] | + flex | [] [] [] [] | + gas | [] | + gawk | [] [] [] [] | + gcal | [] | + gcc | [] [] | + gettext | [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] | + gettext-tools | [] [] | + gimp-print | [] [] [] [] [] | + gliv | | + glunarclock | [] [] [] | + gnucash | () [] | + gnucash-glossary | [] () [] | + gnupg | [] () [] [] [] [] | + gpe-calendar | [] | + gpe-conf | [] | + gpe-contacts | [] | + gpe-edit | | + gpe-login | [] | + gpe-ownerinfo | [] | + gpe-sketchbook | [] | + gpe-timesheet | | + gpe-today | [] | + gpe-todo | [] | + gphoto2 | [] [] [] [] | + gprof | [] [] | + gpsdrive | () () () | + grep | [] [] [] [] [] | + gretl | [] | + hello | [] [] [] [] [] [] | + id-utils | [] [] | + indent | [] [] [] [] | + jpilot | [] [] [] [] | + jwhois | [] | + kbd | [] [] [] [] [] | + ld | [] [] | + libc | [] [] [] [] [] [] | + libgpewidget | [] | + libiconv | [] [] [] [] [] | + lifelines | [] () | + lilypond | [] | + lingoteach | | + lingoteach_lessons | () () | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailutils | [] [] | + make | [] [] [] | + man-db | [] () [] [] () | + mysecretdiary | [] [] [] | + nano | [] () [] [] [] | + nano_1_0 | [] () [] [] [] | + opcodes | [] [] | + parted | [] [] [] [] [] | + ptx | [] [] [] [] [] | + python | | + radius | | + recode | [] [] [] [] [] [] | + screem | | + sed | [] [] [] [] [] | + sh-utils | [] [] [] | + sharutils | [] [] [] [] [] [] | + sketch | [] () [] | + soundtracker | [] [] [] | + sp | [] | + tar | [] [] [] [] | + texinfo | [] [] [] [] | + textutils | [] [] [] [] | + tin | () () | + util-linux | [] [] [] [] [] | + vorbis-tools | [] [] [] | + wastesedge | () | + wdiff | [] [] [] [] | + wget | [] [] [] [] [] [] [] | + xchat | [] [] [] | + xpad | | + +-------------------------------------------+ + am az be bg ca cs da de el en en_GB eo es + 0 1 4 2 31 17 54 60 14 1 4 12 56 + + et fa fi fr ga gl he hr hu id it ja ko + +----------------------------------------+ + a2ps | [] [] [] () () | + aegis | | + anubis | [] | + ap-utils | [] | + bash | [] [] | + batchelor | [] | + bfd | [] [] | + binutils | [] [] | + bison | [] [] [] [] | + bluez-pin | [] [] [] [] | + clisp | | + clisp | [] | + coreutils | [] [] [] [] | + cpio | [] [] [] [] | + darkstat | () [] [] [] | + diffutils | [] [] [] [] [] [] [] | + e2fsprogs | | + enscript | [] [] | + error | [] [] [] [] | + fetchmail | [] | + fileutils | [] [] [] [] [] | + findutils | [] [] [] [] [] [] [] [] [] [] [] | + flex | [] [] | + gas | [] | + gawk | [] [] | + gcal | [] | + gcc | [] | + gettext | [] [] [] | + gettext-runtime | [] [] [] [] | + gettext-tools | [] | + gimp-print | [] [] | + gliv | () | + glunarclock | [] [] [] [] | + gnucash | [] | + gnucash-glossary | [] | + gnupg | [] [] [] [] [] [] [] | + gpe-calendar | [] | + gpe-conf | | + gpe-contacts | [] | + gpe-edit | [] [] | + gpe-login | [] | + gpe-ownerinfo | [] [] [] | + gpe-sketchbook | [] | + gpe-timesheet | [] [] [] | + gpe-today | [] [] | + gpe-todo | [] [] | + gphoto2 | [] [] [] | + gprof | [] [] | + gpsdrive | () [] () () | + grep | [] [] [] [] [] [] [] [] [] [] [] | + gretl | [] | + hello | [] [] [] [] [] [] [] [] [] [] [] [] [] | + id-utils | [] [] [] | + indent | [] [] [] [] [] [] [] [] | + jpilot | [] () | + jwhois | [] [] [] [] | + kbd | [] | + ld | [] | + libc | [] [] [] [] [] [] | + libgpewidget | [] [] [] | + libiconv | [] [] [] [] [] [] [] [] | + lifelines | () | + lilypond | [] | + lingoteach | [] [] | + lingoteach_lessons | | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailutils | | + make | [] [] [] [] [] [] | + man-db | [] () () | + mysecretdiary | [] [] | + nano | [] [] [] [] | + nano_1_0 | [] [] [] [] | + opcodes | [] [] | + parted | [] [] [] | + ptx | [] [] [] [] [] [] [] | + python | | + radius | | + recode | [] [] [] [] [] [] | + screem | | + sed | [] [] [] [] [] [] [] [] | + sh-utils | [] [] [] [] [] [] | + sharutils | [] [] [] [] [] | + sketch | [] | + soundtracker | [] [] [] | + sp | [] () | + tar | [] [] [] [] [] [] [] [] [] | + texinfo | [] [] [] [] | + textutils | [] [] [] [] [] | + tin | [] () | + util-linux | [] [] [] [] () [] | + vorbis-tools | [] | + wastesedge | () | + wdiff | [] [] [] [] [] | + wget | [] [] [] [] [] [] [] [] | + xchat | [] [] [] | + xpad | | + +----------------------------------------+ + et fa fi fr ga gl he hr hu id it ja ko + 20 1 15 73 14 24 8 10 30 31 19 31 9 + + lg lt lv ms nb nl nn no pl pt pt_BR ro + +----------------------------------------+ + a2ps | [] [] () () () [] [] | + aegis | () | + anubis | [] [] | + ap-utils | () | + bash | [] | + batchelor | | + bfd | | + binutils | | + bison | [] [] [] [] | + bluez-pin | [] | + clisp | | + clisp | [] | + coreutils | [] | + cpio | [] [] [] | + darkstat | [] [] [] [] | + diffutils | [] [] [] | + e2fsprogs | | + enscript | [] [] | + error | [] [] | + fetchmail | () () | + fileutils | [] | + findutils | [] [] [] [] | + flex | [] | + gas | | + gawk | [] | + gcal | | + gcc | | + gettext | [] | + gettext-runtime | [] | + gettext-tools | | + gimp-print | [] | + gliv | [] | + glunarclock | [] | + gnucash | | + gnucash-glossary | [] [] | + gnupg | | + gpe-calendar | [] [] | + gpe-conf | [] [] | + gpe-contacts | [] | + gpe-edit | [] [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] | + gpe-sketchbook | [] [] | + gpe-timesheet | [] [] | + gpe-today | [] [] | + gpe-todo | [] [] | + gphoto2 | | + gprof | [] | + gpsdrive | () () () | + grep | [] [] [] [] | + gretl | | + hello | [] [] [] [] [] [] [] [] [] | + id-utils | [] [] [] | + indent | [] [] [] | + jpilot | () () | + jwhois | [] [] [] | + kbd | | + ld | | + libc | [] [] [] [] | + libgpewidget | [] [] | + libiconv | [] [] | + lifelines | | + lilypond | [] | + lingoteach | | + lingoteach_lessons | | + lynx | [] [] | + m4 | [] [] [] [] | + mailutils | | + make | [] [] | + man-db | [] | + mysecretdiary | [] | + nano | [] [] [] [] | + nano_1_0 | [] [] [] [] | + opcodes | [] [] [] | + parted | [] [] [] | + ptx | [] [] [] [] [] [] [] | + python | | + radius | | + recode | [] [] [] | + screem | | + sed | [] [] | + sh-utils | [] | + sharutils | [] | + sketch | [] | + soundtracker | | + sp | | + tar | [] [] [] [] [] [] | + texinfo | [] | + textutils | [] | + tin | | + util-linux | [] [] | + vorbis-tools | [] [] | + wastesedge | | + wdiff | [] [] [] [] | + wget | [] [] [] | + xchat | [] [] | + xpad | [] | + +----------------------------------------+ + lg lt lv ms nb nl nn no pl pt pt_BR ro + 0 0 2 11 7 26 3 4 18 15 34 34 + + ru sk sl sr sv ta tr uk vi wa zh_CN zh_TW + +-------------------------------------------+ + a2ps | [] [] [] [] [] | 16 + aegis | () | 0 + anubis | [] [] | 5 + ap-utils | () | 1 + bash | [] | 7 + batchelor | | 1 + bfd | [] [] [] | 7 + binutils | [] [] [] | 7 + bison | [] [] | 13 + bluez-pin | | 7 + clisp | | 0 + clisp | | 5 + coreutils | [] [] [] [] [] | 14 + cpio | [] [] [] | 13 + darkstat | [] () () | 9 + diffutils | [] [] [] [] | 21 + e2fsprogs | [] | 3 + enscript | [] [] [] | 11 + error | [] [] [] | 14 + fetchmail | [] | 7 + fileutils | [] [] [] [] [] [] | 15 + findutils | [] [] [] [] [] [] | 27 + flex | [] [] [] | 10 + gas | [] | 3 + gawk | [] [] | 9 + gcal | [] [] | 4 + gcc | [] | 4 + gettext | [] [] [] [] [] [] | 15 + gettext-runtime | [] [] [] [] [] [] | 16 + gettext-tools | [] [] | 5 + gimp-print | [] [] | 10 + gliv | | 1 + glunarclock | [] [] [] | 11 + gnucash | [] [] | 4 + gnucash-glossary | [] [] [] | 8 + gnupg | [] [] [] [] | 16 + gpe-calendar | [] | 5 + gpe-conf | | 3 + gpe-contacts | [] | 4 + gpe-edit | [] | 5 + gpe-login | [] | 5 + gpe-ownerinfo | [] | 7 + gpe-sketchbook | [] | 5 + gpe-timesheet | [] | 6 + gpe-today | [] | 6 + gpe-todo | [] | 6 + gphoto2 | [] [] | 9 + gprof | [] [] | 7 + gpsdrive | [] [] | 3 + grep | [] [] [] [] | 24 + gretl | | 2 + hello | [] [] [] [] [] | 33 + id-utils | [] [] [] | 11 + indent | [] [] [] [] | 19 + jpilot | [] [] [] [] [] | 10 + jwhois | () () [] [] | 10 + kbd | [] [] | 8 + ld | [] [] | 5 + libc | [] [] [] [] | 20 + libgpewidget | | 6 + libiconv | [] [] [] [] [] [] | 21 + lifelines | [] | 2 + lilypond | [] | 4 + lingoteach | | 2 + lingoteach_lessons | () | 0 + lynx | [] [] [] [] | 14 + m4 | [] [] [] | 15 + mailutils | | 2 + make | [] [] [] [] | 15 + man-db | [] | 6 + mysecretdiary | [] [] | 8 + nano | [] [] [] | 15 + nano_1_0 | [] [] [] | 15 + opcodes | [] [] | 9 + parted | [] [] | 13 + ptx | [] [] [] | 22 + python | | 0 + radius | | 0 + recode | [] [] [] [] | 19 + screem | [] | 1 + sed | [] [] [] [] [] | 20 + sh-utils | [] [] [] | 13 + sharutils | [] [] [] [] | 16 + sketch | [] | 5 + soundtracker | [] | 7 + sp | [] | 3 + tar | [] [] [] [] [] | 24 + texinfo | [] [] [] [] | 13 + textutils | [] [] [] [] [] | 15 + tin | | 1 + util-linux | [] [] | 14 + vorbis-tools | [] | 7 + wastesedge | | 0 + wdiff | [] [] [] [] | 17 + wget | [] [] [] [] [] [] [] | 25 + xchat | [] [] [] | 11 + xpad | | 1 + +-------------------------------------------+ + 50 teams ru sk sl sr sv ta tr uk vi wa zh_CN zh_TW + 97 domains 32 19 16 0 56 0 48 10 1 1 12 23 913 + + Some counters in the preceding matrix are higher than the number of + visible blocks let us expect. This is because a few extra PO files are + used for implementing regional variants of languages, or language + dialects. + + For a PO file in the matrix above to be effective, the package to + which it applies should also have been internationalized and + distributed as such by its maintainer. There might be an observable + lag between the mere existence a PO file and its wide availability in a + distribution. + + If May 2003 seems to be old, you may fetch a more recent copy of + this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date + matrix with full percentage details can be found at + `http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. + + Using `gettext' in new packages + =============================== + + If you are writing a freely available program and want to + internationalize it you are welcome to use GNU `gettext' in your + package. Of course you have to respect the GNU Library General Public + License which covers the use of the GNU `gettext' library. This means + in particular that even non-free programs can use `libintl' as a shared + library, whereas only free software can use `libintl' as a static + library or use modified versions of `libintl'. + + Once the sources are changed appropriately and the setup can handle + the use of `gettext' the only thing missing are the translations. The + Free Translation Project is also available for packages which are not + developed inside the GNU project. Therefore the information given above + applies also for every other Free Software Project. Contact + `translation@iro.umontreal.ca' to make the `.pot' files available to + the translation teams. + diff -Nrc3pad gcc-3.3.3/boehm-gc/aix_irix_threads.c gcc-3.4.0/boehm-gc/aix_irix_threads.c *** gcc-3.3.3/boehm-gc/aix_irix_threads.c 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/aix_irix_threads.c 2003-07-28 03:46:08.000000000 +0000 *************** *** 0 **** --- 1,693 ---- + /* + * Copyright (c) 1991-1995 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. + * + * 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. + */ + /* + * Support code for Irix (>=6.2) Pthreads and for AIX pthreads. + * This relies on properties + * not guaranteed by the Pthread standard. It may or may not be portable + * to other implementations. + * + * Note that there is a lot of code duplication between this file and + * (pthread_support.c, pthread_stop_world.c). They should be merged. + * Pthread_support.c should be directly usable. + * + * Please avoid adding new ports here; use the generic pthread support + * as a base instead. + */ + + # if defined(GC_IRIX_THREADS) || defined(GC_AIX_THREADS) + + # include "private/gc_priv.h" + # include + # include + # include + # include + # include + # include + # include + # include + + #undef pthread_create + #undef pthread_sigmask + #undef pthread_join + + #if defined(GC_IRIX_THREADS) && !defined(MUTEX_RECURSIVE_NP) + #define MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE + #endif + + void GC_thr_init(); + + #if 0 + void GC_print_sig_mask() + { + sigset_t blocked; + int i; + + if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0) + ABORT("pthread_sigmask"); + GC_printf0("Blocked: "); + for (i = 1; i <= MAXSIG; i++) { + if (sigismember(&blocked, i)) { GC_printf1("%ld ",(long) i); } + } + GC_printf0("\n"); + } + #endif + + /* We use the allocation lock to protect thread-related data structures. */ + + /* The set of all known threads. We intercept thread creation and */ + /* joins. We never actually create detached threads. We allocate all */ + /* new thread stacks ourselves. These allow us to maintain this */ + /* data structure. */ + /* Protected by GC_thr_lock. */ + /* Some of this should be declared volatile, but that's incosnsistent */ + /* with some library routine declarations. */ + typedef struct GC_Thread_Rep { + struct GC_Thread_Rep * next; /* More recently allocated threads */ + /* with a given pthread id come */ + /* first. (All but the first are */ + /* guaranteed to be dead, but we may */ + /* not yet have registered the join.) */ + pthread_t id; + word stop; + # define NOT_STOPPED 0 + # define PLEASE_STOP 1 + # define STOPPED 2 + word flags; + # define FINISHED 1 /* Thread has exited. */ + # define DETACHED 2 /* Thread is intended to be detached. */ + ptr_t stack_cold; /* cold end of the stack */ + ptr_t stack_hot; /* Valid only when stopped. */ + /* But must be within stack region at */ + /* all times. */ + void * status; /* Used only to avoid premature */ + /* reclamation of any data it might */ + /* reference. */ + } * GC_thread; + + GC_thread GC_lookup_thread(pthread_t id); + + /* + * The only way to suspend threads given the pthread interface is to send + * signals. Unfortunately, this means we have to reserve + * a signal, and intercept client calls to change the signal mask. + */ + #if 0 /* DOB: 6.1 */ + # if defined(GC_AIX_THREADS) + # define SIG_SUSPEND SIGUSR1 + # else + # define SIG_SUSPEND (SIGRTMIN + 6) + # endif + #endif + + pthread_mutex_t GC_suspend_lock = PTHREAD_MUTEX_INITIALIZER; + /* Number of threads stopped so far */ + pthread_cond_t GC_suspend_ack_cv = PTHREAD_COND_INITIALIZER; + pthread_cond_t GC_continue_cv = PTHREAD_COND_INITIALIZER; + + void GC_suspend_handler(int sig) + { + int dummy; + GC_thread me; + sigset_t all_sigs; + sigset_t old_sigs; + int i; + + if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler"); + me = GC_lookup_thread(pthread_self()); + /* The lookup here is safe, since I'm doing this on behalf */ + /* of a thread which holds the allocation lock in order */ + /* to stop the world. Thus concurrent modification of the */ + /* data structure is impossible. */ + if (PLEASE_STOP != me -> stop) { + /* Misdirected signal. */ + pthread_mutex_unlock(&GC_suspend_lock); + return; + } + pthread_mutex_lock(&GC_suspend_lock); + me -> stack_hot = (ptr_t)(&dummy); + me -> stop = STOPPED; + pthread_cond_signal(&GC_suspend_ack_cv); + pthread_cond_wait(&GC_continue_cv, &GC_suspend_lock); + pthread_mutex_unlock(&GC_suspend_lock); + /* GC_printf1("Continuing 0x%x\n", pthread_self()); */ + } + + + GC_bool GC_thr_initialized = FALSE; + + + # define THREAD_TABLE_SZ 128 /* Must be power of 2 */ + volatile GC_thread GC_threads[THREAD_TABLE_SZ]; + + void GC_push_thread_structures GC_PROTO((void)) + { + GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads)); + } + + /* Add a thread to GC_threads. We assume it wasn't already there. */ + /* Caller holds allocation lock. */ + GC_thread GC_new_thread(pthread_t id) + { + int hv = ((word)id) % THREAD_TABLE_SZ; + GC_thread result; + static struct GC_Thread_Rep first_thread; + static GC_bool first_thread_used = FALSE; + + GC_ASSERT(I_HOLD_LOCK()); + if (!first_thread_used) { + result = &first_thread; + first_thread_used = TRUE; + /* Dont acquire allocation lock, since we may already hold it. */ + } else { + result = (struct GC_Thread_Rep *) + GC_generic_malloc_inner(sizeof(struct GC_Thread_Rep), NORMAL); + } + if (result == 0) return(0); + result -> id = id; + result -> next = GC_threads[hv]; + GC_threads[hv] = result; + /* result -> flags = 0; */ + /* result -> stop = 0; */ + return(result); + } + + /* Delete a thread from GC_threads. We assume it is there. */ + /* (The code intentionally traps if it wasn't.) */ + /* Caller holds allocation lock. */ + /* We explicitly pass in the GC_thread we're looking for, since */ + /* if a thread has been joined, but we have not yet */ + /* been notified, then there may be more than one thread */ + /* in the table with the same pthread id. */ + /* This is OK, but we need a way to delete a specific one. */ + void GC_delete_gc_thread(pthread_t id, GC_thread gc_id) + { + int hv = ((word)id) % THREAD_TABLE_SZ; + register GC_thread p = GC_threads[hv]; + register GC_thread prev = 0; + + GC_ASSERT(I_HOLD_LOCK()); + while (p != gc_id) { + prev = p; + p = p -> next; + } + if (prev == 0) { + GC_threads[hv] = p -> next; + } else { + prev -> next = p -> next; + } + } + + /* Return a GC_thread corresponding to a given thread_t. */ + /* Returns 0 if it's not there. */ + /* Caller holds allocation lock or otherwise inhibits */ + /* updates. */ + /* If there is more than one thread with the given id we */ + /* return the most recent one. */ + GC_thread GC_lookup_thread(pthread_t id) + { + int hv = ((word)id) % THREAD_TABLE_SZ; + register GC_thread p = GC_threads[hv]; + + /* I either hold the lock, or i'm being called from the stop-the-world + * handler. */ + #if defined(GC_AIX_THREADS) + GC_ASSERT(I_HOLD_LOCK()); /* no stop-the-world handler needed on AIX */ + #endif + while (p != 0 && !pthread_equal(p -> id, id)) p = p -> next; + return(p); + } + + #if defined(GC_AIX_THREADS) + void GC_stop_world() + { + pthread_t my_thread = pthread_self(); + register int i; + register GC_thread p; + register int result; + struct timespec timeout; + + GC_ASSERT(I_HOLD_LOCK()); + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + if (p -> id != my_thread) { + pthread_suspend_np(p->id); + } + } + } + /* GC_printf1("World stopped 0x%x\n", pthread_self()); */ + } + + void GC_start_world() + { + GC_thread p; + unsigned i; + pthread_t my_thread = pthread_self(); + + /* GC_printf0("World starting\n"); */ + GC_ASSERT(I_HOLD_LOCK()); + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + if (p -> id != my_thread) { + pthread_continue_np(p->id); + } + } + } + } + + #else /* GC_AIX_THREADS */ + + /* Caller holds allocation lock. */ + void GC_stop_world() + { + pthread_t my_thread = pthread_self(); + register int i; + register GC_thread p; + register int result; + struct timespec timeout; + + GC_ASSERT(I_HOLD_LOCK()); + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + if (p -> id != my_thread) { + if (p -> flags & FINISHED) { + p -> stop = STOPPED; + continue; + } + p -> stop = PLEASE_STOP; + result = pthread_kill(p -> id, SIG_SUSPEND); + /* GC_printf1("Sent signal to 0x%x\n", p -> id); */ + switch(result) { + case ESRCH: + /* Not really there anymore. Possible? */ + p -> stop = STOPPED; + break; + case 0: + break; + default: + ABORT("pthread_kill failed"); + } + } + } + } + pthread_mutex_lock(&GC_suspend_lock); + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + while (p -> id != my_thread && p -> stop != STOPPED) { + clock_gettime(CLOCK_REALTIME, &timeout); + timeout.tv_nsec += 50000000; /* 50 msecs */ + if (timeout.tv_nsec >= 1000000000) { + timeout.tv_nsec -= 1000000000; + ++timeout.tv_sec; + } + result = pthread_cond_timedwait(&GC_suspend_ack_cv, + &GC_suspend_lock, + &timeout); + if (result == ETIMEDOUT) { + /* Signal was lost or misdirected. Try again. */ + /* Duplicate signals should be benign. */ + result = pthread_kill(p -> id, SIG_SUSPEND); + } + } + } + } + pthread_mutex_unlock(&GC_suspend_lock); + /* GC_printf1("World stopped 0x%x\n", pthread_self()); */ + } + + /* Caller holds allocation lock. */ + void GC_start_world() + { + GC_thread p; + unsigned i; + + /* GC_printf0("World starting\n"); */ + GC_ASSERT(I_HOLD_LOCK()); + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + p -> stop = NOT_STOPPED; + } + } + pthread_mutex_lock(&GC_suspend_lock); + /* All other threads are at pthread_cond_wait in signal handler. */ + /* Otherwise we couldn't have acquired the lock. */ + pthread_mutex_unlock(&GC_suspend_lock); + pthread_cond_broadcast(&GC_continue_cv); + } + + #endif /* GC_AIX_THREADS */ + + + /* We hold allocation lock. Should do exactly the right thing if the */ + /* world is stopped. Should not fail if it isn't. */ + void GC_push_all_stacks() + { + register int i; + register GC_thread p; + register ptr_t hot, cold; + pthread_t me = pthread_self(); + + /* GC_init() should have been called before GC_push_all_stacks is + * invoked, and GC_init calls GC_thr_init(), which sets + * GC_thr_initialized. */ + GC_ASSERT(GC_thr_initialized); + + /* GC_printf1("Pushing stacks from thread 0x%x\n", me); */ + GC_ASSERT(I_HOLD_LOCK()); + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + if (p -> flags & FINISHED) continue; + cold = p->stack_cold; + if (!cold) cold=GC_stackbottom; /* 0 indicates 'original stack' */ + if (pthread_equal(p -> id, me)) { + hot = GC_approx_sp(); + } else { + # ifdef GC_AIX_THREADS + /* AIX doesn't use signals to suspend, so we need to get an */ + /* accurate hot stack pointer. */ + /* See http://publib16.boulder.ibm.com/pseries/en_US/libs/basetrf1/pthread_getthrds_np.htm */ + pthread_t id = p -> id; + struct __pthrdsinfo pinfo; + int regbuf[64]; + int val = sizeof(regbuf); + int retval = pthread_getthrds_np(&id, PTHRDSINFO_QUERY_ALL, &pinfo, + sizeof(pinfo), regbuf, &val); + if (retval != 0) { + printf("ERROR: pthread_getthrds_np() failed in GC\n"); + abort(); + } + /* according to the AIX ABI, + "the lowest possible valid stack address is 288 bytes (144 + 144) + less than the current value of the stack pointer. Functions may + use this stack space as volatile storage which is not preserved + across function calls." + ftp://ftp.penguinppc64.org/pub/people/amodra/PPC-elf64abi.txt.gz + */ + hot = (ptr_t)(unsigned long)pinfo.__pi_ustk-288; + cold = (ptr_t)pinfo.__pi_stackend; /* more precise */ + /* push the registers too, because they won't be on stack */ + GC_push_all_eager((ptr_t)&pinfo.__pi_context, + (ptr_t)((&pinfo.__pi_context)+1)); + GC_push_all_eager((ptr_t)regbuf, ((ptr_t)regbuf)+val); + # else + hot = p -> stack_hot; + # endif + } + # ifdef STACK_GROWS_UP + GC_push_all_stack(cold, hot); + # else + /* printf("thread 0x%x: hot=0x%08x cold=0x%08x\n", p -> id, hot, cold); */ + GC_push_all_stack(hot, cold); + # endif + } + } + } + + + /* We hold the allocation lock. */ + void GC_thr_init() + { + GC_thread t; + struct sigaction act; + + if (GC_thr_initialized) return; + #if 0 + /* unfortunately, GC_init_inner calls us without the lock, so + * this assertion is not always true. */ + /* Why doesn't GC_init_inner hold the lock? - HB */ + GC_ASSERT(I_HOLD_LOCK()); + #endif + GC_thr_initialized = TRUE; + #ifndef GC_AIX_THREADS + (void) sigaction(SIG_SUSPEND, 0, &act); + if (act.sa_handler != SIG_DFL) + ABORT("Previously installed SIG_SUSPEND handler"); + /* Install handler. */ + act.sa_handler = GC_suspend_handler; + act.sa_flags = SA_RESTART; + (void) sigemptyset(&act.sa_mask); + if (0 != sigaction(SIG_SUSPEND, &act, 0)) + ABORT("Failed to install SIG_SUSPEND handler"); + #endif + /* Add the initial thread, so we can stop it. */ + t = GC_new_thread(pthread_self()); + /* use '0' to indicate GC_stackbottom, since GC_init() has not + * completed by the time we are called (from GC_init_inner()) */ + t -> stack_cold = 0; /* the original stack. */ + t -> stack_hot = (ptr_t)(&t); + t -> flags = DETACHED; + } + + int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) + { + sigset_t fudged_set; + + #ifdef GC_AIX_THREADS + return(pthread_sigmask(how, set, oset)); + #endif + + if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) { + fudged_set = *set; + sigdelset(&fudged_set, SIG_SUSPEND); + set = &fudged_set; + } + return(pthread_sigmask(how, set, oset)); + } + + struct start_info { + void *(*start_routine)(void *); + void *arg; + word flags; + pthread_mutex_t registeredlock; + pthread_cond_t registered; + int volatile registereddone; + }; + + void GC_thread_exit_proc(void *arg) + { + GC_thread me; + + LOCK(); + me = GC_lookup_thread(pthread_self()); + me -> flags |= FINISHED; + /* reclaim DETACHED thread right away; otherwise wait until join() */ + if (me -> flags & DETACHED) { + GC_delete_gc_thread(pthread_self(), me); + } + UNLOCK(); + } + + int GC_pthread_join(pthread_t thread, void **retval) + { + int result; + GC_thread thread_gc_id; + + LOCK(); + thread_gc_id = GC_lookup_thread(thread); + /* This is guaranteed to be the intended one, since the thread id */ + /* cant have been recycled by pthreads. */ + UNLOCK(); + GC_ASSERT(!(thread_gc_id->flags & DETACHED)); + result = pthread_join(thread, retval); + /* Some versions of the Irix pthreads library can erroneously */ + /* return EINTR when the call succeeds. */ + if (EINTR == result) result = 0; + GC_ASSERT(thread_gc_id->flags & FINISHED); + LOCK(); + /* Here the pthread thread id may have been recycled. */ + GC_delete_gc_thread(thread, thread_gc_id); + UNLOCK(); + return result; + } + + void * GC_start_routine(void * arg) + { + int dummy; + struct start_info * si = arg; + void * result; + GC_thread me; + pthread_t my_pthread; + void *(*start)(void *); + void *start_arg; + + my_pthread = pthread_self(); + /* If a GC occurs before the thread is registered, that GC will */ + /* ignore this thread. That's fine, since it will block trying to */ + /* acquire the allocation lock, and won't yet hold interesting */ + /* pointers. */ + LOCK(); + /* We register the thread here instead of in the parent, so that */ + /* we don't need to hold the allocation lock during pthread_create. */ + /* Holding the allocation lock there would make REDIRECT_MALLOC */ + /* impossible. It probably still doesn't work, but we're a little */ + /* closer ... */ + /* This unfortunately means that we have to be careful the parent */ + /* doesn't try to do a pthread_join before we're registered. */ + me = GC_new_thread(my_pthread); + me -> flags = si -> flags; + me -> stack_cold = (ptr_t) &dummy; /* this now the 'start of stack' */ + me -> stack_hot = me->stack_cold;/* this field should always be sensible */ + UNLOCK(); + start = si -> start_routine; + start_arg = si -> arg; + + pthread_mutex_lock(&(si->registeredlock)); + si->registereddone = 1; + pthread_cond_signal(&(si->registered)); + pthread_mutex_unlock(&(si->registeredlock)); + /* si went away as soon as we did this unlock */ + + pthread_cleanup_push(GC_thread_exit_proc, 0); + result = (*start)(start_arg); + me -> status = result; + pthread_cleanup_pop(1); + /* This involves acquiring the lock, ensuring that we can't exit */ + /* while a collection that thinks we're alive is trying to stop */ + /* us. */ + return(result); + } + + int + GC_pthread_create(pthread_t *new_thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) + { + int result; + GC_thread t; + int detachstate; + word my_flags = 0; + struct start_info * si; + /* This is otherwise saved only in an area mmapped by the thread */ + /* library, which isn't visible to the collector. */ + + LOCK(); + /* GC_INTERNAL_MALLOC implicitly calls GC_init() if required */ + si = (struct start_info *)GC_INTERNAL_MALLOC(sizeof(struct start_info), + NORMAL); + GC_ASSERT(GC_thr_initialized); /* initialized by GC_init() */ + UNLOCK(); + if (0 == si) return(ENOMEM); + pthread_mutex_init(&(si->registeredlock), NULL); + pthread_cond_init(&(si->registered),NULL); + pthread_mutex_lock(&(si->registeredlock)); + si -> start_routine = start_routine; + si -> arg = arg; + + pthread_attr_getdetachstate(attr, &detachstate); + if (PTHREAD_CREATE_DETACHED == detachstate) my_flags |= DETACHED; + si -> flags = my_flags; + result = pthread_create(new_thread, attr, GC_start_routine, si); + + /* Wait until child has been added to the thread table. */ + /* This also ensures that we hold onto si until the child is done */ + /* with it. Thus it doesn't matter whether it is otherwise */ + /* visible to the collector. */ + + if (0 == result) { + si->registereddone = 0; + while (!si->registereddone) + pthread_cond_wait(&(si->registered), &(si->registeredlock)); + } + pthread_mutex_unlock(&(si->registeredlock)); + + pthread_cond_destroy(&(si->registered)); + pthread_mutex_destroy(&(si->registeredlock)); + LOCK(); + GC_INTERNAL_FREE(si); + UNLOCK(); + + return(result); + } + + /* For now we use the pthreads locking primitives on HP/UX */ + + VOLATILE GC_bool GC_collecting = 0; /* A hint that we're in the collector and */ + /* holding the allocation lock for an */ + /* extended period. */ + + /* Reasonably fast spin locks. Basically the same implementation */ + /* as STL alloc.h. */ + + #define SLEEP_THRESHOLD 3 + + volatile unsigned int GC_allocate_lock = 0; + #define GC_TRY_LOCK() !GC_test_and_set(&GC_allocate_lock) + #define GC_LOCK_TAKEN GC_allocate_lock + + void GC_lock() + { + # define low_spin_max 30 /* spin cycles if we suspect uniprocessor */ + # define high_spin_max 1000 /* spin cycles for multiprocessor */ + static unsigned spin_max = low_spin_max; + unsigned my_spin_max; + static unsigned last_spins = 0; + unsigned my_last_spins; + volatile unsigned junk; + # define PAUSE junk *= junk; junk *= junk; junk *= junk; junk *= junk + int i; + + if (GC_TRY_LOCK()) { + return; + } + junk = 0; + my_spin_max = spin_max; + my_last_spins = last_spins; + for (i = 0; i < my_spin_max; i++) { + if (GC_collecting) goto yield; + if (i < my_last_spins/2 || GC_LOCK_TAKEN) { + PAUSE; + continue; + } + if (GC_TRY_LOCK()) { + /* + * got it! + * Spinning worked. Thus we're probably not being scheduled + * against the other process with which we were contending. + * Thus it makes sense to spin longer the next time. + */ + last_spins = i; + spin_max = high_spin_max; + return; + } + } + /* We are probably being scheduled against the other process. Sleep. */ + spin_max = low_spin_max; + yield: + for (i = 0;; ++i) { + if (GC_TRY_LOCK()) { + return; + } + if (i < SLEEP_THRESHOLD) { + sched_yield(); + } else { + struct timespec ts; + + if (i > 26) i = 26; + /* Don't wait for more than about 60msecs, even */ + /* under extreme contention. */ + ts.tv_sec = 0; + ts.tv_nsec = 1 << i; + nanosleep(&ts, 0); + } + } + } + + # else /* !GC_IRIX_THREADS && !GC_AIX_THREADS */ + + #ifndef LINT + int GC_no_Irix_threads; + #endif + + # endif /* IRIX_THREADS */ + diff -Nrc3pad gcc-3.3.3/boehm-gc/allchblk.c gcc-3.4.0/boehm-gc/allchblk.c *** gcc-3.3.3/boehm-gc/allchblk.c 2002-04-09 00:39:15.000000000 +0000 --- gcc-3.4.0/boehm-gc/allchblk.c 2003-07-28 04:18:20.000000000 +0000 *************** GC_bool GC_use_entire_heap = 0; *** 47,58 **** struct hblk * GC_hblkfreelist[N_HBLK_FLS+1] = { 0 }; #ifndef USE_MUNMAP word GC_free_bytes[N_HBLK_FLS+1] = { 0 }; /* Number of free bytes on each list. */ /* Is bytes + the number of free bytes on lists n .. N_HBLK_FLS */ /* > GC_max_large_allocd_bytes? */ ! GC_bool GC_enough_large_bytes_left(bytes,n) word bytes; int n; { --- 47,62 ---- struct hblk * GC_hblkfreelist[N_HBLK_FLS+1] = { 0 }; #ifndef USE_MUNMAP + word GC_free_bytes[N_HBLK_FLS+1] = { 0 }; /* Number of free bytes on each list. */ /* Is bytes + the number of free bytes on lists n .. N_HBLK_FLS */ /* > GC_max_large_allocd_bytes? */ ! # ifdef __GNUC__ ! __inline__ ! # endif ! static GC_bool GC_enough_large_bytes_left(bytes,n) word bytes; int n; { *************** int n; *** 583,593 **** if (!GC_use_entire_heap && size_avail != size_needed && USED_HEAP_SIZE >= GC_requested_heapsize ! && !GC_incremental && GC_should_collect()) { # ifdef USE_MUNMAP continue; # else ! /* If we enough large blocks left to cover any */ /* previous request for large blocks, we go ahead */ /* and split. Assuming a steady state, that should */ /* be safe. It means that we can use the full */ --- 587,597 ---- if (!GC_use_entire_heap && size_avail != size_needed && USED_HEAP_SIZE >= GC_requested_heapsize ! && !TRUE_INCREMENTAL && GC_should_collect()) { # ifdef USE_MUNMAP continue; # else ! /* If we have enough large blocks left to cover any */ /* previous request for large blocks, we go ahead */ /* and split. Assuming a steady state, that should */ /* be safe. It means that we can use the full */ *************** int n; *** 595,600 **** --- 599,610 ---- if (!GC_enough_large_bytes_left(GC_large_allocd_bytes, n)) { continue; } + /* If we are deallocating lots of memory from */ + /* finalizers, fail and collect sooner rather */ + /* than later. */ + if (GC_finalizer_mem_freed > (GC_heapsize >> 4)) { + continue; + } # endif /* !USE_MUNMAP */ } /* If the next heap block is obviously better, go on. */ diff -Nrc3pad gcc-3.3.3/boehm-gc/alloc.c gcc-3.4.0/boehm-gc/alloc.c *** gcc-3.3.3/boehm-gc/alloc.c 2003-03-04 06:38:30.000000000 +0000 --- gcc-3.4.0/boehm-gc/alloc.c 2003-07-28 04:18:20.000000000 +0000 *************** int GC_full_freq = 19; /* Every 20th *** 72,77 **** --- 72,84 ---- GC_bool GC_need_full_gc = FALSE; /* Need full GC do to heap growth. */ + #ifdef THREADS + GC_bool GC_world_stopped = FALSE; + # define IF_THREADS(x) x + #else + # define IF_THREADS(x) + #endif + word GC_used_heap_size_after_full = 0; char * GC_copyright[] = *************** static word min_words_allocd() *** 160,166 **** + (GC_large_free_bytes >> 2) /* use a bit more of large empty heap */ + total_root_size); ! if (GC_incremental) { return scan_size / (2 * GC_free_space_divisor); } else { return scan_size / GC_free_space_divisor; --- 167,173 ---- + (GC_large_free_bytes >> 2) /* use a bit more of large empty heap */ + total_root_size); ! if (TRUE_INCREMENTAL) { return scan_size / (2 * GC_free_space_divisor); } else { return scan_size / GC_free_space_divisor; *************** word GC_adj_words_allocd() *** 182,188 **** /* managed object should not alter result, assuming the client */ /* is playing by the rules. */ result = (signed_word)GC_words_allocd ! - (signed_word)GC_mem_freed - expl_managed; if (result > (signed_word)GC_words_allocd) { result = GC_words_allocd; /* probably client bug or unfortunate scheduling */ --- 189,196 ---- /* managed object should not alter result, assuming the client */ /* is playing by the rules. */ result = (signed_word)GC_words_allocd ! - (signed_word)GC_mem_freed ! + (signed_word)GC_finalizer_mem_freed - expl_managed; if (result > (signed_word)GC_words_allocd) { result = GC_words_allocd; /* probably client bug or unfortunate scheduling */ *************** void GC_maybe_gc() *** 250,256 **** if (GC_should_collect()) { if (!GC_incremental) { - GC_notify_full_gc(); GC_gcollect_inner(); n_partial_gcs = 0; return; --- 258,263 ---- *************** void GC_maybe_gc() *** 302,311 **** --- 309,322 ---- /* * Stop the world garbage collection. Assumes lock held, signals disabled. * 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_bool GC_try_to_collect_inner(stop_func) GC_stop_func stop_func; { + # ifdef CONDPRINT + CLOCK_TYPE start_time, current_time; + # endif if (GC_dont_gc) return FALSE; if (GC_incremental && GC_collection_in_progress()) { # ifdef CONDPRINT *************** GC_stop_func stop_func; *** 320,327 **** --- 331,340 ---- GC_collect_a_little_inner(1); } } + if (stop_func == GC_never_stop_func) GC_notify_full_gc(); # ifdef CONDPRINT if (GC_print_stats) { + if (GC_print_stats) GET_TIME(start_time); GC_printf2( "Initiating full world-stop collection %lu after %ld allocd bytes\n", (unsigned long) GC_gc_no+1, *************** GC_stop_func stop_func; *** 360,365 **** --- 373,385 ---- return(FALSE); } GC_finish_collection(); + # if defined(CONDPRINT) + if (GC_print_stats) { + GET_TIME(current_time); + GC_printf1("Complete collection took %lu msecs\n", + MS_TIME_DIFF(current_time,start_time)); + } + # endif return(TRUE); } *************** int GC_collect_a_little GC_PROTO(()) *** 430,435 **** --- 450,456 ---- result = (int)GC_collection_in_progress(); UNLOCK(); ENABLE_SIGNALS(); + if (!result && GC_debugging_started) GC_print_all_smashed(); return(result); } *************** GC_stop_func stop_func; *** 448,463 **** CLOCK_TYPE start_time, current_time; # endif - # if defined(REGISTER_LIBRARIES_EARLY) - GC_cond_register_dynamic_libraries(); - # endif - STOP_WORLD(); # ifdef PRINTTIMES GET_TIME(start_time); # endif # if defined(CONDPRINT) && !defined(PRINTTIMES) if (GC_print_stats) GET_TIME(start_time); # endif # ifdef CONDPRINT if (GC_print_stats) { GC_printf1("--> Marking for collection %lu ", --- 469,485 ---- CLOCK_TYPE start_time, current_time; # endif # ifdef PRINTTIMES GET_TIME(start_time); # endif # if defined(CONDPRINT) && !defined(PRINTTIMES) if (GC_print_stats) GET_TIME(start_time); # endif + # if defined(REGISTER_LIBRARIES_EARLY) + GC_cond_register_dynamic_libraries(); + # endif + STOP_WORLD(); + IF_THREADS(GC_world_stopped = TRUE); # ifdef CONDPRINT if (GC_print_stats) { GC_printf1("--> Marking for collection %lu ", *************** GC_stop_func stop_func; *** 488,493 **** --- 510,516 ---- } # endif GC_deficit = i; /* Give the mutator a chance. */ + IF_THREADS(GC_world_stopped = FALSE); START_WORLD(); return(FALSE); } *************** GC_stop_func stop_func; *** 521,526 **** --- 544,551 ---- (*GC_check_heap)(); } + IF_THREADS(GC_world_stopped = FALSE); + START_WORLD(); # ifdef PRINTTIMES GET_TIME(current_time); GC_printf1("World-stopped marking took %lu msecs\n", *************** GC_stop_func stop_func; *** 534,540 **** } # endif # endif - START_WORLD(); return(TRUE); } --- 559,564 ---- *************** void GC_finish_collection() *** 611,616 **** --- 635,641 ---- GC_print_address_map(); } # endif + COND_DUMP; if (GC_find_leak) { /* Mark all objects on the free list. All objects should be */ /* marked when we're done. */ *************** void GC_finish_collection() *** 707,712 **** --- 732,738 ---- GC_words_allocd = 0; GC_words_wasted = 0; GC_mem_freed = 0; + GC_finalizer_mem_freed = 0; # ifdef USE_MUNMAP GC_unmap_old(); *************** void GC_finish_collection() *** 730,735 **** --- 756,762 ---- int result; DCL_LOCK_STATE; + if (GC_debugging_started) GC_print_all_smashed(); GC_INVOKE_FINALIZERS(); DISABLE_SIGNALS(); LOCK(); *************** void GC_finish_collection() *** 741,754 **** EXIT_GC(); UNLOCK(); ENABLE_SIGNALS(); ! if(result) GC_INVOKE_FINALIZERS(); return(result); } void GC_gcollect GC_PROTO(()) { - GC_notify_full_gc(); (void)GC_try_to_collect(GC_never_stop_func); } word GC_n_heap_sects = 0; /* Number of sections currently in heap. */ --- 768,784 ---- EXIT_GC(); UNLOCK(); ENABLE_SIGNALS(); ! if(result) { ! if (GC_debugging_started) GC_print_all_smashed(); ! GC_INVOKE_FINALIZERS(); ! } return(result); } void GC_gcollect GC_PROTO(()) { (void)GC_try_to_collect(GC_never_stop_func); + if (GC_have_errors) GC_print_all_errors(); } word GC_n_heap_sects = 0; /* Number of sections currently in heap. */ *************** GC_bool ignore_off_page; *** 950,956 **** { if (!GC_incremental && !GC_dont_gc && (GC_dont_expand && GC_words_allocd > 0 || GC_should_collect())) { - GC_notify_full_gc(); GC_gcollect_inner(); } else { word blocks_to_get = GC_heapsize/(HBLKSIZE*GC_free_space_divisor) --- 980,985 ---- *************** GC_bool ignore_off_page; *** 975,981 **** && !GC_expand_hp_inner(needed_blocks)) { if (GC_fail_count++ < GC_max_retries) { WARN("Out of Memory! Trying to continue ...\n", 0); - GC_notify_full_gc(); GC_gcollect_inner(); } else { # if !defined(AMIGA) || !defined(GC_AMIGA_FASTALLOC) --- 1004,1009 ---- *************** ptr_t GC_allocobj(sz, kind) *** 1005,1033 **** word sz; int kind; { ! register ptr_t * flh = &(GC_obj_kinds[kind].ok_freelist[sz]); if (sz == 0) return(0); while (*flh == 0) { ENTER_GC(); /* Do our share of marking work */ ! if(GC_incremental && !GC_dont_gc) GC_collect_a_little_inner(1); /* Sweep blocks for objects of this size */ ! GC_continue_reclaim(sz, kind); EXIT_GC(); if (*flh == 0) { GC_new_hblk(sz, kind); } if (*flh == 0) { ENTER_GC(); ! if (!GC_collect_or_expand((word)1,FALSE)) { EXIT_GC(); return(0); } EXIT_GC(); } } return(*flh); } --- 1033,1070 ---- word sz; int kind; { ! ptr_t * flh = &(GC_obj_kinds[kind].ok_freelist[sz]); ! GC_bool tried_minor = FALSE; if (sz == 0) return(0); while (*flh == 0) { ENTER_GC(); /* Do our share of marking work */ ! if(TRUE_INCREMENTAL) GC_collect_a_little_inner(1); /* Sweep blocks for objects of this size */ ! GC_continue_reclaim(sz, kind); EXIT_GC(); if (*flh == 0) { GC_new_hblk(sz, kind); } if (*flh == 0) { ENTER_GC(); ! if (GC_incremental && GC_time_limit == GC_TIME_UNLIMITED ! && ! tried_minor ) { ! GC_collect_a_little_inner(1); ! tried_minor = TRUE; ! } else { ! if (!GC_collect_or_expand((word)1,FALSE)) { EXIT_GC(); return(0); + } } EXIT_GC(); } } + /* Successful allocation; reset failure count. */ + GC_fail_count = 0; return(*flh); } diff -Nrc3pad gcc-3.3.3/boehm-gc/alpha_mach_dep.s gcc-3.4.0/boehm-gc/alpha_mach_dep.s *** gcc-3.3.3/boehm-gc/alpha_mach_dep.s 2001-08-17 18:30:45.000000000 +0000 --- gcc-3.4.0/boehm-gc/alpha_mach_dep.s 1970-01-01 00:00:00.000000000 +0000 *************** *** 1,86 **** - .arch ev6 - - .text - .align 4 - .globl GC_push_regs - .ent GC_push_regs 2 - GC_push_regs: - ldgp $gp, 0($27) - lda $sp, -16($sp) - stq $26, 0($sp) - .mask 0x04000000, 0 - .frame $sp, 16, $26, 0 - - # $0 integer result - # $1-$8 temp regs - not preserved cross calls - # $9-$15 call saved regs - # $16-$21 argument regs - not preserved cross calls - # $22-$28 temp regs - not preserved cross calls - # $29 global pointer - not preserved cross calls - # $30 stack pointer - - # define call_push(x) \ - mov x, $16; \ - jsr $26, GC_push_one; \ - ldgp $gp, 0($26) - - call_push($9) - call_push($10) - call_push($11) - call_push($12) - call_push($13) - call_push($14) - call_push($15) - - # $f0-$f1 floating point results - # $f2-$f9 call saved regs - # $f10-$f30 temp regs - not preserved cross calls - - # Use the most efficient transfer method for this hardware. - # Bit 1 detects the FIX extension, which includes ftoit. - amask 2, $0 - bne $0, $use_stack - - #undef call_push - #define call_push(x) \ - ftoit x, $16; \ - jsr $26, GC_push_one; \ - ldgp $gp, 0($26) - - call_push($f2) - call_push($f3) - call_push($f4) - call_push($f5) - call_push($f6) - call_push($f7) - call_push($f8) - call_push($f9) - - ldq $26, 0($sp) - lda $sp, 16($sp) - ret $31, ($26), 1 - - .align 4 - $use_stack: - - #undef call_push - #define call_push(x) \ - stt x, 8($sp); \ - ldq $16, 8($sp); \ - jsr $26, GC_push_one; \ - ldgp $gp, 0($26) - - call_push($f2) - call_push($f3) - call_push($f4) - call_push($f5) - call_push($f6) - call_push($f7) - call_push($f8) - call_push($f9) - - ldq $26, 0($sp) - lda $sp, 16($sp) - ret $31, ($26), 1 - - .end GC_push_regs --- 0 ---- diff -Nrc3pad gcc-3.3.3/boehm-gc/alpha_mach_dep.S gcc-3.4.0/boehm-gc/alpha_mach_dep.S *** gcc-3.3.3/boehm-gc/alpha_mach_dep.S 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/alpha_mach_dep.S 2003-07-28 03:46:09.000000000 +0000 *************** *** 0 **** --- 1,87 ---- + # $Id: alpha_mach_dep.s,v 1.2 1993/01/18 22:54:51 dosser Exp $ + .arch ev6 + + .text + .align 4 + .globl GC_push_regs + .ent GC_push_regs 2 + GC_push_regs: + ldgp $gp, 0($27) + lda $sp, -16($sp) + stq $26, 0($sp) + .mask 0x04000000, 0 + .frame $sp, 16, $26, 0 + + # $0 integer result + # $1-$8 temp regs - not preserved cross calls + # $9-$15 call saved regs + # $16-$21 argument regs - not preserved cross calls + # $22-$28 temp regs - not preserved cross calls + # $29 global pointer - not preserved cross calls + # $30 stack pointer + + # define call_push(x) \ + mov x, $16; \ + jsr $26, GC_push_one; \ + ldgp $gp, 0($26) + + call_push($9) + call_push($10) + call_push($11) + call_push($12) + call_push($13) + call_push($14) + call_push($15) + + # $f0-$f1 floating point results + # $f2-$f9 call saved regs + # $f10-$f30 temp regs - not preserved cross calls + + # Use the most efficient transfer method for this hardware. + # Bit 1 detects the FIX extension, which includes ftoit. + amask 2, $0 + bne $0, $use_stack + + #undef call_push + #define call_push(x) \ + ftoit x, $16; \ + jsr $26, GC_push_one; \ + ldgp $gp, 0($26) + + call_push($f2) + call_push($f3) + call_push($f4) + call_push($f5) + call_push($f6) + call_push($f7) + call_push($f8) + call_push($f9) + + ldq $26, 0($sp) + lda $sp, 16($sp) + ret $31, ($26), 1 + + .align 4 + $use_stack: + + #undef call_push + #define call_push(x) \ + stt x, 8($sp); \ + ldq $16, 8($sp); \ + jsr $26, GC_push_one; \ + ldgp $gp, 0($26) + + call_push($f2) + call_push($f3) + call_push($f4) + call_push($f5) + call_push($f6) + call_push($f7) + call_push($f8) + call_push($f9) + + ldq $26, 0($sp) + lda $sp, 16($sp) + ret $31, ($26), 1 + + .end GC_push_regs diff -Nrc3pad gcc-3.3.3/boehm-gc/backgraph.c gcc-3.4.0/boehm-gc/backgraph.c *** gcc-3.3.3/boehm-gc/backgraph.c 2002-01-31 02:48:45.000000000 +0000 --- gcc-3.4.0/boehm-gc/backgraph.c 2003-07-28 04:18:20.000000000 +0000 *************** static void add_back_edges(ptr_t p, word *** 307,312 **** --- 307,313 ---- } while (currentp < (word *)(p + gc_descr)) { word current = *currentp++; + FIXUP_POINTER(current); if (current >= (word)GC_least_plausible_heap_addr && current <= (word)GC_greatest_plausible_heap_addr) { ptr_t target = GC_base((GC_PTR)current); diff -Nrc3pad gcc-3.3.3/boehm-gc/BCC_MAKEFILE gcc-3.4.0/boehm-gc/BCC_MAKEFILE *** gcc-3.3.3/boehm-gc/BCC_MAKEFILE 2001-08-17 18:30:44.000000000 +0000 --- gcc-3.4.0/boehm-gc/BCC_MAKEFILE 2003-07-28 04:18:19.000000000 +0000 *************** *** 1,29 **** ! # Makefile for Borland C++ 4.5 on NT ! # For Borland 5.0, replace bc45 by bc5. # If you have the Borland assembler, remove "-DUSE_GENERIC" # ! bc= c:\bc45 ! bcbin= $(bc)\bin ! bclib= $(bc)\lib bcinclude= $(bc)\include ! cc= $(bcbin)\bcc32 ! rc= $(bcbin)\brc32 ! lib= $(bcbin)\tlib ! link= $(bcbin)\tlink32 ! cflags= -R -v -vi -H -H=gc.csm -I$(bcinclude);cord -L$(bclib) \ ! -w-pro -w-aus -w-par -w-ccc -w-rch -a4 -D__STDC__=0 #defines= -DSILENT ! defines= -DSMALL_CONFIG -DSILENT -DALL_INTERIOR_POINTERS -DUSE_GENERIC .c.obj: $(cc) @&&| ! $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.c | .cpp.obj: $(cc) @&&| ! $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.cpp | .rc.res: --- 1,31 ---- ! # 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 ! ! 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 -D__STDC__=0 #defines= -DSILENT ! defines= -DSMALL_CONFIG -DSILENT -DALL_INTERIOR_POINTERS -DUSE_GENERIC -DNO_GETENV -DJAVA_FINALIZATION -DGC_OPERATOR_NEW_ARRAY .c.obj: $(cc) @&&| ! $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.c | .cpp.obj: $(cc) @&&| ! $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.cpp | .rc.res: *************** OBJS= $(XXXOBJS:XXX=) *** 39,69 **** all: gctest.exe cord\de.exe test_cpp.exe ! $(OBJS) test.obj: gc_priv.h gc_hdrs.h gc.h gcconfig.h MAKEFILE gc.lib: $(OBJS) ! -del gc.lib ! tlib $* @&&| ! $(XXXOBJS:XXX=+) | gctest.exe: tests\test.obj gc.lib $(cc) @&&| ! $(cflags) -W -e$* tests\test.obj gc.lib | ! cord\de.obj cord\de_win.obj: cord\cord.h cord\private\cord_pos.h cord\de_win.h \ cord\de_cmds.h cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj \ ! cord\de_win.res gc.lib $(cc) @&&| ! $(cflags) -W -e$* cord\cordbscs.obj cord\cordxtra.obj \ ! cord\de.obj cord\de_win.obj gc.lib | $(rc) cord\de_win.res cord\de.exe ! gc_cpp.obj: gc_cpp.h gc.h gc_cpp.cpp: gc_cpp.cc copy gc_cpp.cc gc_cpp.cpp --- 41,71 ---- 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 ! $(lib) $* @&&| ! $(XXXOBJS:XXX=+) | gctest.exe: tests\test.obj gc.lib $(cc) @&&| ! $(cflags) -W -e$* tests\test.obj gc.lib | ! cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h \ cord\de_cmds.h cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj \ ! cord\de_win.res gc.lib $(cc) @&&| ! $(cflags) -W -e$* cord\cordbscs.obj cord\cordxtra.obj \ ! cord\de.obj cord\de_win.obj gc.lib | $(rc) cord\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.cpp: gc_cpp.cc *** 71,82 **** test_cpp.cpp: tests\test_cpp.cc copy tests\test_cpp.cc test_cpp.cpp ! test_cpp.exe: test_cpp.obj gc_cpp.h gc.h gc.lib $(cc) @&&| ! $(cflags) -W -e$* test_cpp.obj gc.lib | scratch: -del *.obj *.res *.exe *.csm cord\*.obj cord\*.res cord\*.exe cord\*.csm --- 73,88 ---- 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) @&&| ! $(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 diff -Nrc3pad gcc-3.3.3/boehm-gc/ChangeLog gcc-3.4.0/boehm-gc/ChangeLog *** gcc-3.3.3/boehm-gc/ChangeLog 2004-02-14 20:16:39.000000000 +0000 --- gcc-3.4.0/boehm-gc/ChangeLog 2004-04-19 01:57:30.000000000 +0000 *************** *** 1,49 **** ! 2004-02-14 Release Manager ! * GCC 3.3.3 Released. ! 2003-12-21 Roger Sayle ! * configure.host: Backport/synchronize from mainline. ! 2003-10-16 Release Manager ! * GCC 3.3.2 Released. ! 2003-10-01 Rainer Orth * configure.in: Remove wildcard from Solaris 8-9/Intel and Solaris 2.3/SPARC, there are no micro versions. Treat Solaris 10 and up alike. * configure: Regenerate. 2003-09-09 Alan Modra * configure: Regenerate. ! 2003-08-04 Release Manager ! ! * GCC 3.3.1 Released. ! 2003-08-04 Release Manager ! * GCC 3.3.1 Released. ! 2003-05-13 Release Manager ! * GCC 3.3 Released. ! 2003-05-13 Release Manager ! * GCC 3.3 Released. ! 2003-05-13 Release Manager ! * GCC 3.3 Released. ! 2003-05-13 Release Manager ! * GCC 3.3 Released. 2003-04-28 Mohan Embar --- 1,197 ---- ! 2004-04-18 Release Manager ! * GCC 3.4.0 released. ! 2004-02-22 Matthias Klose ! * config.guess: Update from version 2002-01-10 to 2004-02-16. ! * config.sub: Update from version 2002-01-02 to 2004-02-16. ! 2004-01-20 Andrew Haley ! * include/private/gcconfig.h (USE_MMAP): Define for all Linux. ! * configure.in: Comment change. ! ! 2004-01-16 Andrew Haley ! ! * configure.in (NO_EXECUTE_PERMISSION): Remove global declaration; ! add for ia64; remove for MIPS. ! * configure: Regnerated. ! ! 2004-01-14 Kelley Cook ! ! * configure.in: Add in AC_PREREQ(2.13) ! ! 2004-01-07 Dave Jones ! ! * malloc.c (GC_generic_malloc): Correct initialization typo. ! * mallocx.c (GC_generic_malloc_ignore_off_page): Ditto. ! ! 2003-10-31 Richard Earnshaw ! ! * include/private/gcconfig.h: Re-install change of 2003-04-16. ! ! 2003-10-20 Rainer Orth ! ! * mips_sgi_mach_dep.s: Use _ABIO32 instead of external ! _MIPS_SIM_ABI32. ! ! 2003-10-18 Alan Modra ! ! * include/private/gcconfig.h (ALIGNMENT ): Remove ! unsure comment. ! ! 2003-10-03 Jeff Sturm ! ! * configure: Rebuild. ! ! 2003-10-03 Hans Boehm ! ! * configure.in: Remove NO_GETENV definition for win32. ! * mach_dep.c (GC_generic_push_regs): Prevent tail call optimization. ! * misc.c (GC_init_inner): Call GC_thr_init for win32. ! (GC_set_warn_proc): Add assertion. ! * win32_threads.c: Import 6.3alpha2 version. ! * include/private/gc_priv.h: Add support for EMPTY_GETENV_RESULTS. ! ! 2003-09-29 Rainer Orth * configure.in: Remove wildcard from Solaris 8-9/Intel and Solaris 2.3/SPARC, there are no micro versions. Treat Solaris 10 and up alike. * configure: Regenerate. + 2003-09-22 Anthony Green + + * os_dep.c: Fix GC_get_stack_base build problem for vanilla elf + "NOSYS" targets. + + 2003-09-20 + + * include/private/gcconfig.h: Don't check for __XSCALE__. Instead + check for __arm__ or __thumb__. + 2003-09-09 Alan Modra * configure: Regenerate. ! 2003-08-07 Rainer Orth ! Roger Sayle ! * configure.in: Set INCLUDES to absolute path. ! Save $INCLUDES in boehm-cflags, too. ! Set INCLUDES so it's available to config.status. ! * configure: Regenerate. ! 2003-07-31 Danny Smith ! * include/gc.h (GC_CreateThread): Declare with WINAPI ! attribute. ! * win32_threads.c (GC_CreateThread): Make definitions consistent ! with declaration. Cast &thread_table[i].handle to PHANDLE ! in call to DuplicateHandle ! (thread_start): Declare as static. ! 2003-07-30 Andreas Tobler ! * dyn_load.c: Define __private_extern__ to match Apple's system ! header. ! ! 2003-07-28 Loren J. Rittle ! * os_dep.c: Remove redundancy introduced in last merge. ! 2003-07-28 Jeff Sturm ! Import GC 6.3alpha1. ! * BCC_MAKEFILE: Merge with GC 6.3alpha1 release. ! * ChangeLog: Likewise. ! * Makefile.am: Likewise. ! * Makefile.direct: Likewise. ! * Makefile.dj: Likewise. ! * allchblk.c: Likewise. ! * alloc.c: Likewise. ! * backgraph.c: Likewise. ! * configure.host: Likewise. ! * configure.in: Likewise. ! * dbg_mlc.c: Likewise. ! * dyn_load.c: Likewise. ! * finalize.c: Likewise. ! * gc_cpp.cc: Likewise. ! * gc_dlopen.c: Likewise. ! * gcj_mlc.c: Likewise. ! * if_mach.c: Likewise. ! * mach_dep.c: Likewise. ! * malloc.c: Likewise. ! * mallocx.c: Likewise. ! * mark.c: Likewise. ! * mark_rts.c: Likewise. ! * misc.c: Likewise. ! * os_dep.c: Likewise. ! * ptr_chck.c: Likewise. ! * reclaim.c: Likewise. ! * solaris_pthreads.c: Likewise. ! * solaris_threads.c: Likewise. ! * sparc_mach_dep.S: Likewise. ! * threadlibs.c: Likewise. ! * typd_mlc.c: Likewise. ! * version.h: Likewise. ! * win32_threads.c: Likewise. ! * Mac_files/MacOS_Test_config.h: Likewise. ! * Mac_files/MacOS_config.h: Likewise. ! * cord/cordbscs.c: Likewise. ! * cord/cordprnt.c: Likewise. ! * cord/de_win.c: Likewise. ! * doc/README: Likewise. ! * doc/README.MacOSX: Likewise. ! * doc/README.changes: Likewise. ! * doc/README.environment: Likewise. ! * doc/README.ews4800: Likewise. ! * doc/README.linux: Likewise. ! * doc/README.macros: Likewise. ! * doc/README.win32: Likewise. ! * doc/debugging.html: Likewise. ! * doc/gcdescr.html: Likewise. ! * doc/tree.html: Likewise. ! * include/Makefile.in: Likewise. ! * include/gc.h: Likewise. ! * include/gc_cpp.h: Likewise. ! * include/gc_local_alloc.h: Likewise. ! * include/gc_mark.h: Likewise. ! * include/gc_pthread_redirects.h: Likewise. ! * include/gc_typed.h: Likewise. ! * include/new_gc_alloc.h: Likewise. ! * include/private/dbg_mlc.h: Likewise. ! * include/private/gc_hdrs.h: Likewise. ! * include/private/gc_locks.h: Likewise. ! * include/private/gc_pmark.h: Likewise. ! * include/private/gc_priv.h: Likewise. ! * include/private/gcconfig.h: Likewise. ! * include/private/solaris_threads.h: Likewise. ! * include/private/specific.h: Likewise. ! * tests/test.c: Likewise. ! * tests/test_cpp.cc: Likewise. ! ! * configure: Rebuild. ! * Makefile.in: Rebuild. ! ! * mips_sgi_mach_dep.s: Add. ! ! * alpha_mach_dep.s: Remove. ! * irix_threads.c: Remove. ! * linux_threads.c: Remove. ! * mips_sgi_mach_dep.S: Remove. ! * missing: Remove. ! * powerpc_macosx_mach_dep.s: Remove. ! * doc/Makefile.am: Remove. ! * doc/Makefile.in: Remove. ! 2003-07-25 Roger Sayle ! * configure.host: Only use +ESdbgasm when using the HPUX native ! compiler on PA-Risc. It isn't recognized by GCC and is silently ! ignored by HP's compilers on ia64. 2003-04-28 Mohan Embar *************** *** 51,66 **** --- 199,236 ---- * configure: rebuilt * win32_threads.c: add #ifdef GC_DLL around DllMain + 2003-04-16 Richard Earnshaw + + * include/private/gcconfig.h: Add support for arm-netbsdelf. + 2003-04-09 Tom Tromey * include/private/gcconfig.h (LINUX_STACKBOTTOM): Define for POWERPC. (STACK_GRAN, HEURISTIC1): Don't define for POWERPC. + 2003-03-22 Richard Henderson + + * include/private/gc_locks.h [IA64]: Include ia64intrin.h. + (GC_test_and_set): Use __sync_lock_test_and_set. + (GC_clear): Use volatile assignment. + (GC_compare_and_exchange): Use __sync_bool_compare_and_swap. + (GC_memory_write_barrier): Use __sync_synchronize. + + 2003-03-12 Andreas Schwab + + * configure.in: Avoid trailing /. in toolexeclibdir. + * configure: Rebuilt. + 2003-03-04 Hans Boehm * include/private/gcconfig.h (GC_data_start): declare when needed. * include/private/gc_priv.h: Include gcconfig.h after ptr_t declaration. + * dyn_load.c (GC_register_dynamic_libraries_dl_iterate_phdr, + GC_register_dynlib_callback): Register main data for static + executable if dl_iterate_phdr() didn't. + * misc.c (GC_init_inner): Call GC_init_linux_data_start() even + if we don't expect to register main static data. 2003-03-03 Hans Boehm * mark_rts.c (GC_cond_register_dynamic_libraries): add. *************** *** 71,77 **** (GC_collect_a_little_inner, GC_try_to_collect_inner): Check GC_dont_gc. * dyn_load.c (GC_register_main_static_data): define. (GC_register_dyn_libraries (Linux /proc, Linux ELF versions)): ! no longer skip main data. Register main data for static executable. * misc.c (GC_REGISTER_MAIN_STATIC_DATA): define. (GC_init_inner): Make main data registration conditional. * include/private/gc_priv.h (GC_register_main_static_data): declare. --- 241,247 ---- (GC_collect_a_little_inner, GC_try_to_collect_inner): Check GC_dont_gc. * dyn_load.c (GC_register_main_static_data): define. (GC_register_dyn_libraries (Linux /proc, Linux ELF versions)): ! no longer skip main data. * misc.c (GC_REGISTER_MAIN_STATIC_DATA): define. (GC_init_inner): Make main data registration conditional. * include/private/gc_priv.h (GC_register_main_static_data): declare. diff -Nrc3pad gcc-3.3.3/boehm-gc/config.guess gcc-3.4.0/boehm-gc/config.guess *** gcc-3.3.3/boehm-gc/config.guess 2002-02-12 04:37:53.000000000 +0000 --- gcc-3.4.0/boehm-gc/config.guess 2004-02-22 14:43:48.000000000 +0000 *************** *** 1,9 **** #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, ! # 2000, 2001, 2002 Free Software Foundation, Inc. ! timestamp='2002-01-10' # 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 --- 1,9 ---- #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, ! # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. ! timestamp='2004-02-16' # 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 *************** if test $# != 0; then *** 88,117 **** exit 1 fi ! dummy=dummy-$$ ! trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 - # CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. ! set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in ! ,,) echo "int dummy(){}" > $dummy.c ; ! for c in cc gcc c89 ; do ! ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; ! if test $? = 0 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; - rm -f $dummy.c $dummy.o $dummy.rel ; 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' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) --- 88,129 ---- 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 -q "$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 ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) *************** case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$ *** 138,146 **** # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". ! UNAME_MACHINE_ARCH=`(uname -p) 2>/dev/null` || \ ! UNAME_MACHINE_ARCH=unknown case "${UNAME_MACHINE_ARCH}" in arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; --- 150,160 ---- # # 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 ;; *************** case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$ *** 166,183 **** ;; esac # The OS release ! release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` # 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 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; --- 180,214 ---- ;; 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 0 ;; + amd64:OpenBSD:*:*) + echo x86_64-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; + cats:OpenBSD:*:*) + echo arm-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *************** case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$ *** 196,201 **** --- 227,235 ---- mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; + pegasos:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *************** case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$ *** 211,279 **** *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # 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. - cat <$dummy.s - .data - \$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main - main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main - EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - 2-1307) - UNAME_MACHINE="alphaev68" - ;; - esac - fi - rm -f $dummy.s $dummy echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; 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 --- 245,309 ---- *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit 0 ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi + # 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 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/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; + Alpha*:OpenVMS:*:*) + echo alpha-hp-vms + exit 0 ;; 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 *************** EOF *** 295,300 **** --- 325,333 ---- *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; *************** EOF *** 312,317 **** --- 345,357 ---- NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *************** EOF *** 340,346 **** echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) ! UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) --- 380,386 ---- echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; 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) *************** EOF *** 380,385 **** --- 420,428 ---- *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; *************** EOF *** 418,432 **** exit (-1); } EOF ! $CC_FOR_BUILD $dummy.c -o $dummy \ ! && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ ! && rm -f $dummy.c $dummy && exit 0 ! rm -f $dummy.c $dummy echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; --- 461,480 ---- exit (-1); } EOF ! $CC_FOR_BUILD -o $dummy $dummy.c \ ! && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ ! && exit 0 echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; *************** EOF *** 499,506 **** exit(0); } EOF ! $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 ! rm -f $dummy.c $dummy echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 --- 547,553 ---- exit(0); } EOF ! $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 *************** EOF *** 509,515 **** fi exit 0 ;; *:AIX:*:[45]) ! IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else --- 556,562 ---- fi exit 0 ;; *:AIX:*:[45]) ! 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 *************** EOF *** 598,608 **** exit (0); } EOF ! (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` ! if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi ! rm -f $dummy.c $dummy fi ;; esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) --- 645,665 ---- 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 + # avoid double evaluation of $set_cc_for_build + test -n "$CC_FOR_BUILD" || eval $set_cc_for_build + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) *************** EOF *** 636,643 **** exit (0); } EOF ! $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 ! rm -f $dummy.c $dummy echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) --- 693,699 ---- exit (0); } EOF ! $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) *************** EOF *** 683,691 **** C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; - CRAY*X-MP:*:*:*) - echo xmp-cray-unicos - exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; --- 739,744 ---- *************** EOF *** 698,721 **** CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; ! CRAY-2:*:*:*) ! echo cray2-cray-unicos ! exit 0 ;; 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 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; --- 751,776 ---- CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; ! *:UNICOS/mp:*:*) ! echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' ! exit 0 ;; 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 0 ;; + 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 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; *************** EOF *** 726,732 **** echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) ! echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin --- 781,801 ---- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) ! # Determine whether the default compiler uses glibc. ! eval $set_cc_for_build ! sed 's/^ //' << EOF >$dummy.c ! #include ! #if __GLIBC__ >= 2 ! LIBC=gnu ! #else ! LIBC= ! #endif ! EOF ! eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` ! # GNU/KFreeBSD systems have a "k" prefix to indicate we are using ! # FreeBSD's kernel, but not the complete OS. ! case ${LIBC} in gnu) kernel_only='k' ;; esac ! echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin *************** EOF *** 737,750 **** i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; ! x86:Interix*:3*) ! echo i386-pc-interix3 exit 0 ;; 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 i386-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin --- 806,822 ---- i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; ! x86:Interix*:[34]*) ! echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' ! exit 0 ;; ! [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) ! echo i${UNAME_MACHINE}-pc-mks exit 0 ;; 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 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin *************** EOF *** 756,771 **** echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; ia64:Linux:*:*) ! echo ${UNAME_MACHINE}-unknown-linux exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu --- 828,851 ---- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) + # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; + *: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/[-(].*//'`-gnu + exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit 0 ;; ia64:Linux:*:*) ! echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu *************** EOF *** 776,794 **** #undef CPU #undef mips #undef mipsel ! #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) ! CPU=mipsel #else ! #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif ! #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` ! rm -f $dummy.c ! test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu --- 856,892 ---- #undef CPU #undef mips #undef mipsel ! #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) ! CPU=mipsel #else ! #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #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-gnu" && exit 0 ! ;; ! mips64:Linux:*:*) ! eval $set_cc_for_build ! sed 's/^ //' << EOF >$dummy.c ! #undef CPU ! #undef mips64 ! #undef mips64el ! #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) ! CPU=mips64el ! #else ! #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) ! CPU=mips64 ! #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-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu *************** EOF *** 824,829 **** --- 922,930 ---- s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; *************** EOF *** 837,843 **** # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. ! ld_supported_targets=`cd /; ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// --- 938,945 ---- # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. ! # Set LC_ALL=C to ensure ld outputs messages in English. ! ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// *************** EOF *** 849,855 **** ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ! exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; --- 951,957 ---- ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ! exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; *************** EOF *** 874,884 **** LIBC=gnulibc1 # endif #else LIBC=gnuaout #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - rm -f $dummy.c test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; --- 976,992 ---- LIBC=gnulibc1 # endif #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else LIBC=gnuaout #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; *************** EOF *** 896,901 **** --- 1004,1029 ---- # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; + 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 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; 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 *************** EOF *** 917,938 **** UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then ! UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` ! (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 ! (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 ! (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ && UNAME_MACHINE=i686 ! (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about --- 1045,1063 ---- 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 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about *************** EOF *** 956,964 **** # "miniframe" echo m68010-convergent-sysv exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; ! 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` --- 1081,1095 ---- # "miniframe" echo m68010-convergent-sysv exit 0 ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; ! 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) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` *************** EOF *** 975,983 **** mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; --- 1106,1111 ---- *************** EOF *** 1049,1054 **** --- 1177,1185 ---- SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *************** EOF *** 1056,1073 **** echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) ! echo `uname -p`-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) ! if test "${UNAME_MACHINE}" = "x86pc"; then UNAME_MACHINE=pc fi ! echo `uname -p`-${UNAME_MACHINE}-nto-qnx exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; ! NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) --- 1187,1210 ---- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) ! case `uname -p` in ! *86) UNAME_PROCESSOR=i686 ;; ! powerpc) UNAME_PROCESSOR=powerpc ;; ! esac ! echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; *: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 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; ! NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) *************** EOF *** 1090,1100 **** fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; - 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 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; --- 1227,1232 ---- *************** EOF *** 1113,1123 **** *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; ! i*86:XTS-300:*:STOP) ! echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; ! i*86:atheos:*:*) ! echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; esac --- 1245,1255 ---- *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; ! SEI:*:*:SEIUX) ! echo mips-sei-seiux${UNAME_RELEASE} exit 0 ;; ! *:DragonFly:*:*) ! echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; esac *************** main () *** 1239,1246 **** } EOF ! $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 ! rm -f $dummy.c $dummy # Apollos put the system type in the environment. --- 1371,1377 ---- } EOF ! $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 # Apollos put the system type in the environment. diff -Nrc3pad gcc-3.3.3/boehm-gc/config.sub gcc-3.4.0/boehm-gc/config.sub *** gcc-3.3.3/boehm-gc/config.sub 2002-02-12 04:37:53.000000000 +0000 --- gcc-3.4.0/boehm-gc/config.sub 2004-02-22 14:43:48.000000000 +0000 *************** *** 1,9 **** #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, ! # 2000, 2001, 2002 Free Software Foundation, Inc. ! timestamp='2002-01-02' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software --- 1,9 ---- #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, ! # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. ! timestamp='2004-02-16' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software *************** esac *** 118,124 **** # 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* | storm-chaos* | os2-emx* | windows32-*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; --- 118,125 ---- # 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-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ ! kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *************** case $basic_machine in *** 228,255 **** | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ ! | d10v | d30v | dsp16xx \ ! | fr30 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | m32r | m68000 | m68k | m88k | mcore \ ! | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ ! | mips64vr4100 | mips64vr4100el | mips64vr4300 \ ! | mips64vr4300el | mips64vr5000 | mips64vr5000el \ ! | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ ! | mipsisa32 \ | mn10200 | mn10300 \ | ns16k | ns32k \ ! | openrisc \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ ! | sh | sh[34] | sh[34]eb | shbe | shle \ ! | sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ ! | tahoe | thumb | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ --- 229,270 ---- | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ ! | d10v | d30v | dlx | dsp16xx \ ! | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ | m32r | m68000 | m68k | m88k | mcore \ ! | mips | mipsbe | mipseb | mipsel | mipsle \ ! | mips16 \ ! | mips64 | mips64el \ ! | mips64vr | mips64vrel \ ! | mips64orion | mips64orionel \ ! | mips64vr4100 | mips64vr4100el \ ! | mips64vr4300 | mips64vr4300el \ ! | mips64vr5000 | mips64vr5000el \ ! | mipsisa32 | mipsisa32el \ ! | mipsisa32r2 | mipsisa32r2el \ ! | mipsisa64 | mipsisa64el \ ! | mipsisa64r2 | mipsisa64r2el \ ! | mipsisa64sb1 | mipsisa64sb1el \ ! | mipsisa64sr71k | mipsisa64sr71kel \ ! | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | msp430 \ | ns16k | ns32k \ ! | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ ! | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ ! | sh64 | sh64le \ ! | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ ! | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ *************** case $basic_machine in *** 281,317 **** | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ ! | arm-* | armbe-* | armle-* | armv*-* \ | avr-* \ | bs2000-* \ ! | c[123]* | c30-* | [cjt]90-* | c54x-* \ ! | clipper-* | cray2-* | cydra-* \ ! | d10v-* | d30v-* \ | elxsi-* \ ! | f30[01]-* | f700-* | fr30-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | m32r-* \ ! | m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ ! | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ ! | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ ! | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ ! | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ ! | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ ! | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \ ! | sparc-* | sparc64-* | sparc86x-* | sparclite-* \ ! | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* \ ! | t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ ! | x86-* | x86_64-* | xmp-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) --- 296,348 ---- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ ! | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ ! | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ ! | clipper-* | cydra-* \ ! | d10v-* | d30v-* | dlx-* \ | elxsi-* \ ! | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ | m32r-* \ ! | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ ! | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ ! | mips16-* \ ! | mips64-* | mips64el-* \ ! | mips64vr-* | mips64vrel-* \ ! | mips64orion-* | mips64orionel-* \ ! | mips64vr4100-* | mips64vr4100el-* \ ! | mips64vr4300-* | mips64vr4300el-* \ ! | mips64vr5000-* | mips64vr5000el-* \ ! | mipsisa32-* | mipsisa32el-* \ ! | mipsisa32r2-* | mipsisa32r2el-* \ ! | mipsisa64-* | mipsisa64el-* \ ! | mipsisa64r2-* | mipsisa64r2el-* \ ! | mipsisa64sb1-* | mipsisa64sb1el-* \ ! | mipsisa64sr71k-* | mipsisa64sr71kel-* \ ! | mipstx39-* | mipstx39el-* \ ! | msp430-* \ ! | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ ! | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ ! | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ ! | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ ! | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ ! | tahoe-* | thumb-* \ ! | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ ! | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ ! | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) *************** case $basic_machine in *** 332,337 **** --- 363,371 ---- basic_machine=a29k-amd os=-udi ;; + abacus) + basic_machine=abacus-unknown + ;; adobe68k) basic_machine=m68010-adobe os=-scout *************** case $basic_machine in *** 346,351 **** --- 380,391 ---- 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 *************** case $basic_machine in *** 377,382 **** --- 417,426 ---- basic_machine=ns32k-sequent os=-dynix ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; convex-c1) basic_machine=c1-convex os=-bsd *************** case $basic_machine in *** 397,413 **** basic_machine=c38-convex os=-bsd ;; ! cray | ymp) ! basic_machine=ymp-cray ! os=-unicos ! ;; ! cray2) ! basic_machine=cray2-cray os=-unicos ;; ! [cjt]90) ! basic_machine=${basic_machine}-cray ! os=-unicos ;; crds | unos) basic_machine=m68k-crds --- 441,453 ---- basic_machine=c38-convex os=-bsd ;; ! cray | j90) ! basic_machine=j90-cray os=-unicos ;; ! cr16c) ! basic_machine=cr16c-unknown ! os=-elf ;; crds | unos) basic_machine=m68k-crds *************** case $basic_machine in *** 609,622 **** basic_machine=m68k-atari os=-mint ;; - mipsel*-linux*) - basic_machine=mipsel-unknown - os=-linux-gnu - ;; - mips*-linux*) - basic_machine=mips-unknown - os=-linux-gnu - ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; --- 649,654 ---- *************** case $basic_machine in *** 707,712 **** --- 739,748 ---- np1) basic_machine=np1-gould ;; + nv1) + basic_machine=nv1-cray + os=-unicosmp + ;; nsr-tandem) basic_machine=nsr-tandem ;; *************** case $basic_machine in *** 714,719 **** --- 750,763 ---- basic_machine=hppa1.1-oki os=-proelf ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose *************** case $basic_machine in *** 736,784 **** pbb) basic_machine=m68k-tti ;; ! pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; ! pentiumpro | p6 | 6x86 | athlon) basic_machine=i686-pc ;; ! pentiumii | pentium2) basic_machine=i686-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-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ! ;; ppc-*) 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/^[^-]*-//'` ;; --- 780,834 ---- pbb) basic_machine=m68k-tti ;; ! pc532 | pc532-*) basic_machine=ns32k-pc532 ;; 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) basic_machine=powerpc-unknown ! ;; ppc-*) 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/^[^-]*-//'` ;; *************** case $basic_machine in *** 809,814 **** --- 859,874 ---- basic_machine=a29k-amd os=-udi ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; sequent) basic_machine=i386-sequent ;; *************** case $basic_machine in *** 816,821 **** --- 876,884 ---- basic_machine=sh-hitachi os=-hms ;; + sh64) + basic_machine=sh64-unknown + ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks *************** case $basic_machine in *** 883,895 **** os=-dynix ;; t3e) ! basic_machine=t3e-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; --- 946,970 ---- os=-dynix ;; t3e) ! basic_machine=alphaev5-cray ! os=-unicos ! ;; ! t90) ! basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; tx39) basic_machine=mipstx39-unknown ;; *************** case $basic_machine in *** 903,908 **** --- 978,987 ---- tower | tower-32) basic_machine=m68k-ncr ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; udi29k) basic_machine=a29k-amd os=-udi *************** case $basic_machine in *** 924,931 **** os=-vms ;; vpp*|vx|vx-*) ! basic_machine=f301-fujitsu ! ;; vxworks960) basic_machine=i960-wrs os=-vxworks --- 1003,1010 ---- os=-vms ;; vpp*|vx|vx-*) ! basic_machine=f301-fujitsu ! ;; vxworks960) basic_machine=i960-wrs os=-vxworks *************** case $basic_machine in *** 946,962 **** basic_machine=hppa1.1-winbond os=-proelf ;; ! windows32) ! basic_machine=i386-pc ! os=-windows32-msvcrt ;; ! xmp) ! basic_machine=xmp-cray os=-unicos ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim --- 1025,1037 ---- basic_machine=hppa1.1-winbond os=-proelf ;; ! xps | xps100) ! basic_machine=xps100-honeywell ;; ! ymp) ! basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim *************** case $basic_machine in *** 977,989 **** op60c) basic_machine=hppa1.1-oki ;; - mips) - if [ x$os = x-linux-gnu ]; then - basic_machine=mips-unknown - else - basic_machine=mips-mips - fi - ;; romp) basic_machine=romp-ibm ;; --- 1052,1057 ---- *************** case $basic_machine in *** 1003,1015 **** we32k) basic_machine=we32k-att ;; ! sh3 | sh4 | sh3eb | sh4eb) basic_machine=sh-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; ! cydra) basic_machine=cydra-cydrome ;; orion) --- 1071,1086 ---- we32k) basic_machine=we32k-att ;; ! sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; + sh64) + basic_machine=sh64-unknown + ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; ! cydra) basic_machine=cydra-cydrome ;; orion) *************** case $basic_machine in *** 1024,1033 **** pmac | pmac-mpw) basic_machine=powerpc-apple ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; --- 1095,1100 ---- *************** case $os in *** 1083,1099 **** | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ ! | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ ! | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ ! | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ ! | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ ! | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* | -morphos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) --- 1150,1169 ---- | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ ! | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ ! | -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* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ ! | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ ! | -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*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) *************** case $os in *** 1105,1112 **** ;; esac ;; -nto*) ! os=-nto-qnx ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ --- 1175,1184 ---- ;; 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* \ *************** case $os in *** 1115,1120 **** --- 1187,1195 ---- -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; *************** case $os in *** 1127,1132 **** --- 1202,1210 ---- -opened*) os=-openedition ;; + -os400*) + os=-os400 + ;; -wince*) os=-wince ;; *************** case $os in *** 1148,1161 **** -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -ns2 ) ! os=-nextstep2 ;; -nsk*) os=-nsk --- 1226,1245 ---- -atheos*) os=-atheos ;; + -syllable*) + os=-syllable + ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; + -nova*) + os=-rtmk-nova + ;; -ns2 ) ! os=-nextstep2 ;; -nsk*) os=-nsk *************** case $os in *** 1167,1172 **** --- 1251,1259 ---- -sinix*) os=-sysv4 ;; + -tpf*) + os=-tpf + ;; -triton*) os=-sysv3 ;; *************** case $os in *** 1194,1201 **** -xenix) os=-xenix ;; ! -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) ! os=-mint ;; -none) ;; --- 1281,1294 ---- -xenix) os=-xenix ;; ! -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) ! os=-mint ! ;; ! -aros*) ! os=-aros ! ;; ! -kaos*) ! os=-kaos ;; -none) ;; *************** case $basic_machine in *** 1228,1238 **** arm*-semi) os=-aout ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; ! pdp11-*) os=-none ;; *-dec | vax-*) --- 1321,1334 ---- arm*-semi) os=-aout ;; + c4x-* | tic4x-*) + os=-coff + ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; ! pdp11-*) os=-none ;; *-dec | vax-*) *************** case $basic_machine in *** 1259,1264 **** --- 1355,1363 ---- mips*-*) os=-elf ;; + or32-*) + os=-coff + ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; *************** case $basic_machine in *** 1322,1340 **** *-next) os=-nextstep3 ;; ! *-gould) os=-sysv ;; ! *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; ! *-sgi) os=-irix ;; ! *-siemens) os=-sysv4 ;; *-masscomp) --- 1421,1439 ---- *-next) os=-nextstep3 ;; ! *-gould) os=-sysv ;; ! *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; ! *-sgi) os=-irix ;; ! *-siemens) os=-sysv4 ;; *-masscomp) *************** case $basic_machine in *** 1403,1412 **** -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; ! -vxsim* | -vxworks*) vendor=wrs ;; -aux*) --- 1502,1517 ---- -mvs* | -opened*) vendor=ibm ;; + -os400*) + vendor=ibm + ;; -ptx*) vendor=sequent ;; ! -tpf*) ! vendor=ibm ! ;; ! -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) diff -Nrc3pad gcc-3.3.3/boehm-gc/configure gcc-3.4.0/boehm-gc/configure *** gcc-3.3.3/boehm-gc/configure 2004-02-14 20:34:20.000000000 +0000 --- gcc-3.4.0/boehm-gc/configure 2004-04-19 02:23:04.000000000 +0000 *************** ac_help="$ac_help *** 41,47 **** ac_help="$ac_help --with-ecos enable runtime eCos target support" ac_help="$ac_help ! --enable-shared[=PKGS] build shared libraries [default=no]" ac_help="$ac_help --enable-full-debug include full support for pointer backtracing etc." --- 41,52 ---- ac_help="$ac_help --with-ecos enable runtime eCos target support" ac_help="$ac_help ! --enable-shared[=PKGS] build shared libraries [default=yes]" ! ac_help="$ac_help ! --with-target-subdir=SUBDIR ! configuring with a cross compiler" ! ac_help="$ac_help ! --with-cross-host=HOST configuring with a cross compiler" ac_help="$ac_help --enable-full-debug include full support for pointer backtracing etc." *************** ac_configure=$ac_aux_dir/configure # Thi *** 593,599 **** # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 ! echo "configure:597: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 598,604 ---- # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 ! echo "configure:602: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** test -z "$INSTALL_SCRIPT" && INSTALL_SCR *** 646,652 **** test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 ! echo "configure:650: checking whether build environment is sane" >&5 # Just in case sleep 1 echo timestamp > conftestfile --- 651,657 ---- test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 ! echo "configure:655: checking whether build environment is sane" >&5 # Just in case sleep 1 echo timestamp > conftestfile *************** test "$program_suffix" != NONE && *** 703,709 **** test "$program_transform_name" = "" && program_transform_name="s,x,x," echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 ! echo "configure:707: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 708,714 ---- test "$program_transform_name" = "" && program_transform_name="s,x,x," echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 ! echo "configure:712: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** else *** 736,747 **** fi echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 ! echo "configure:740: checking for Cygwin environment" >&5 if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 ! echo "configure:745: checking for Cygwin environment" >&5 if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_cygwin=yes else --- 757,763 ---- return __CYGWIN__; ; return 0; } EOF ! if { (eval echo configure:761: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_cygwin=yes else *************** echo "$ac_t""$ac_cv_cygwin" 1>&6 *** 769,787 **** CYGWIN= test "$ac_cv_cygwin" = yes && CYGWIN=yes echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 ! echo "configure:773: checking for mingw32 environment" >&5 if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_mingw32=yes else --- 774,792 ---- CYGWIN= test "$ac_cv_cygwin" = yes && CYGWIN=yes echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 ! echo "configure:778: checking for mingw32 environment" >&5 if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_mingw32=yes else *************** else { echo "configure: error: can not r *** 892,898 **** fi echo $ac_n "checking host system type""... $ac_c" 1>&6 ! echo "configure:896: checking host system type" >&5 host_alias=$host case "$host_alias" in --- 897,903 ---- fi echo $ac_n "checking host system type""... $ac_c" 1>&6 ! echo "configure:901: checking host system type" >&5 host_alias=$host case "$host_alias" in *************** host_os=`echo $host | sed 's/^\([^-]*\)- *** 913,919 **** echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 ! echo "configure:917: checking target system type" >&5 target_alias=$target case "$target_alias" in --- 918,924 ---- echo "$ac_t""$host" 1>&6 echo $ac_n "checking target system type""... $ac_c" 1>&6 ! echo "configure:922: checking target system type" >&5 target_alias=$target case "$target_alias" in *************** target_os=`echo $target | sed 's/^\([^-] *** 931,937 **** echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 ! echo "configure:935: checking build system type" >&5 build_alias=$build case "$build_alias" in --- 936,942 ---- echo "$ac_t""$target" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 ! echo "configure:940: checking build system type" >&5 build_alias=$build case "$build_alias" in *************** fi *** 971,977 **** missing_dir=`cd $ac_aux_dir && pwd` echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 ! echo "configure:975: checking for working aclocal" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. --- 976,982 ---- missing_dir=`cd $ac_aux_dir && pwd` echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 ! echo "configure:980: checking for working aclocal" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. *************** else *** 984,990 **** fi echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 ! echo "configure:988: checking for working autoconf" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. --- 989,995 ---- fi echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 ! echo "configure:993: checking for working autoconf" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. *************** else *** 997,1003 **** fi echo $ac_n "checking for working automake""... $ac_c" 1>&6 ! echo "configure:1001: checking for working automake" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. --- 1002,1008 ---- fi echo $ac_n "checking for working automake""... $ac_c" 1>&6 ! echo "configure:1006: checking for working automake" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. *************** else *** 1010,1016 **** fi echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 ! echo "configure:1014: checking for working autoheader" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. --- 1015,1021 ---- fi echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 ! echo "configure:1019: checking for working autoheader" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. *************** else *** 1023,1029 **** fi echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 ! echo "configure:1027: checking for working makeinfo" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. --- 1028,1034 ---- fi echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 ! echo "configure:1032: checking for working makeinfo" >&5 # Run test in a subshell; some versions of sh will print an error if # an executable is not found, even if stderr is redirected. # Redirect stdin to placate older versions of autoconf. Sigh. *************** fi *** 1049,1055 **** # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1053: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1054,1060 ---- # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1058: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** if test -z "$CC"; then *** 1079,1085 **** # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1083: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1084,1090 ---- # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1088: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** fi *** 1128,1134 **** fi echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 ! echo "configure:1132: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1133,1139 ---- fi echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 ! echo "configure:1137: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** else *** 1137,1143 **** yes; #endif EOF ! if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1141: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no --- 1142,1148 ---- yes; #endif EOF ! if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1146: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no *************** if test $ac_cv_prog_gcc = yes; then *** 1152,1158 **** ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 ! echo "configure:1156: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1157,1163 ---- ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 ! echo "configure:1161: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** do *** 1189,1195 **** # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1193: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1194,1200 ---- # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1198: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** test -n "$CXX" || CXX="gcc" *** 1222,1228 **** test -z "$CXX" && { echo "configure: error: no acceptable c++ found in \$PATH" 1>&2; exit 1; } echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 ! echo "configure:1226: checking whether we are using GNU C++" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1227,1233 ---- test -z "$CXX" && { echo "configure: error: no acceptable c++ found in \$PATH" 1>&2; exit 1; } echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 ! echo "configure:1231: checking whether we are using GNU C++" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** else *** 1231,1237 **** yes; #endif EOF ! if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1235: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gxx=yes else ac_cv_prog_gxx=no --- 1236,1242 ---- yes; #endif EOF ! if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1240: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gxx=yes else ac_cv_prog_gxx=no *************** if test $ac_cv_prog_gxx = yes; then *** 1246,1252 **** ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS= echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 ! echo "configure:1250: checking whether ${CXX-g++} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1251,1257 ---- ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS= echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 ! echo "configure:1255: checking whether ${CXX-g++} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** fi *** 1279,1285 **** # NEWLIB_CONFIGURE, which doesn't work because that means that it will # be run before AC_CANONICAL_HOST. echo $ac_n "checking build system type""... $ac_c" 1>&6 ! echo "configure:1283: checking build system type" >&5 build_alias=$build case "$build_alias" in --- 1284,1290 ---- # NEWLIB_CONFIGURE, which doesn't work because that means that it will # be run before AC_CANONICAL_HOST. echo $ac_n "checking build system type""... $ac_c" 1>&6 ! echo "configure:1288: checking build system type" >&5 build_alias=$build case "$build_alias" in *************** echo "$ac_t""$build" 1>&6 *** 1300,1306 **** # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. set dummy ${ac_tool_prefix}as; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1304: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1305,1311 ---- # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. set dummy ${ac_tool_prefix}as; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1309: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** fi *** 1332,1338 **** # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1336: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1337,1343 ---- # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1341: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** fi *** 1364,1370 **** # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1368: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1369,1375 ---- # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1373: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** if test -n "$ac_tool_prefix"; then *** 1396,1402 **** # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1400: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1401,1407 ---- # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:1405: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** fi *** 1441,1447 **** # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 ! echo "configure:1445: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1446,1452 ---- # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 ! echo "configure:1450: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** test -z "$INSTALL_DATA" && INSTALL_DATA= *** 1495,1501 **** echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 ! echo "configure:1499: checking whether to enable maintainer-specific portions of Makefiles" >&5 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" --- 1500,1506 ---- echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 ! echo "configure:1504: checking whether to enable maintainer-specific portions of Makefiles" >&5 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" *************** if false; then *** 1533,1539 **** echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 ! echo "configure:1537: checking for executable suffix" >&5 if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1538,1544 ---- echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 ! echo "configure:1542: checking for executable suffix" >&5 if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** else *** 1543,1549 **** rm -f conftest* echo 'int main () { return 0; }' > conftest.$ac_ext ac_cv_exeext= ! if { (eval echo configure:1547: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then for file in conftest.*; do case $file in *.c | *.o | *.obj) ;; --- 1548,1554 ---- rm -f conftest* echo 'int main () { return 0; }' > conftest.$ac_ext ac_cv_exeext= ! if { (eval echo configure:1552: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then for file in conftest.*; do case $file in *.c | *.o | *.obj) ;; *************** ac_prog=ld *** 1665,1671 **** if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6 ! echo "configure:1669: checking for ld used by GCC" >&5 case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw --- 1670,1676 ---- if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6 ! echo "configure:1674: checking for ld used by GCC" >&5 case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw *************** echo "configure:1669: checking for ld us *** 1695,1704 **** esac elif test "$with_gnu_ld" = yes; then echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 ! echo "configure:1699: checking for GNU ld" >&5 else echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 ! echo "configure:1702: checking for non-GNU ld" >&5 fi if eval "test \"`echo '$''{'lt_cv_path_LD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 1700,1709 ---- esac elif test "$with_gnu_ld" = yes; then echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 ! echo "configure:1704: checking for GNU ld" >&5 else echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 ! echo "configure:1707: checking for non-GNU ld" >&5 fi if eval "test \"`echo '$''{'lt_cv_path_LD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** else *** 1733,1739 **** fi test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; } echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6 ! echo "configure:1737: checking if the linker ($LD) is GNU ld" >&5 if eval "test \"`echo '$''{'lt_cv_prog_gnu_ld'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1738,1744 ---- fi test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; } echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6 ! echo "configure:1742: checking if the linker ($LD) is GNU ld" >&5 if eval "test \"`echo '$''{'lt_cv_prog_gnu_ld'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** with_gnu_ld=$lt_cv_prog_gnu_ld *** 1750,1756 **** echo $ac_n "checking for $LD option to reload object files""... $ac_c" 1>&6 ! echo "configure:1754: checking for $LD option to reload object files" >&5 if eval "test \"`echo '$''{'lt_cv_ld_reload_flag'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1755,1761 ---- echo $ac_n "checking for $LD option to reload object files""... $ac_c" 1>&6 ! echo "configure:1759: checking for $LD option to reload object files" >&5 if eval "test \"`echo '$''{'lt_cv_ld_reload_flag'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** reload_flag=$lt_cv_ld_reload_flag *** 1762,1768 **** test -n "$reload_flag" && reload_flag=" $reload_flag" echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6 ! echo "configure:1766: checking for BSD-compatible nm" >&5 if eval "test \"`echo '$''{'lt_cv_path_NM'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1767,1773 ---- test -n "$reload_flag" && reload_flag=" $reload_flag" echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6 ! echo "configure:1771: checking for BSD-compatible nm" >&5 if eval "test \"`echo '$''{'lt_cv_path_NM'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** NM="$lt_cv_path_NM" *** 1800,1806 **** echo "$ac_t""$NM" 1>&6 echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 ! echo "configure:1804: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1805,1811 ---- echo "$ac_t""$NM" 1>&6 echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 ! echo "configure:1809: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** else *** 1821,1827 **** fi echo $ac_n "checking how to recognise dependant libraries""... $ac_c" 1>&6 ! echo "configure:1825: checking how to recognise dependant libraries" >&5 if eval "test \"`echo '$''{'lt_cv_deplibs_check_method'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 1826,1832 ---- fi echo $ac_n "checking how to recognise dependant libraries""... $ac_c" 1>&6 ! echo "configure:1830: checking how to recognise dependant libraries" >&5 if eval "test \"`echo '$''{'lt_cv_deplibs_check_method'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** cygwin* | mingw* |pw32*) *** 1860,1865 **** --- 1865,1871 ---- ;; darwin* | rhapsody*) + # this will be overwritten by pass_all, but leave it in just in case lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' lt_cv_file_magic_cmd='/usr/bin/file -L' case "$host_os" in *************** darwin* | rhapsody*) *** 1870,1875 **** --- 1876,1882 ---- lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' ;; esac + lt_cv_deplibs_check_method=pass_all ;; freebsd* ) *************** irix5* | irix6*) *** 1931,1937 **** # This must be Linux ELF. linux-gnu*) case $host_cpu in ! alpha* | hppa* | i*86 | powerpc* | sparc* | ia64* ) lt_cv_deplibs_check_method=pass_all ;; *) # glibc up to 2.1.1 does not perform some relocations on ARM --- 1938,1944 ---- # This must be Linux ELF. linux-gnu*) case $host_cpu in ! alpha* | mips* | hppa* | i*86 | powerpc* | sparc* | ia64* ) lt_cv_deplibs_check_method=pass_all ;; *) # glibc up to 2.1.1 does not perform some relocations on ARM *************** file_magic_cmd=$lt_cv_file_magic_cmd *** 1994,2006 **** deplibs_check_method=$lt_cv_deplibs_check_method echo $ac_n "checking for object suffix""... $ac_c" 1>&6 ! echo "configure:1998: checking for object suffix" >&5 if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else rm -f conftest* echo 'int i = 1;' > conftest.$ac_ext ! if { (eval echo configure:2004: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then for ac_file in conftest.*; do case $ac_file in *.c) ;; --- 2001,2013 ---- deplibs_check_method=$lt_cv_deplibs_check_method echo $ac_n "checking for object suffix""... $ac_c" 1>&6 ! echo "configure:2005: checking for object suffix" >&5 if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else rm -f conftest* echo 'int i = 1;' > conftest.$ac_ext ! if { (eval echo configure:2011: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then for ac_file in conftest.*; do case $ac_file in *.c) ;; *************** case $deplibs_check_method in *** 2024,2030 **** file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then echo $ac_n "checking for ${ac_tool_prefix}file""... $ac_c" 1>&6 ! echo "configure:2028: checking for ${ac_tool_prefix}file" >&5 if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 2031,2037 ---- file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then echo $ac_n "checking for ${ac_tool_prefix}file""... $ac_c" 1>&6 ! echo "configure:2035: checking for ${ac_tool_prefix}file" >&5 if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** fi *** 2086,2092 **** if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then echo $ac_n "checking for file""... $ac_c" 1>&6 ! echo "configure:2090: checking for file" >&5 if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 2093,2099 ---- if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then echo $ac_n "checking for file""... $ac_c" 1>&6 ! echo "configure:2097: checking for file" >&5 if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** esac *** 2157,2163 **** # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:2161: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 2164,2170 ---- # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:2168: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** if test -n "$ac_tool_prefix"; then *** 2189,2195 **** # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:2193: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 2196,2202 ---- # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:2200: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** fi *** 2224,2230 **** # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:2228: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 2231,2237 ---- # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:2235: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** if test -n "$ac_tool_prefix"; then *** 2256,2262 **** # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:2260: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 2263,2269 ---- # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 ! echo "configure:2267: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** test x"$pic_mode" = xno && libtool_flags *** 2323,2330 **** case $host in *-*-irix6*) # Find out which ABI we are using. ! echo '#line 2327 "configure"' > conftest.$ac_ext ! if { (eval echo configure:2328: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) --- 2330,2337 ---- case $host in *-*-irix6*) # Find out which ABI we are using. ! echo '#line 2334 "configure"' > conftest.$ac_ext ! if { (eval echo configure:2335: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) *************** case $host in *** 2357,2363 **** ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext ! if { (eval echo configure:2361: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then case "`/usr/bin/file conftest.o`" in *ELF-32*) HPUX_IA64_MODE="32" --- 2364,2370 ---- ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext ! if { (eval echo configure:2368: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then case "`/usr/bin/file conftest.o`" in *ELF-32*) HPUX_IA64_MODE="32" *************** ia64-*-hpux*) *** 2373,2379 **** x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext ! if { (eval echo configure:2377: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then case "`/usr/bin/file conftest.o`" in *32-bit*) case $host in --- 2380,2386 ---- x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext ! if { (eval echo configure:2384: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then case "`/usr/bin/file conftest.o`" in *32-bit*) case $host in *************** x86_64-*linux*|ppc*-*linux*|powerpc*-*li *** 2417,2423 **** SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6 ! echo "configure:2421: checking whether the C compiler needs -belf" >&5 if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 2424,2430 ---- SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6 ! echo "configure:2428: checking whether the C compiler needs -belf" >&5 if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** ac_link='${CC-cc} -o conftest${ac_exeext *** 2430,2443 **** cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* lt_cv_cc_needs_belf=yes else --- 2437,2450 ---- cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* lt_cv_cc_needs_belf=yes else *************** echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6 *** 2467,2473 **** esac echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6 ! echo "configure:2471: checking how to run the C++ preprocessor" >&5 if test -z "$CXXCPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 2474,2480 ---- esac echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6 ! echo "configure:2478: checking how to run the C++ preprocessor" >&5 if test -z "$CXXCPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** ac_link='${CXX-g++} -o conftest${ac_exee *** 2480,2491 **** cross_compiling=$ac_cv_prog_cxx_cross CXXCPP="${CXX-g++} -E" cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:2489: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : --- 2487,2498 ---- cross_compiling=$ac_cv_prog_cxx_cross CXXCPP="${CXX-g++} -E" cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ! { (eval echo configure:2496: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : *************** fi *** 2632,2638 **** echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 ! echo "configure:2636: checking whether to enable maintainer-specific portions of Makefiles" >&5 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" --- 2639,2645 ---- echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 ! echo "configure:2643: checking whether to enable maintainer-specific portions of Makefiles" >&5 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" *************** if false; then *** 2665,2671 **** echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 ! echo "configure:2669: checking for executable suffix" >&5 if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else --- 2672,2678 ---- echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 ! echo "configure:2676: checking for executable suffix" >&5 if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else *************** else *** 2675,2681 **** rm -f conftest* echo 'int main () { return 0; }' > conftest.$ac_ext ac_cv_exeext= ! if { (eval echo configure:2679: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then for file in conftest.*; do case $file in *.c | *.o | *.obj) ;; --- 2682,2688 ---- rm -f conftest* echo 'int main () { return 0; }' > conftest.$ac_ext ac_cv_exeext= ! if { (eval echo configure:2686: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then for file in conftest.*; do case $file in *.c | *.o | *.obj) ;; *************** ac_exeext=$EXEEXT *** 2698,2704 **** fi echo $ac_n "checking for thread model used by GCC""... $ac_c" 1>&6 ! echo "configure:2702: checking for thread model used by GCC" >&5 THREADS=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'` if test -z "$THREADS"; then THREADS=no --- 2705,2711 ---- fi echo $ac_n "checking for thread model used by GCC""... $ac_c" 1>&6 ! echo "configure:2709: checking for thread model used by GCC" >&5 THREADS=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'` if test -z "$THREADS"; then THREADS=no *************** if test "${enable_parallel_mark+set}" = *** 2717,2723 **** fi ! INCLUDES=-I${srcdir}/include THREADLIBS= case "$THREADS" in no | none | single) --- 2724,2730 ---- fi ! INCLUDES="-I`cd $srcdir && ${PWDCMD-pwd}`/include" THREADLIBS= case "$THREADS" in no | none | single) *************** case "$THREADS" in *** 2727,2733 **** THREADS=posix THREADLIBS=-lpthread case "$host" in ! x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* ) cat >> confdefs.h <<\EOF #define GC_LINUX_THREADS 1 EOF --- 2734,2740 ---- THREADS=posix THREADLIBS=-lpthread case "$host" in ! x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux*) cat >> confdefs.h <<\EOF #define GC_LINUX_THREADS 1 EOF *************** EOF *** 2736,2742 **** #define _REENTRANT 1 EOF ! if test "${enable_parallel_mark}"; then cat >> confdefs.h <<\EOF #define PARALLEL_MARK 1 EOF --- 2743,2749 ---- #define _REENTRANT 1 EOF ! if test "${enable_parallel_mark}" = yes; then cat >> confdefs.h <<\EOF #define PARALLEL_MARK 1 EOF *************** EOF *** 2757,2762 **** --- 2764,2779 ---- EOF ;; + *-*-aix*) + cat >> confdefs.h <<\EOF + #define GC_AIX_THREADS 1 + EOF + + cat >> confdefs.h <<\EOF + #define _REENTRANT 1 + EOF + + ;; *-*-hpux*) echo "configure: warning: "Only HP/UX 11 threads are supported."" 1>&2 cat >> confdefs.h <<\EOF *************** EOF *** 2805,2811 **** ;; *-*-cygwin*) ! THREADLIBS= ;; esac ;; --- 2822,2867 ---- ;; *-*-cygwin*) ! cat >> confdefs.h <<\EOF ! #define GC_WIN32_THREADS 1 ! EOF ! ! ;; ! *-*-darwin*) ! cat >> confdefs.h <<\EOF ! #define GC_DARWIN_THREADS 1 ! EOF ! ! cat >> confdefs.h <<\EOF ! #define THREAD_LOCAL_ALLOC 1 ! EOF ! ! if test "${enable_parallel_mark}" = yes; then ! cat >> confdefs.h <<\EOF ! #define PARALLEL_MARK 1 ! EOF ! ! fi ! ;; ! *-*-osf*) ! cat >> confdefs.h <<\EOF ! #define GC_OSF1_THREADS 1 ! EOF ! ! if test "${enable_parallel_mark}" = yes; then ! cat >> confdefs.h <<\EOF ! #define PARALLEL_MARK 1 ! EOF ! ! cat >> confdefs.h <<\EOF ! #define THREAD_LOCAL_ALLOC 1 ! EOF ! ! # May want to enable it in other cases, too. ! # Measurements havent yet been done. ! fi ! INCLUDES="$INCLUDES -pthread" ! THREADLIBS="-lpthread -lrt" ;; esac ;; *************** EOF *** 2814,2829 **** #define GC_WIN32_THREADS 1 EOF cat >> confdefs.h <<\EOF ! #define NO_GETENV 1 EOF ! if test $enable_shared = yes; then ! cat >> confdefs.h <<\EOF ! #define GC_DLL 1 EOF - fi ;; decosf1 | irix | mach | os2 | solaris | dce | vxworks) { echo "configure: error: thread package $THREADS not yet supported" 1>&2; exit 1; } --- 2870,2913 ---- #define GC_WIN32_THREADS 1 EOF + ;; + dgux386) + THREADS=dgux386 + echo "$ac_t""$THREADLIBS" 1>&6 + # Use pthread GCC switch + THREADLIBS=-pthread + if test "${enable_parallel_mark}" = yes; then + cat >> confdefs.h <<\EOF + #define PARALLEL_MARK 1 + EOF + + fi cat >> confdefs.h <<\EOF ! #define THREAD_LOCAL_ALLOC 1 EOF ! cat >> confdefs.h <<\EOF ! #define GC_DGUX386_THREADS 1 ! EOF ! ! cat >> confdefs.h <<\EOF ! #define DGUX_THREADS 1 ! EOF ! ! # Enable _POSIX4A_DRAFT10_SOURCE with flag -pthread ! INCLUDES="-pthread $INCLUDES" ! ;; ! aix) ! THREADS=posix ! THREADLIBS=-lpthread ! cat >> confdefs.h <<\EOF ! #define GC_AIX_THREADS 1 ! EOF ! ! cat >> confdefs.h <<\EOF ! #define _REENTRANT 1 EOF ;; decosf1 | irix | mach | os2 | solaris | dce | vxworks) { echo "configure: error: thread package $THREADS not yet supported" 1>&2; exit 1; } *************** EOF *** 2834,2841 **** esac ! echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 ! echo "configure:2839: checking for dlopen in -ldl" >&5 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 --- 2918,2945 ---- esac ! case "$host" in ! powerpc-*-darwin*) ! powerpc_darwin=true ! ;; ! esac ! ! ! if test x$powerpc_darwin = xtrue; then ! POWERPC_DARWIN_TRUE= ! POWERPC_DARWIN_FALSE='#' ! else ! POWERPC_DARWIN_TRUE='#' ! POWERPC_DARWIN_FALSE= ! fi ! ! # We never want libdl on darwin. It is a fake libdl that just ends up making ! # dyld calls anyway ! case "$host" in ! *-*-darwin*) ;; ! *) ! echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 ! echo "configure:2943: checking for dlopen in -ldl" >&5 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 *************** else *** 2843,2849 **** ac_save_LIBS="$LIBS" LIBS="-ldl $LIBS" cat > conftest.$ac_ext < conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else --- 2958,2964 ---- dlopen() ; return 0; } EOF ! if { (eval echo configure:2962: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else *************** else *** 2874,2879 **** --- 2978,2986 ---- echo "$ac_t""no" 1>&6 fi + ;; + esac + target_all=libgcjgc.la *************** fi *** 2890,2895 **** --- 2997,3005 ---- addobjs= + addlibs= + addincludes= + addtests= CXXINCLUDES= case "$TARGET_ECOS" in no) *************** EOF *** 2904,2920 **** ;; esac ! machdep= ! case "$host" in ! alpha*-*-openbsd*) ! machdep="alpha_mach_dep.lo" ! if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then ! echo "configure: warning: OpenBSD/Alpha without dlopen(). Shared library support is disabled" 1>&2 ! # Check whether --enable-shared or --disable-shared was given. if test "${enable_shared+set}" = set; then enableval="$enable_shared" p=${PACKAGE-default} --- 3014,3044 ---- ;; esac + if test "${enable_cplusplus}" = yes; then + addincludes="$addincludes include/gc_cpp.h include/gc_allocator.h" + addtests="$addtests test_cpp" + fi + + if test "${enable_cplusplus}" = yes; then + CPLUSPLUS_TRUE= + CPLUSPLUS_FALSE='#' + else + CPLUSPLUS_TRUE='#' + CPLUSPLUS_FALSE= + fi + ! ! ! ! # Configuration of shared libraries ! # ! echo $ac_n "checking whether to build shared libraries""... $ac_c" 1>&6 ! echo "configure:3041: checking whether to build shared libraries" >&5 ! # Check whether --enable-shared or --disable-shared was given. if test "${enable_shared+set}" = set; then enableval="$enable_shared" p=${PACKAGE-default} *************** no) enable_shared=no ;; *** 2934,2945 **** ;; esac else ! enable_shared=no fi fi ;; ! alpha*-*-*) machdep="alpha_mach_dep.lo" ;; i?86-*-solaris2.[89] | i?86-*-solaris2.1?) --- 3058,3096 ---- ;; esac else ! enable_shared=yes fi + + case "$host" in + alpha-*-openbsd*) + enable_shared=no + echo "$ac_t""no" 1>&6 + ;; + *) + echo "$ac_t""yes" 1>&6 + ;; + esac + + # Configuration of machine-dependent code + # + # We don't set NO_EXECUTE_PERMISSION by default because gcj (and + # anything else that creates trampolines in gc-allocated memory) + # always needs exec permission. The exception to this is IA-64 and + # some variations of Power PC, where trampolines don't contain + # executable code. + # + echo $ac_n "checking which machine-dependent code should be used""... $ac_c" 1>&6 + echo "configure:3085: checking which machine-dependent code should be used" >&5 + machdep= + case "$host" in + alpha*-*-openbsd*) + machdep="alpha_mach_dep.lo" + if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then + echo "configure: warning: OpenBSD/Alpha without dlopen(). Shared library support is disabled" 1>&2 fi ;; ! alpha*-*-linux*) machdep="alpha_mach_dep.lo" ;; i?86-*-solaris2.[89] | i?86-*-solaris2.1?) *************** EOF *** 2962,2975 **** mips-dec-ultrix*) machdep="mips_ultrix_mach-dep.lo" ;; ! mips*-*-linux*) ;; mips-*-*) machdep="mips_sgi_mach_dep.lo" ! cat >> confdefs.h <<\EOF ! #define NO_EXECUTE_PERMISSION 1 ! EOF ! ;; sparc-sun-solaris2.3) machdep="sparc_mach_dep.lo" --- 3113,3127 ---- mips-dec-ultrix*) machdep="mips_ultrix_mach-dep.lo" ;; ! mips-nec-sysv*|mips-unknown-sysv*) ;; + mips*-*-linux*) + ;; mips-*-*) machdep="mips_sgi_mach_dep.lo" ! ;; ! sparc-*-netbsd*) ! machdep="sparc_netbsd_mach_dep.lo" ;; sparc-sun-solaris2.3) machdep="sparc_mach_dep.lo" *************** EOF *** 2982,2999 **** machdep="sparc_mach_dep.lo" ;; ia64-*-*) machdep="mach_dep.lo ia64_save_regs_in_stack.lo" ;; esac if test x"$machdep" = x; then machdep="mach_dep.lo" fi addobjs="$addobjs $machdep" case "$host" in ! sparc-sun-solaris2*) if test "$GCC" = yes; then new_CFLAGS= for i in $CFLAGS; do case "$i" in --- 3134,3358 ---- machdep="sparc_mach_dep.lo" ;; ia64-*-*) + cat >> confdefs.h <<\EOF + #define NO_EXECUTE_PERMISSION 1 + EOF + machdep="mach_dep.lo ia64_save_regs_in_stack.lo" ;; esac if test x"$machdep" = x; then + echo "$ac_t""$machdep" 1>&6 machdep="mach_dep.lo" fi addobjs="$addobjs $machdep" + + + + + + + + + + # + # Check for AViiON Machines running DGUX + # + echo $ac_n "checking if host is AViiON running DGUX""... $ac_c" 1>&6 + echo "configure:3165: checking if host is AViiON running DGUX" >&5 + ac_is_dgux=no + echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 + echo "configure:3168: checking how to run the C preprocessor" >&5 + # On Suns, sometimes $CPP names a directory. + if test -n "$CPP" && test -d "$CPP"; then + CPP= + fi + if test -z "$CPP"; then + if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < + Syntax Error + EOF + ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" + { (eval echo configure:3189: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } + ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` + if test -z "$ac_err"; then + : + else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < + Syntax Error + EOF + ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" + { (eval echo configure:3206: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } + ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` + if test -z "$ac_err"; then + : + else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < + Syntax Error + EOF + ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" + { (eval echo configure:3223: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } + ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` + if test -z "$ac_err"; then + : + else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp + fi + rm -f conftest* + fi + rm -f conftest* + fi + rm -f conftest* + ac_cv_prog_CPP="$CPP" + fi + CPP="$ac_cv_prog_CPP" + else + ac_cv_prog_CPP="$CPP" + fi + echo "$ac_t""$CPP" 1>&6 + + ac_safe=`echo "sys/dg_sys_info.h" | sed 'y%./+-%__p_%'` + echo $ac_n "checking for sys/dg_sys_info.h""... $ac_c" 1>&6 + echo "configure:3249: checking for sys/dg_sys_info.h" >&5 + if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + cat > conftest.$ac_ext < + EOF + ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" + { (eval echo configure:3259: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } + ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` + if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" + else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" + fi + rm -f conftest* + fi + if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_is_dgux=yes; + else + echo "$ac_t""no" 1>&6 + fi + + + echo "$ac_t""$ac_is_dgux" 1>&6 + ## :GOTCHA: we do not check anything but sys/dg_sys_info.h + if test $ac_is_dgux = yes; then + if test "$enable_full_debug" = "yes"; then + CFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2" + CXXFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2" + else + CFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2" + CXXFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2" + fi + + + fi + + # Check whether --with-target-subdir or --without-target-subdir was given. + if test "${with_target_subdir+set}" = set; then + withval="$with_target_subdir" + : + fi + + # Check whether --with-cross-host or --without-cross-host was given. + if test "${with_cross_host+set}" = set; then + withval="$with_cross_host" + : + 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. + : + + + echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 + echo "configure:3319: checking for executable suffix" >&5 + if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 + else + if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_exeext=.exe + else + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_exeext= + if { (eval echo configure:3329: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj) ;; + *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; } + fi + rm -f conftest* + test x"${ac_cv_exeext}" = x && ac_cv_exeext=no + fi + fi + + EXEEXT="" + test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext} + echo "$ac_t""${ac_cv_exeext}" 1>&6 + ac_exeext=$EXEEXT + + fi + + echo $ac_n "checking whether Solaris gcc optimization fix is necessary""... $ac_c" 1>&6 + echo "configure:3352: checking whether Solaris gcc optimization fix is necessary" >&5 case "$host" in ! sparc-sun-solaris2*|*aix*) if test "$GCC" = yes; then + echo "$ac_t""yes" 1>&6 new_CFLAGS= for i in $CFLAGS; do case "$i" in *************** case "$host" in *** 3005,3012 **** --- 3364,3374 ---- esac done CFLAGS="$new_CFLAGS" + else + echo "$ac_t""no" 1>&6 fi ;; + *) echo "$ac_t""no" 1>&6 ;; esac MY_CFLAGS="$CFLAGS" *************** cat >> confdefs.h <<\EOF *** 3021,3030 **** EOF cat >> confdefs.h <<\EOF - #define NO_EXECUTE_PERMISSION 1 - EOF - - cat >> confdefs.h <<\EOF #define ALL_INTERIOR_POINTERS 1 EOF --- 3383,3388 ---- *************** EOF *** 3084,3089 **** --- 3442,3453 ---- EOF ;; + i345686-*-dgux*) + cat >> confdefs.h <<\EOF + #define MAKE_BACK_GRAPH 1 + EOF + + ;; esac fi fi *************** else *** 3097,3103 **** toolexecdir='$(libdir)/gcc-lib/$(target_alias)' toolexeclibdir='$(libdir)' fi ! toolexeclibdir=$toolexeclibdir/`$CC -print-multi-os-directory` --- 3461,3471 ---- toolexecdir='$(libdir)/gcc-lib/$(target_alias)' toolexeclibdir='$(libdir)' fi ! multi_os_directory=`$CC -print-multi-os-directory` ! case $multi_os_directory in ! .) ;; # Avoid trailing /. ! *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; ! esac *************** s%@STRIP@%$STRIP%g *** 3296,3306 **** --- 3664,3682 ---- s%@LIBTOOL@%$LIBTOOL%g s%@CXXCPP@%$CXXCPP%g s%@THREADLIBS@%$THREADLIBS%g + s%@POWERPC_DARWIN_TRUE@%$POWERPC_DARWIN_TRUE%g + s%@POWERPC_DARWIN_FALSE@%$POWERPC_DARWIN_FALSE%g s%@EXTRA_TEST_LIBS@%$EXTRA_TEST_LIBS%g s%@target_all@%$target_all%g + s%@CPLUSPLUS_TRUE@%$CPLUSPLUS_TRUE%g + s%@CPLUSPLUS_FALSE@%$CPLUSPLUS_FALSE%g s%@INCLUDES@%$INCLUDES%g s%@CXXINCLUDES@%$CXXINCLUDES%g s%@addobjs@%$addobjs%g + s%@addincludes@%$addincludes%g + s%@addlibs@%$addlibs%g + s%@addtests@%$addtests%g + s%@CPP@%$CPP%g s%@MY_CFLAGS@%$MY_CFLAGS%g s%@toolexecdir@%$toolexecdir%g s%@toolexeclibdir@%$toolexeclibdir%g *************** gc_basedir=${gc_basedir} *** 3416,3426 **** CC="${CC}" ORIGINAL_LD_FOR_MULTILIBS="${ORIGINAL_LD_FOR_MULTILIBS}" DEFS="$DEFS" EOF cat >> $CONFIG_STATUS <<\EOF ! echo "$DEFS" > boehm-cflags if test -n "$CONFIG_FILES"; then LD="${ORIGINAL_LD_FOR_MULTILIBS}" --- 3792,3803 ---- CC="${CC}" ORIGINAL_LD_FOR_MULTILIBS="${ORIGINAL_LD_FOR_MULTILIBS}" DEFS="$DEFS" + INCLUDES="$INCLUDES" EOF cat >> $CONFIG_STATUS <<\EOF ! echo "$INCLUDES $DEFS" > boehm-cflags if test -n "$CONFIG_FILES"; then LD="${ORIGINAL_LD_FOR_MULTILIBS}" diff -Nrc3pad gcc-3.3.3/boehm-gc/configure.in gcc-3.4.0/boehm-gc/configure.in *** gcc-3.3.3/boehm-gc/configure.in 2003-10-01 19:06:52.000000000 +0000 --- gcc-3.4.0/boehm-gc/configure.in 2004-01-20 15:15:48.000000000 +0000 *************** *** 13,18 **** --- 13,19 ---- dnl Process this file with autoconf to produce configure. + AC_PREREQ(2.13) AC_INIT(gcj_mlc.c) # This works around the fact that libtool configuration may change LD *************** AC_ARG_ENABLE(parallel-mark, *** 63,69 **** esac] ) ! INCLUDES=-I${srcdir}/include THREADLIBS= case "$THREADS" in no | none | single) --- 64,70 ---- esac] ) ! INCLUDES="-I`cd $srcdir && ${PWDCMD-pwd}`/include" THREADLIBS= case "$THREADS" in no | none | single) *************** case "$THREADS" in *** 73,82 **** THREADS=posix THREADLIBS=-lpthread case "$host" in ! x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* ) AC_DEFINE(GC_LINUX_THREADS) AC_DEFINE(_REENTRANT) ! if test "${enable_parallel_mark}"; then AC_DEFINE(PARALLEL_MARK) fi AC_DEFINE(THREAD_LOCAL_ALLOC) --- 74,83 ---- THREADS=posix THREADLIBS=-lpthread case "$host" in ! x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux*) AC_DEFINE(GC_LINUX_THREADS) AC_DEFINE(_REENTRANT) ! if test "${enable_parallel_mark}" = yes; then AC_DEFINE(PARALLEL_MARK) fi AC_DEFINE(THREAD_LOCAL_ALLOC) *************** case "$THREADS" in *** 85,90 **** --- 86,95 ---- AC_DEFINE(GC_LINUX_THREADS) AC_DEFINE(_REENTRANT) ;; + *-*-aix*) + AC_DEFINE(GC_AIX_THREADS) + AC_DEFINE(_REENTRANT) + ;; *-*-hpux*) AC_MSG_WARN("Only HP/UX 11 threads are supported.") AC_DEFINE(GC_HPUX_THREADS) *************** case "$THREADS" in *** 109,124 **** AC_DEFINE(GC_IRIX_THREADS) ;; *-*-cygwin*) ! THREADLIBS= ;; esac ;; win32) AC_DEFINE(GC_WIN32_THREADS) ! AC_DEFINE(NO_GETENV) ! if test $enable_shared = yes; then ! AC_DEFINE(GC_DLL) fi ;; decosf1 | irix | mach | os2 | solaris | dce | vxworks) AC_MSG_ERROR(thread package $THREADS not yet supported) --- 114,165 ---- AC_DEFINE(GC_IRIX_THREADS) ;; *-*-cygwin*) ! AC_DEFINE(GC_WIN32_THREADS) ! ;; ! *-*-darwin*) ! AC_DEFINE(GC_DARWIN_THREADS) ! AC_DEFINE(THREAD_LOCAL_ALLOC) ! if test "${enable_parallel_mark}" = yes; then ! AC_DEFINE(PARALLEL_MARK) ! fi ! ;; ! *-*-osf*) ! AC_DEFINE(GC_OSF1_THREADS) ! if test "${enable_parallel_mark}" = yes; then ! AC_DEFINE(PARALLEL_MARK) ! AC_DEFINE(THREAD_LOCAL_ALLOC) ! # May want to enable it in other cases, too. ! # Measurements havent yet been done. ! fi ! INCLUDES="$INCLUDES -pthread" ! THREADLIBS="-lpthread -lrt" ;; esac ;; win32) AC_DEFINE(GC_WIN32_THREADS) ! dnl Old wine getenv may not return NULL for missing entry. ! dnl Define EMPTY_GETENV_RESULTS here to work around the bug. ! ;; ! dgux386) ! THREADS=dgux386 ! AC_MSG_RESULT($THREADLIBS) ! # Use pthread GCC switch ! THREADLIBS=-pthread ! if test "${enable_parallel_mark}" = yes; then ! AC_DEFINE(PARALLEL_MARK) fi + AC_DEFINE(THREAD_LOCAL_ALLOC) + AC_DEFINE(GC_DGUX386_THREADS) + AC_DEFINE(DGUX_THREADS) + # Enable _POSIX4A_DRAFT10_SOURCE with flag -pthread + INCLUDES="-pthread $INCLUDES" + ;; + aix) + THREADS=posix + THREADLIBS=-lpthread + AC_DEFINE(GC_AIX_THREADS) + AC_DEFINE(_REENTRANT) ;; decosf1 | irix | mach | os2 | solaris | dce | vxworks) AC_MSG_ERROR(thread package $THREADS not yet supported) *************** case "$THREADS" in *** 129,135 **** esac AC_SUBST(THREADLIBS) ! AC_CHECK_LIB(dl, dlopen, EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl") AC_SUBST(EXTRA_TEST_LIBS) target_all=libgcjgc.la --- 170,191 ---- esac AC_SUBST(THREADLIBS) ! case "$host" in ! powerpc-*-darwin*) ! powerpc_darwin=true ! ;; ! esac ! AM_CONDITIONAL(POWERPC_DARWIN,test x$powerpc_darwin = xtrue) ! ! # We never want libdl on darwin. It is a fake libdl that just ends up making ! # dyld calls anyway ! case "$host" in ! *-*-darwin*) ;; ! *) ! AC_CHECK_LIB(dl, dlopen, EXTRA_TEST_LIBS="$EXTRA_TEST_LIBS -ldl") ! ;; ! esac ! AC_SUBST(EXTRA_TEST_LIBS) target_all=libgcjgc.la *************** TARGET_ECOS="$with_ecos" *** 147,152 **** --- 203,211 ---- ) addobjs= + addlibs= + addincludes= + addtests= CXXINCLUDES= case "$TARGET_ECOS" in no) *************** case "$TARGET_ECOS" in *** 157,177 **** addobjs="$addobjs ecos.lo" ;; esac AC_SUBST(CXX) AC_SUBST(INCLUDES) AC_SUBST(CXXINCLUDES) machdep= case "$host" in alpha*-*-openbsd*) machdep="alpha_mach_dep.lo" if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then AC_MSG_WARN(OpenBSD/Alpha without dlopen(). Shared library support is disabled) - AM_DISABLE_SHARED fi ;; ! alpha*-*-*) machdep="alpha_mach_dep.lo" ;; i?86-*-solaris2.[[89]] | i?86-*-solaris2.1?) --- 216,267 ---- addobjs="$addobjs ecos.lo" ;; esac + + if test "${enable_cplusplus}" = yes; then + addincludes="$addincludes include/gc_cpp.h include/gc_allocator.h" + addtests="$addtests test_cpp" + fi + + AM_CONDITIONAL(CPLUSPLUS, test "${enable_cplusplus}" = yes) + AC_SUBST(CXX) AC_SUBST(INCLUDES) AC_SUBST(CXXINCLUDES) + # Configuration of shared libraries + # + AC_MSG_CHECKING(whether to build shared libraries) + AC_ENABLE_SHARED + + case "$host" in + alpha-*-openbsd*) + enable_shared=no + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + ;; + esac + + # Configuration of machine-dependent code + # + # We don't set NO_EXECUTE_PERMISSION by default because gcj (and + # anything else that creates trampolines in gc-allocated memory) + # always needs exec permission. The exceptions to this are IA-64 and + # some variations of Power PC, where trampolines don't contain + # executable code. + # + AC_MSG_CHECKING(which machine-dependent code should be used) machdep= case "$host" in alpha*-*-openbsd*) machdep="alpha_mach_dep.lo" if test x"${ac_cv_lib_dl_dlopen}" != xyes ; then AC_MSG_WARN(OpenBSD/Alpha without dlopen(). Shared library support is disabled) fi ;; ! alpha*-*-linux*) machdep="alpha_mach_dep.lo" ;; i?86-*-solaris2.[[89]] | i?86-*-solaris2.1?) *************** case "$host" in *** 185,195 **** mips-dec-ultrix*) machdep="mips_ultrix_mach-dep.lo" ;; ! mips*-*-linux*) ;; mips-*-*) machdep="mips_sgi_mach_dep.lo" ! AC_DEFINE(NO_EXECUTE_PERMISSION) ;; sparc-sun-solaris2.3) machdep="sparc_mach_dep.lo" --- 275,289 ---- mips-dec-ultrix*) machdep="mips_ultrix_mach-dep.lo" ;; ! mips-nec-sysv*|mips-unknown-sysv*) ;; + mips*-*-linux*) + ;; mips-*-*) machdep="mips_sgi_mach_dep.lo" ! ;; ! sparc-*-netbsd*) ! machdep="sparc_netbsd_mach_dep.lo" ;; sparc-sun-solaris2.3) machdep="sparc_mach_dep.lo" *************** case "$host" in *** 199,218 **** machdep="sparc_mach_dep.lo" ;; ia64-*-*) machdep="mach_dep.lo ia64_save_regs_in_stack.lo" ;; esac if test x"$machdep" = x; then machdep="mach_dep.lo" fi addobjs="$addobjs $machdep" AC_SUBST(addobjs) dnl As of 4.13a2, the collector will not properly work on Solaris when dnl built with gcc and -O. So we remove -O in the appropriate case. case "$host" in ! sparc-sun-solaris2*) if test "$GCC" = yes; then new_CFLAGS= for i in $CFLAGS; do case "$i" in --- 293,362 ---- machdep="sparc_mach_dep.lo" ;; ia64-*-*) + AC_DEFINE(NO_EXECUTE_PERMISSION) machdep="mach_dep.lo ia64_save_regs_in_stack.lo" ;; esac if test x"$machdep" = x; then + AC_MSG_RESULT($machdep) machdep="mach_dep.lo" fi addobjs="$addobjs $machdep" AC_SUBST(addobjs) + AC_SUBST(addincludes) + AC_SUBST(addlibs) + AC_SUBST(addtests) + + AC_PROG_LIBTOOL + + # + # Check for AViiON Machines running DGUX + # + AC_MSG_CHECKING(if host is AViiON running DGUX) + ac_is_dgux=no + AC_CHECK_HEADER(sys/dg_sys_info.h, + [ac_is_dgux=yes;]) + + AC_MSG_RESULT($ac_is_dgux) + ## :GOTCHA: we do not check anything but sys/dg_sys_info.h + if test $ac_is_dgux = yes; then + if test "$enable_full_debug" = "yes"; then + CFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2" + CXXFLAGS="-g -mstandard -DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2" + else + CFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2" + CXXFLAGS="-DDGUX -D_DGUX_SOURCE -Di386 -mno-legend -O2" + fi + AC_SUBST(CFLAGS) + AC_SUBST(CXXFLAGS) + fi + + dnl We use these options to decide which functions to include. + AC_ARG_WITH(target-subdir, + [ --with-target-subdir=SUBDIR + configuring with a cross compiler]) + 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. + 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. + : + AC_EXEEXT + fi dnl As of 4.13a2, the collector will not properly work on Solaris when dnl built with gcc and -O. So we remove -O in the appropriate case. + dnl + AC_MSG_CHECKING(whether Solaris gcc optimization fix is necessary) case "$host" in ! sparc-sun-solaris2*|*aix*) if test "$GCC" = yes; then + AC_MSG_RESULT(yes) new_CFLAGS= for i in $CFLAGS; do case "$i" in *************** case "$host" in *** 224,231 **** --- 368,378 ---- esac done CFLAGS="$new_CFLAGS" + else + AC_MSG_RESULT(no) fi ;; + *) AC_MSG_RESULT(no) ;; esac dnl We need to override the top-level CFLAGS. This is how we do it. *************** dnl Include defines that have become de *** 236,242 **** dnl ALL_INTERIOR_POINTERS can be overridden in startup code. AC_DEFINE(SILENT) AC_DEFINE(NO_SIGNALS) - AC_DEFINE(NO_EXECUTE_PERMISSION) AC_DEFINE(ALL_INTERIOR_POINTERS) dnl By default, make the library as general as possible. --- 383,388 ---- *************** AC_ARG_ENABLE(full-debug, *** 267,272 **** --- 413,421 ---- AC_MSG_WARN("Client must not use -fomit-frame-pointer.") AC_DEFINE(SAVE_CALL_COUNT, 8) ;; + i[3456]86-*-dgux*) + AC_DEFINE(MAKE_BACK_GRAPH) + ;; esac ] fi) *************** else *** 278,284 **** toolexecdir='$(libdir)/gcc-lib/$(target_alias)' toolexeclibdir='$(libdir)' fi ! toolexeclibdir=$toolexeclibdir/`$CC -print-multi-os-directory` AC_SUBST(toolexecdir) AC_SUBST(toolexeclibdir) --- 427,437 ---- toolexecdir='$(libdir)/gcc-lib/$(target_alias)' toolexeclibdir='$(libdir)' fi ! multi_os_directory=`$CC -print-multi-os-directory` ! case $multi_os_directory in ! .) ;; # Avoid trailing /. ! *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; ! esac AC_SUBST(toolexecdir) AC_SUBST(toolexeclibdir) *************** else *** 289,296 **** fi AC_OUTPUT(Makefile include/Makefile, [ ! dnl Put all the -D options in a file. ! echo "$DEFS" > boehm-cflags if test -n "$CONFIG_FILES"; then LD="${ORIGINAL_LD_FOR_MULTILIBS}" --- 442,449 ---- fi AC_OUTPUT(Makefile include/Makefile, [ ! dnl Put all the -I and -D options in a file. ! echo "$INCLUDES $DEFS" > boehm-cflags if test -n "$CONFIG_FILES"; then LD="${ORIGINAL_LD_FOR_MULTILIBS}" *************** gc_basedir=${gc_basedir} *** 306,309 **** --- 459,463 ---- CC="${CC}" ORIGINAL_LD_FOR_MULTILIBS="${ORIGINAL_LD_FOR_MULTILIBS}" DEFS="$DEFS" + INCLUDES="$INCLUDES" ) diff -Nrc3pad gcc-3.3.3/boehm-gc/cord/cordbscs.c gcc-3.4.0/boehm-gc/cord/cordbscs.c *** gcc-3.3.3/boehm-gc/cord/cordbscs.c 2001-08-17 18:30:48.000000000 +0000 --- gcc-3.4.0/boehm-gc/cord/cordbscs.c 2003-07-28 04:18:22.000000000 +0000 *************** CORD CORD_cat_char_star(CORD x, const ch *** 219,225 **** result->len = result_len; result->left = x; result->right = y; ! if (depth > MAX_DEPTH) { return(CORD_balance((CORD)result)); } else { return((CORD) result); --- 219,225 ---- result->len = result_len; result->left = x; result->right = y; ! if (depth >= MAX_DEPTH) { return(CORD_balance((CORD)result)); } else { return((CORD) result); *************** CORD CORD_cat(CORD x, CORD y) *** 260,266 **** result->len = result_len; result->left = x; result->right = y; ! return((CORD) result); } } --- 260,270 ---- result->len = result_len; result->left = x; result->right = y; ! if (depth >= MAX_DEPTH) { ! return(CORD_balance((CORD)result)); ! } else { ! return((CORD) result); ! } } } diff -Nrc3pad gcc-3.3.3/boehm-gc/cord/cordprnt.c gcc-3.4.0/boehm-gc/cord/cordprnt.c *** gcc-3.3.3/boehm-gc/cord/cordprnt.c 2001-08-17 18:30:48.000000000 +0000 --- gcc-3.4.0/boehm-gc/cord/cordprnt.c 2003-07-28 04:18:22.000000000 +0000 *************** int CORD_vsprintf(CORD * out, CORD forma *** 233,239 **** if (width == NONE && prec == NONE) { register char c; ! c = va_arg(args, int); CORD_ec_append(result, c); goto done; } --- 233,239 ---- if (width == NONE && prec == NONE) { register char c; ! c = (char)va_arg(args, int); CORD_ec_append(result, c); goto done; } *************** int CORD_vsprintf(CORD * out, CORD forma *** 255,266 **** /* Use standard sprintf to perform conversion */ { register char * buf; ! va_list vsprintf_args = args; ! /* The above does not appear to be sanctioned */ ! /* by the ANSI C standard. */ int max_size = 0; int res; ! if (width == VARIABLE) width = va_arg(args, int); if (prec == VARIABLE) prec = va_arg(args, int); if (width != NONE) max_size = width; --- 255,272 ---- /* Use standard sprintf to perform conversion */ { register char * buf; ! va_list vsprintf_args; int max_size = 0; int res; ! # ifdef __va_copy ! __va_copy(vsprintf_args, args); ! # else ! # if defined(__GNUC__) /* and probably in other cases */ ! va_copy(vsprintf_args, args); ! # else ! vsprintf_args = args; ! # endif ! # endif if (width == VARIABLE) width = va_arg(args, int); if (prec == VARIABLE) prec = va_arg(args, int); if (width != NONE) max_size = width; diff -Nrc3pad gcc-3.3.3/boehm-gc/cord/de_win.c gcc-3.4.0/boehm-gc/cord/de_win.c *** gcc-3.3.3/boehm-gc/cord/de_win.c 2001-08-17 18:30:48.000000000 +0000 --- gcc-3.4.0/boehm-gc/cord/de_win.c 2003-07-28 04:18:22.000000000 +0000 *************** LRESULT CALLBACK WndProc (HWND hwnd, UIN *** 249,255 **** case IDM_HELPABOUT: if( DialogBox( hInstance, "ABOUTBOX", ! hwnd, lpfnAboutBox ) ); InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); case IDM_HELPCONTENTS: --- 249,255 ---- case IDM_HELPABOUT: if( DialogBox( hInstance, "ABOUTBOX", ! hwnd, lpfnAboutBox ) ) InvalidateRect( hwnd, NULL, TRUE ); return( 0 ); case IDM_HELPCONTENTS: diff -Nrc3pad gcc-3.3.3/boehm-gc/darwin_stop_world.c gcc-3.4.0/boehm-gc/darwin_stop_world.c *** gcc-3.3.3/boehm-gc/darwin_stop_world.c 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/darwin_stop_world.c 2003-07-28 03:46:09.000000000 +0000 *************** *** 0 **** --- 1,209 ---- + #include "private/pthread_support.h" + + # if defined(GC_DARWIN_THREADS) + + #define DEBUG_THREADS 0 + + /* From "Inside Mac OS X - Mach-O Runtime Architecture" published by Apple + Page 49: + "The space beneath the stack pointer, where a new stack frame would normally + be allocated, is called the red zone. This area as shown in Figure 3-2 may + be used for any purpose as long as a new stack frame does not need to be + added to the stack." + + Page 50: "If a leaf procedure's red zone usage would exceed 224 bytes, then + it must set up a stack frame just like routines that call other routines." + */ + #define PPC_RED_ZONE_SIZE 224 + + void GC_push_all_stacks() { + int i; + kern_return_t r; + GC_thread p; + pthread_t me; + ptr_t lo, hi; + # if defined(POWERPC) + ppc_thread_state_t state; + # else + # error FIXME for non-ppc OS X + # endif + mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT; + + me = pthread_self(); + if (!GC_thr_initialized) GC_thr_init(); + + for(i=0;inext) { + if(p -> flags & FINISHED) continue; + if(pthread_equal(p->id,me)) { + lo = GC_approx_sp(); + } else { + /* Get the thread state (registers, etc) */ + r = thread_get_state( + p->stop_info.mach_thread, + MACHINE_THREAD_STATE, + (natural_t*)&state, + &thread_state_count); + if(r != KERN_SUCCESS) ABORT("thread_get_state failed"); + + #ifdef POWERPC + lo = (void*)(state.r1 - PPC_RED_ZONE_SIZE); + + GC_push_one(state.r0); + GC_push_one(state.r2); + GC_push_one(state.r3); + GC_push_one(state.r4); + GC_push_one(state.r5); + GC_push_one(state.r6); + GC_push_one(state.r7); + GC_push_one(state.r8); + GC_push_one(state.r9); + GC_push_one(state.r10); + GC_push_one(state.r11); + GC_push_one(state.r12); + GC_push_one(state.r13); + GC_push_one(state.r14); + GC_push_one(state.r15); + GC_push_one(state.r16); + GC_push_one(state.r17); + GC_push_one(state.r18); + GC_push_one(state.r19); + GC_push_one(state.r20); + GC_push_one(state.r21); + GC_push_one(state.r22); + GC_push_one(state.r23); + GC_push_one(state.r24); + GC_push_one(state.r25); + GC_push_one(state.r26); + GC_push_one(state.r27); + GC_push_one(state.r28); + GC_push_one(state.r29); + GC_push_one(state.r30); + GC_push_one(state.r31); + #else + # error FIXME for non-PPC darwin + #endif /* !POWERPC */ + } /* p != me */ + if(p->flags & MAIN_THREAD) + hi = GC_stackbottom; + else + hi = p->stack_end; + #if DEBUG_THREADS + GC_printf3("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n", + (unsigned long) p -> id, + (unsigned long) lo, + (unsigned long) hi + ); + #endif + GC_push_all_stack(lo,hi); + } /* for(p=GC_threads[i]...) */ + } /* for(i=0;i next) { + if (p -> id == my_thread) continue; + if (p -> flags & FINISHED) continue; + if (p -> thread_blocked) /* Will wait */ continue; + + #if DEBUG_THREADS + GC_printf1("Suspending thread 0x%lx\n", p -> id); + #endif + + /* Suspend the thread */ + kern_result = thread_suspend(p->stop_info.mach_thread); + if(kern_result != KERN_SUCCESS) ABORT("thread_suspend failed"); + + /* This is only needed if we are modifying the threads + state. thread_abort_safely should also be used + if this code is ever added in again. + + kern_result = thread_abort(p->stop_info.mach_thread); + if(kern_result != KERN_SUCCESS) + ABORT("thread_abort failed (%ul)",kern_result); + */ + } + } + + # ifdef MPROTECT_VDB + if(GC_incremental) { + extern void GC_mprotect_stop(); + GC_mprotect_stop(); + } + # endif + + # ifdef PARALLEL_MARK + GC_release_mark_lock(); + # endif + #if DEBUG_THREADS + GC_printf1("World stopped from 0x%lx\n", pthread_self()); + #endif + } + + /* Caller holds allocation lock, and has held it continuously since */ + /* the world stopped. */ + void GC_start_world() + { + pthread_t my_thread = pthread_self(); + int i; + GC_thread p; + kern_return_t kern_result; + + # if DEBUG_THREADS + GC_printf0("World starting\n"); + # endif + + # ifdef MPROTECT_VDB + if(GC_incremental) { + extern void GC_mprotect_resume(); + GC_mprotect_resume(); + } + # endif + + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + if (p -> id == my_thread) continue; + if (p -> flags & FINISHED) continue; + if (p -> thread_blocked) continue; + + #if DEBUG_THREADS + GC_printf1("Resuming 0x%lx\n", p -> id); + #endif + + /* Resume the thread */ + kern_result = thread_resume(p->stop_info.mach_thread); + if(kern_result != KERN_SUCCESS) ABORT("thread_resume failed"); + } + } + #if DEBUG_THREADS + GC_printf0("World started\n"); + #endif + } + + void GC_stop_init() { + + } + + #endif diff -Nrc3pad gcc-3.3.3/boehm-gc/dbg_mlc.c gcc-3.4.0/boehm-gc/dbg_mlc.c *** gcc-3.3.3/boehm-gc/dbg_mlc.c 2002-02-13 05:38:39.000000000 +0000 --- gcc-3.4.0/boehm-gc/dbg_mlc.c 2003-07-28 04:18:20.000000000 +0000 *************** ptr_t p; *** 60,66 **** # include # if defined(LINUX) || defined(SUNOS4) || defined(SUNOS5) \ ! || defined(HPUX) || defined(IRIX) || defined(OSF1) # define RANDOM() random() # else # define RANDOM() (long)rand() --- 60,66 ---- # include # if defined(LINUX) || defined(SUNOS4) || defined(SUNOS5) \ ! || defined(HPUX) || defined(IRIX5) || defined(OSF1) # define RANDOM() random() # else # define RANDOM() (long)rand() *************** ptr_t p; *** 228,233 **** --- 228,235 ---- #endif /* KEEP_BACK_PTRS */ + # define CROSSES_HBLK(p, sz) \ + (((word)(p + sizeof(oh) + sz - 1) ^ (word)p) >= HBLKSIZE) /* Store debugging info into p. Return displaced pointer. */ /* Assumes we don't hold allocation lock. */ ptr_t GC_store_debug_info(p, sz, string, integer) *************** word integer; *** 243,248 **** --- 245,252 ---- /* But that's expensive. And this way things should only appear */ /* inconsistent while we're in the handler. */ LOCK(); + GC_ASSERT(GC_size(p) >= sizeof(oh) + sz); + GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz))); # ifdef KEEP_BACK_PTRS ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED); # endif *************** word integer; *** 275,280 **** --- 279,286 ---- /* There is some argument that we should disable signals here. */ /* But that's expensive. And this way things should only appear */ /* inconsistent while we're in the handler. */ + GC_ASSERT(GC_size(p) >= sizeof(oh) + sz); + GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz))); # ifdef KEEP_BACK_PTRS ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED); # endif *************** ptr_t p; *** 324,333 **** { register oh * ohdr = (oh *)GC_base(p); GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh))); GC_err_puts(ohdr -> oh_string); # ifdef SHORT_DBG_HDRS ! GC_err_printf1(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int)); # else GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int), (unsigned long)(ohdr -> oh_sz)); --- 330,340 ---- { register oh * ohdr = (oh *)GC_base(p); + GC_ASSERT(!I_HOLD_LOCK()); GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh))); GC_err_puts(ohdr -> oh_string); # ifdef SHORT_DBG_HDRS ! GC_err_printf1(":%ld)\n", (unsigned long)(ohdr -> oh_int)); # else GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int), (unsigned long)(ohdr -> oh_sz)); *************** ptr_t p; *** 342,347 **** --- 349,355 ---- ptr_t p; # endif { + GC_ASSERT(!I_HOLD_LOCK()); if (GC_HAS_DEBUG_INFO(p)) { GC_print_obj(p); } else { *************** ptr_t p, clobbered_addr; *** 355,360 **** --- 363,369 ---- { register oh * ohdr = (oh *)GC_base(p); + GC_ASSERT(!I_HOLD_LOCK()); GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr, (unsigned long)p); if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz)) *************** ptr_t p, clobbered_addr; *** 376,389 **** --- 385,402 ---- void GC_check_heap_proc GC_PROTO((void)); + void GC_print_all_smashed_proc GC_PROTO((void)); + void GC_do_nothing() {} void GC_start_debugging() { # ifndef SHORT_DBG_HDRS GC_check_heap = GC_check_heap_proc; + GC_print_all_smashed = GC_print_all_smashed_proc; # else GC_check_heap = GC_do_nothing; + GC_print_all_smashed = GC_do_nothing; # endif GC_print_heap_obj = GC_debug_print_heap_obj_proc; GC_debugging_started = TRUE; *************** void GC_start_debugging() *** 429,434 **** --- 442,503 ---- return (GC_store_debug_info(result, (word)lb, s, (word)i)); } + # ifdef __STDC__ + GC_PTR GC_debug_malloc_ignore_off_page(size_t lb, GC_EXTRA_PARAMS) + # else + GC_PTR GC_debug_malloc_ignore_off_page(lb, s, i) + size_t lb; + char * s; + int i; + # ifdef GC_ADD_CALLER + --> GC_ADD_CALLER not implemented for K&R C + # endif + # endif + { + GC_PTR result = GC_malloc_ignore_off_page(lb + DEBUG_BYTES); + + if (result == 0) { + GC_err_printf1("GC_debug_malloc_ignore_off_page(%ld) returning NIL (", + (unsigned long) lb); + GC_err_puts(s); + GC_err_printf1(":%ld)\n", (unsigned long)i); + return(0); + } + if (!GC_debugging_started) { + GC_start_debugging(); + } + ADD_CALL_CHAIN(result, ra); + return (GC_store_debug_info(result, (word)lb, s, (word)i)); + } + + # ifdef __STDC__ + GC_PTR GC_debug_malloc_atomic_ignore_off_page(size_t lb, GC_EXTRA_PARAMS) + # else + GC_PTR GC_debug_malloc_atomic_ignore_off_page(lb, s, i) + size_t lb; + char * s; + int i; + # ifdef GC_ADD_CALLER + --> GC_ADD_CALLER not implemented for K&R C + # endif + # endif + { + GC_PTR result = GC_malloc_atomic_ignore_off_page(lb + DEBUG_BYTES); + + if (result == 0) { + GC_err_printf1("GC_debug_malloc_atomic_ignore_off_page(%ld)" + " returning NIL (", (unsigned long) lb); + GC_err_puts(s); + GC_err_printf1(":%ld)\n", (unsigned long)i); + return(0); + } + if (!GC_debugging_started) { + GC_start_debugging(); + } + ADD_CALL_CHAIN(result, ra); + return (GC_store_debug_info(result, (word)lb, s, (word)i)); + } + # ifdef DBG_HDRS_ALL /* * An allocation function for internal use. *************** void GC_start_debugging() *** 447,453 **** (unsigned long) lb); return(0); } ! ADD_CALL_CHAIN(result, ra); return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); } --- 516,522 ---- (unsigned long) lb); return(0); } ! ADD_CALL_CHAIN(result, GC_RETURN_ADDR); return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); } *************** void GC_start_debugging() *** 461,467 **** (unsigned long) lb); return(0); } ! ADD_CALL_CHAIN(result, ra); return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); } # endif --- 530,536 ---- (unsigned long) lb); return(0); } ! ADD_CALL_CHAIN(result, GC_RETURN_ADDR); return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); } # endif *************** GC_PTR p; *** 592,598 **** int i; # endif { ! GC_PTR result = GC_malloc_uncollectable(lb + DEBUG_BYTES); if (result == 0) { GC_err_printf1("GC_debug_malloc_uncollectable(%ld) returning NIL (", --- 661,667 ---- int i; # endif { ! GC_PTR result = GC_malloc_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES); if (result == 0) { GC_err_printf1("GC_debug_malloc_uncollectable(%ld) returning NIL (", *************** GC_PTR p; *** 618,624 **** int i; # endif { ! GC_PTR result = GC_malloc_atomic_uncollectable(lb + DEBUG_BYTES); if (result == 0) { GC_err_printf1( --- 687,694 ---- int i; # endif { ! GC_PTR result = ! GC_malloc_atomic_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES); if (result == 0) { GC_err_printf1( *************** void GC_debug_free_inner(GC_PTR p) *** 774,779 **** --- 844,888 ---- } #ifndef SHORT_DBG_HDRS + + /* List of smashed objects. We defer printing these, since we can't */ + /* always print them nicely with the allocation lock held. */ + /* We put them here instead of in GC_arrays, since it may be useful to */ + /* be able to look at them with the debugger. */ + #define MAX_SMASHED 20 + ptr_t GC_smashed[MAX_SMASHED]; + unsigned GC_n_smashed = 0; + + # if defined(__STDC__) || defined(__cplusplus) + void GC_add_smashed(ptr_t smashed) + # else + void GC_add_smashed(smashed) + ptr_t smashed; + #endif + { + GC_ASSERT(GC_is_marked(GC_base(smashed))); + GC_smashed[GC_n_smashed] = smashed; + if (GC_n_smashed < MAX_SMASHED - 1) ++GC_n_smashed; + /* In case of overflow, we keep the first MAX_SMASHED-1 */ + /* entries plus the last one. */ + GC_have_errors = TRUE; + } + + /* Print all objects on the list. Clear the list. */ + void GC_print_all_smashed_proc () + { + unsigned i; + + GC_ASSERT(!I_HOLD_LOCK()); + if (GC_n_smashed == 0) return; + GC_err_printf0("GC_check_heap_block: found smashed heap objects:\n"); + for (i = 0; i < GC_n_smashed; ++i) { + GC_print_smashed_obj(GC_base(GC_smashed[i]), GC_smashed[i]); + GC_smashed[i] = 0; + } + GC_n_smashed = 0; + } + /* Check all marked objects in the given block for validity */ /*ARGSUSED*/ # if defined(__STDC__) || defined(__cplusplus) *************** void GC_debug_free_inner(GC_PTR p) *** 802,812 **** && GC_HAS_DEBUG_INFO((ptr_t)p)) { ptr_t clobbered = GC_check_annotated_obj((oh *)p); ! if (clobbered != 0) { ! GC_err_printf0( ! "GC_check_heap_block: found smashed location at "); ! GC_print_smashed_obj((ptr_t)p, clobbered); ! } } word_no += sz; p += sz; --- 911,917 ---- && GC_HAS_DEBUG_INFO((ptr_t)p)) { ptr_t clobbered = GC_check_annotated_obj((oh *)p); ! if (clobbered != 0) GC_add_smashed(clobbered); } word_no += sz; p += sz; *************** void GC_debug_free_inner(GC_PTR p) *** 819,827 **** void GC_check_heap_proc() { # ifndef SMALL_CONFIG ! if (sizeof(oh) & (2 * sizeof(word) - 1) != 0) { ! ABORT("Alignment problem: object header has inappropriate size\n"); ! } # endif GC_apply_to_all_blocks(GC_check_heap_block, (word)0); } --- 924,934 ---- void GC_check_heap_proc() { # ifndef SMALL_CONFIG ! # ifdef ALIGN_DOUBLE ! GC_STATIC_ASSERT((sizeof(oh) & (2 * sizeof(word) - 1)) == 0); ! # else ! GC_STATIC_ASSERT((sizeof(oh) & (sizeof(word) - 1)) == 0); ! # endif # endif GC_apply_to_all_blocks(GC_check_heap_block, (word)0); } *************** struct closure { *** 842,853 **** # endif { struct closure * result = ! # ifdef DBG_HDRS_ALL ! (struct closure *) GC_debug_malloc(sizeof (struct closure), ! GC_EXTRAS); ! # else ! (struct closure *) GC_malloc(sizeof (struct closure)); ! # endif result -> cl_fn = fn; result -> cl_data = data; --- 949,960 ---- # endif { struct closure * result = ! # ifdef DBG_HDRS_ALL ! (struct closure *) GC_debug_malloc(sizeof (struct closure), ! GC_EXTRAS); ! # else ! (struct closure *) GC_malloc(sizeof (struct closure)); ! # endif result -> cl_fn = fn; result -> cl_data = data; *************** GC_PTR *ocd; *** 908,914 **** ptr_t base = GC_base(obj); if (0 == base || (ptr_t)obj - base != sizeof(oh)) { GC_err_printf1( ! "GC_register_finalizer called with non-base-pointer 0x%lx\n", obj); } if (0 == fn) { --- 1015,1021 ---- ptr_t base = GC_base(obj); if (0 == base || (ptr_t)obj - base != sizeof(oh)) { GC_err_printf1( ! "GC_debug_register_finalizer called with non-base-pointer 0x%lx\n", obj); } if (0 == fn) { *************** GC_PTR *ocd; *** 940,946 **** ptr_t base = GC_base(obj); if (0 == base || (ptr_t)obj - base != sizeof(oh)) { GC_err_printf1( ! "GC_register_finalizer_no_order called with non-base-pointer 0x%lx\n", obj); } if (0 == fn) { --- 1047,1053 ---- ptr_t base = GC_base(obj); if (0 == base || (ptr_t)obj - base != sizeof(oh)) { GC_err_printf1( ! "GC_debug_register_finalizer_no_order called with non-base-pointer 0x%lx\n", obj); } if (0 == fn) { *************** GC_PTR *ocd; *** 973,979 **** ptr_t base = GC_base(obj); if (0 == base || (ptr_t)obj - base != sizeof(oh)) { GC_err_printf1( ! "GC_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n", obj); } if (0 == fn) { --- 1080,1086 ---- ptr_t base = GC_base(obj); if (0 == base || (ptr_t)obj - base != sizeof(oh)) { GC_err_printf1( ! "GC_debug_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n", obj); } if (0 == fn) { diff -Nrc3pad gcc-3.3.3/boehm-gc/depcomp gcc-3.4.0/boehm-gc/depcomp *** gcc-3.3.3/boehm-gc/depcomp 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/depcomp 2003-07-28 03:46:15.000000000 +0000 *************** *** 0 **** --- 1,436 ---- + #! /bin/sh + + # depcomp - compile a program generating dependencies as side-effects + # Copyright 1999, 2000 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, 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. + + # Originally written by Alexandre Oliva . + + 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 + # `libtool' can also be set to `yes' or `no'. + + if test -z "$depfile"; then + base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` + dir=`echo "$object" | sed 's,/.*$,/,'` + if test "$dir" = "$object"; then + dir= + fi + # FIXME: should be _deps on DOS. + depfile="$dir.deps/$base" + fi + + tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + + rm -f "$tmpdepfile" + + # 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 + + 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. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + + gcc) + ## 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). + ## - 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 -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz + ## 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. + tr ' ' ' + ' < "$tmpdepfile" | + ## 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. + ## Some versions of the HPUX 10.20 sed can't process this invocation + ## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -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 -eq 0; then : + else + 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 ' ' ' + ' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' + ' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' + ' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + + aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. 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. + stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + outname="$stripped.o" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + + 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. + + base=`echo "$object" | sed -e 's/\.o$//' -e 's/\.lo$//'` + tmpdepfile1="$base.o.d" + tmpdepfile2="$base.d" + if test "$libtool" = yes; then + "$@" -Wc,-MD + else + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + else + tmpdepfile="$tmpdepfile2" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a space and a tab in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + + #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 proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + test -z "$dashmflag" && dashmflag=-M + ( IFS=" " + case " $* " in + *" --mode=compile "*) # this is libtool, let us make it quiet + for arg + do # cycle over the arguments + case "$arg" in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' + ' < "$tmpdepfile" | \ + ## Some versions of the HPUX 10.20 sed can't process this invocation + ## correctly. Breaking it into two sed invocations is a workaround. + 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) + # X makedepend + ( + shift + cleared=no + for arg in "$@"; do + case $cleared in no) + set ""; shift + cleared=yes + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift;; + -*) + ;; + *) + set fnord "$@" "$arg"; shift;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' + ' | \ + ## Some versions of the HPUX 10.20 sed can't process this invocation + ## correctly. Breaking it into two sed invocations is a workaround. + 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 proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + ( IFS=" " + case " $* " in + *" --mode=compile "*) + for arg + do # cycle over the arguments + case $arg in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + 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 proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + ( IFS=" " + case " $* " in + *" --mode=compile "*) + for arg + do # cycle over the arguments + case $arg in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + + none) + exec "$@" + ;; + + *) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; + esac + + exit 0 diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/debugging.html gcc-3.4.0/boehm-gc/doc/debugging.html *** gcc-3.3.3/boehm-gc/doc/debugging.html 2002-02-12 04:37:55.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/debugging.html 2003-07-28 04:18:22.000000000 +0000 *************** The hb_last_reclaimed field wil *** 248,255 **** during which its block was last swept.
  • Verify that the offending object still has its correct contents at this point. ! The call GC_is_marked(p) from the debugger to verify that the ! object has not been marked, and is about to be reclaimed.
  • Determine a path from a root, i.e. static variable, stack, or register variable, to the reclaimed object. Call GC_is_marked(q) for each object --- 248,259 ---- during which its block was last swept.
  • Verify that the offending object still has its correct contents at this point. ! Then call GC_is_marked(p) from the debugger to verify that the ! object has not been marked, and is about to be reclaimed. Note that ! GC_is_marked(p) expects the real address of an object (the ! address of the debug header if there is one), and thus it may ! be more appropriate to call GC_is_marked(GC_base(p)) ! instead.
  • Determine a path from a root, i.e. static variable, stack, or register variable, to the reclaimed object. Call GC_is_marked(q) for each object diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/gcdescr.html gcc-3.4.0/boehm-gc/doc/gcdescr.html *** gcc-3.3.3/boehm-gc/doc/gcdescr.html 2001-08-17 18:39:18.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/gcdescr.html 2003-07-28 04:18:22.000000000 +0000 *************** *** 1,7 **** Conservative GC Algorithmic Overview ! Hans-J. Boehm, Silicon Graphics

    This is under construction

    --- 1,7 ---- Conservative GC Algorithmic Overview ! Hans-J. Boehm, HP Labs (Much of this was written at SGI)

    This is under construction

    *************** typically on the order of the page size. *** 96,115 ****

    Large block sizes are rounded up to the next multiple of HBLKSIZE and then allocated by ! GC_allochblk. This uses roughly what Paul Wilson has termed ! a "next fit" algorithm, i.e. first-fit with a rotating pointer. ! The implementation does check for a better fitting immediately ! adjacent block, which gives it somewhat better fragmentation characteristics. ! I'm now convinced it should use a best fit algorithm. The actual implementation of GC_allochblk is significantly complicated by black-listing issues (see below).

    ! Small blocks are allocated in blocks of size HBLKSIZE. ! Each block is dedicated to only one object size and kind. The allocator maintains separate free lists for each size and kind of object.

    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 --- 96,119 ----

    Large block sizes are rounded up to the next multiple of HBLKSIZE and then allocated by ! GC_allochblk. Recent versions of the collector ! use an approximate best fit algorithm by keeping free lists for ! several large block sizes. ! The actual implementation of GC_allochblk is significantly complicated by black-listing issues (see below).

    ! Small blocks are allocated in chunks of size HBLKSIZE. ! Each chunk is dedicated to only one object size and kind. The allocator maintains separate free lists for each size and kind of object.

    + Once a large block is split for use in smaller objects, it can only + be used for objects of that size, unless the collector discovers a completely + empty chunk. Completely empty chunks are restored to the appropriate + 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 *************** expand the heap. Otherwise, we initiate *** 139,165 **** that the amount of garbage collection work per allocated byte remains constant.

    ! The above is in fat an oversimplification of the real heap expansion ! heuristic, which adjusts slightly for root size and certain kinds of ! fragmentation. In particular, programs with a large root set size and little live heap memory will expand the heap to amortize the cost of ! scanning the roots. !

    ! Versions 5.x of the collector actually collect more frequently in nonincremental mode. The large block allocator usually refuses to split large heap blocks once the garbage collection threshold is reached. This often has the effect of collecting well before the heap fills up, thus reducing fragmentation and working set size at the ! expense of GC time. 6.x will chose an intermediate strategy depending on how much large object allocation has taken place in the past. (If the collector is configured to unmap unused pages, versions 6.x ! will use the 5.x strategy.)

    ! (It has been suggested that this should be adjusted so that we favor expansion if the resulting heap still fits into physical memory. In many cases, that would no doubt help. But it is tricky to do this in a way that remains robust if multiple application are contending ! for a single pool of physical memory.)

    Mark phase

    --- 143,177 ---- that the amount of garbage collection work per allocated byte remains constant.

    ! The above is in fact an oversimplification of the real heap expansion ! and GC triggering heuristic, which adjusts slightly for root size ! and certain kinds of ! fragmentation. In particular: !

      !
    • Programs with a large root set size and little live heap memory will expand the heap to amortize the cost of ! scanning the roots. !
    • Versions 5.x of the collector actually collect more frequently in nonincremental mode. The large block allocator usually refuses to split large heap blocks once the garbage collection threshold is reached. This often has the effect of collecting well before the heap fills up, thus reducing fragmentation and working set size at the ! expense of GC time. Versions 6.x choose an intermediate strategy depending on how much large object allocation has taken place in the past. (If the collector is configured to unmap unused pages, versions 6.x ! use the 5.x strategy.) !
    • In calculating the amount of allocation since the last collection we ! give partial credit for objects we expect to be explicitly deallocated. ! Even if all objects are explicitly managed, it is often desirable to collect ! on rare occasion, since that is our only mechanism for coalescing completely ! empty chunks. !

    ! It has been suggested that this should be adjusted so that we favor expansion if the resulting heap still fits into physical memory. In many cases, that would no doubt help. But it is tricky to do this in a way that remains robust if multiple application are contending ! for a single pool of physical memory.

    Mark phase

    *************** changes to *** 204,210 ****
  • MS_NONE indicating that reachable objects are marked. ! The core mark routine GC_mark_from_mark_stack, is called repeatedly by several of the sub-phases when the mark stack starts to fill up. It is also called repeatedly in MS_ROOTS_PUSHED state to empty the mark stack. --- 216,222 ----
  • MS_NONE indicating that reachable objects are marked. ! The core mark routine GC_mark_from, is called repeatedly by several of the sub-phases when the mark stack starts to fill up. It is also called repeatedly in MS_ROOTS_PUSHED state to empty the mark stack. *************** each call, so that it can also be used b *** 213,218 **** --- 225,236 ---- 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 + 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 + scale.html +

    The marker correctly handles mark stack overflows. Whenever the mark stack overflows, the mark state is reset to MS_INVALID. Since there are already marked objects in the heap, *************** Unmarked large objects are immediately r *** 281,287 **** Each small object page is checked to see if all mark bits are clear. If so, the entire page is returned to the large object free list. Small object pages containing some reachable object are queued for later ! sweeping.

    This initial sweep pass touches only block headers, not the blocks themselves. Thus it does not require significant paging, even --- 299,306 ---- Each small object page is checked to see if all mark bits are clear. If so, the entire page is returned to the large object free list. Small object pages containing some reachable object are queued for later ! sweeping, unless we determine that the page contains very little free ! space, in which case it is not examined further.

    This initial sweep pass touches only block headers, not the blocks themselves. Thus it does not require significant paging, even *************** object itself becomes marked, we have un *** 341,352 **** a cycle involving the object. This usually results in a warning from the collector. Such objects are not finalized, since it may be unsafe to do so. See the more detailed ! discussion of finalization semantics.

    Any objects remaining unmarked at the end of this process are added to a queue of objects whose finalizers can be run. Depending on collector configuration, finalizers are dequeued and run either implicitly during allocation calls, or explicitly in response to a user request.

    The collector provides a mechanism for replacing the procedure that is used to mark through objects. This is used both to provide support for --- 360,375 ---- a cycle involving the object. This usually results in a warning from the collector. Such objects are not finalized, since it may be unsafe to do so. See the more detailed ! discussion of finalization semantics.

    Any objects remaining unmarked at the end of this process are added to a queue of objects whose finalizers can be run. Depending on collector configuration, finalizers are dequeued and run either implicitly during allocation calls, or explicitly in response to a user request. + (Note that the former is unfortunately both the default and not generally safe. + If finalizers perform synchronization, it may result in deadlocks. + Nontrivial finalizers generally need to perform synchronization, and + thus require a different collector configuration.)

    The collector provides a mechanism for replacing the procedure that is used to mark through objects. This is used both to provide support for *************** Java-style unordered finalization, and t *** 354,366 **** e.g. those arising from C++ implementations of virtual inheritance.

    Generational Collection and Dirty Bits

    ! We basically use the parallel and generational GC algorithm described in ! "Mostly Parallel Garbage Collection", by Boehm, Demers, and Shenker.

    The most significant modification is that ! the collector always runs in the allocating thread. ! There is no separate garbage collector thread. If an allocation attempt either requests a large object, or encounters an empty small object free list, and notices that there is a collection in progress, it immediately performs a small amount of marking work --- 377,390 ---- e.g. those arising from C++ implementations of virtual inheritance.

    Generational Collection and Dirty Bits

    ! We basically use the concurrent and generational GC algorithm described in ! "Mostly Parallel Garbage Collection", by Boehm, Demers, and Shenker.

    The most significant modification is that ! the collector always starts running in the allocating thread. ! There is no separate garbage collector thread. (If parallel GC is ! enabled, helper threads may also be woken up.) If an allocation attempt either requests a large object, or encounters an empty small object free list, and notices that there is a collection in progress, it immediately performs a small amount of marking work *************** cannot be satisfied from small object fr *** 389,438 **** the set of modified pages is retrieved, and we mark once again from marked objects on those pages, this time with the mutator stopped.

    ! We keep track of modified pages using one of three distinct mechanisms:

    1. Through explicit mutator cooperation. Currently this requires ! the use of GC_malloc_stubborn.
    2. ! By write-protecting physical pages and catching write faults. This is implemented for many Unix-like systems and for win32. It is not possible in a few environments.
    3. ! By retrieving dirty bit information from /proc. (Currently only Sun's Solaris supports this. Though this is considerably cleaner, performance may actually be better with mprotect and signals.)

    Thread support

    We support several different threading models. Unfortunately Pthreads, the only reasonably well standardized thread model, supports too narrow an interface for conservative garbage collection. There appears to be ! no portable way to allow the collector to coexist with various Pthreads implementations. Hence we currently support only a few of the more 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 different Pthreads implementations. The Solaris implementation temporarily disables much of the user-level threads implementation by stopping kernel-level threads ! ("lwp"s). The Irix implementation sends signals to individual Pthreads ! and has them wait in the signal handler. The Linux implementation ! is similar in spirit to the Irix one.

    ! The Irix implementation uses ! only documented Pthreads calls, but relies on extensions to their semantics, ! notably the use of mutexes and condition variables from signal ! handlers. The Linux implementation should be far closer to ! portable, though impirically it is not completely portable.

    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 ! accomplished with # define's in gc.h, or optionally by using ld's function call wrapping mechanism under Linux.

    Comments are appreciated. Please send mail to ! boehm@acm.org --- 413,520 ---- the set of modified pages is retrieved, and we mark once again from marked objects on those pages, this time with the mutator stopped.

    ! We keep track of modified pages using one of several distinct mechanisms:

    1. Through explicit mutator cooperation. Currently this requires ! the use of GC_malloc_stubborn, and is rarely used.
    2. ! (MPROTECT_VDB) By write-protecting physical pages and ! catching write faults. This is implemented for many Unix-like systems and for win32. It is not possible in a few environments.
    3. ! (PROC_VDB) By retrieving dirty bit information from /proc. ! (Currently only Sun's Solaris supports this. Though this is considerably cleaner, performance may actually be better with mprotect and signals.) +
    4. + (PCR_VDB) By relying on an external dirty bit implementation, in this + case the one in Xerox PCR. +
    5. + (DEFAULT_VDB) By treating all pages as dirty. This is the default if + none of the other techniques is known to be usable, and + GC_malloc_stubborn is not used. Practical only for testing, or if + the vast majority of objects use GC_malloc_stubborn.
    +

    Black-listing

    + + The collector implements black-listing of pages, as described + in + + Boehm, ``Space Efficient Conservative Collection'', PLDI '93, also available + 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 + to a currently unallocated page inside the heap. Pages that have been + the targets of such near misses are likely to be the targets of + misidentified ``pointers'' in the future. To minimize the future + damage caused by such misidentifications they will be allocated only to + small pointerfree objects. +

    + The collector understands two different kinds of black-listing. A + page may be black listed for interior pointer references + (GC_add_to_black_list_stack), if it was the target of a near + miss from a location that requires interior pointer recognition, + e.g. the stack, or the heap if GC_all_interior_pointers + is set. In this case, we also avoid allocating large blocks that include + this page. +

    + If the near miss came from a source that did not require interior + pointer recognition, it is black-listed with + GC_add_to_black_list_normal. + A page black-listed in this way may appear inside a large object, + so long as it is not the first page of a large object. +

    + The GC_allochblk routine respects black-listing when assigning + a block to a particular object kind and size. It occasionally + drops (i.e. allocates and forgets) blocks that are completely black-listed + in order to avoid excessively long large block free lists containing + only unusable blocks. This would otherwise become an issue + if there is low demand for small pointerfree objects. +

    Thread support

    We support several different threading models. Unfortunately Pthreads, the only reasonably well standardized thread model, supports too narrow an interface for conservative garbage collection. There appears to be ! no completely portable way to allow the collector to coexist with various Pthreads implementations. Hence we currently support only a few of the more 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 ! 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 ! 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 ! accomplished with # define's in gc.h ! (really gc_pthread_redirects.h), or optionally by using ld's function call wrapping mechanism under Linux.

    Comments are appreciated. Please send mail to ! boehm@acm.org or ! Hans.Boehm@hp.com !

    ! This is a modified copy of a page written while the author was at SGI. ! The original was here. + diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/gcinterface.html gcc-3.4.0/boehm-gc/doc/gcinterface.html *** gcc-3.3.3/boehm-gc/doc/gcinterface.html 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/gcinterface.html 2003-07-28 03:46:20.000000000 +0000 *************** *** 0 **** --- 1,203 ---- + + + Garbage Collector Interface + + +

    C Interface

    + On many platforms, a single-threaded garbage collector library can be built + to act as a plug-in malloc replacement. (Build with -DREDIRECT_MALLOC=GC_malloc + -DIGNORE_FREE.) This is often the best way to deal with third-party libraries + which leak or prematurely free objects. -DREDIRECT_MALLOC is intended + primarily as an easy way to adapt old code, not for new development. +

    + New code should use the interface discussed below. +

    + Code must be linked against the GC library. On most UNIX platforms, + this will be gc.a. +

    + The following describes the standard C interface to the garbage collector. + It is not a complete definition of the interface. It describes only the + most commonly used functionality, approximately in decreasing order of + frequency of use. The description assumes an ANSI C compiler. + The full interface is described in + gc.h + or gc.h in the distribution. +

    + Clients should include gc.h. +

    + In the case of multithreaded code, + gc.h should be included after the threads header file, and + after defining the appropriate GC_XXXX_THREADS macro. + (For 6.2alpha4 and later, simply defining GC_THREADS should suffice.) + Gc.h must be included + in files that use either GC or threads primitives, since threads primitives + will be redefined to cooperate with the GC on many platforms. +

    +
    void * GC_MALLOC(size_t nbytes) +
    + Allocates and clears nbytes of storage. + Requires (amortized) time proportional to nbytes. + The resulting object will be automatically deallocated when unreferenced. + References from objects allocated with the system malloc are usually not + considered by the collector. (See GC_MALLOC_UNCOLLECTABLE, however.) + GC_MALLOC is a macro which invokes GC_malloc by default or, if GC_DEBUG + is defined before gc.h is included, a debugging version that checks + occasionally for overwrite errors, and the like. +
    void * GC_MALLOC_ATOMIC(size_t nbytes) +
    + Allocates nbytes of storage. + Requires (amortized) time proportional to nbytes. + The resulting object will be automatically deallocated when unreferenced. + The client promises that the resulting object will never contain any pointers. + The memory is not cleared. + This is the preferred way to allocate strings, floating point arrays, + bitmaps, etc. + More precise information about pointer locations can be communicated to the + collector using the interface in + gc_typed.h in the distribution. +
    void * GC_MALLOC_UNCOLLECTABLE(size_t nbytes) +
    + Identical to GC_MALLOC, except that the resulting object is not automatically + deallocated. Unlike the system-provided malloc, the collector does + scan the object for pointers to garbage-collectable memory, even if the + block itself does not appear to be reachable. (Objects allocated in this way + are effectively treated as roots by the collector.) +
    void * GC_REALLOC(void *old, size_t new_size) +
    + Allocate a new object of the indicated size and copy (a prefix of) the + old object into the new object. The old object is reused in place if + convenient. If the original object was allocated with GC_malloc_atomic, + the new object is subject to the same constraints. If it was allocated + as an uncollectable object, then the new object is uncollectable, and + the old object (if different) is deallocated. + (Use GC_REALLOC with GC_MALLOC, etc.) +
    void GC_FREE(void *dead) +
    + Explicitly deallocate an object. Typically not useful for small + collectable objects. (Use GC_FREE with GC_MALLOC, etc.) +
    void * GC_MALLOC_IGNORE_OFF_PAGE(size_t nbytes) +
    +
    void * GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(size_t nbytes) +
    + Analogous to GC_MALLOC and GC_MALLOC_ATOMIC, except that the client + guarantees that as long + as the resulting object is of use, a pointer is maintained to someplace + inside the first 512 bytes of the object. This pointer should be declared + volatile to avoid interference from compiler optimizations. + (Other nonvolatile pointers to the object may exist as well.) + This is the + preferred way to allocate objects that are likely to be > 100KBytes in size. + It greatly reduces the risk that such objects will be accidentally retained + when they are no longer needed. Thus space usage may be significantly reduced. +
    void GC_gcollect(void) +
    + Explicitly force a garbage collection. +
    void GC_enable_incremental(void) +
    + Cause the garbage collector to perform a small amount of work + every few invocations of GC_malloc or the like, instead of performing + an entire collection at once. This is likely to increase total + running time. It will improve response on a platform that either has + suitable support in the garbage collector (Irix and most other Unix + versions, win32 if the collector was suitably built) or if "stubborn" + 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) +
    + Replace the default procedure used by the collector to print warnings. + The collector + may otherwise write to sterr, most commonly because GC_malloc was used + in a situation in which GC_malloc_ignore_off_page would have been more + appropriate. See gc.h for details. +
    void GC_register_finalizer(...) +
    + Register a function to be called when an object becomes inaccessible. + This is often useful as a backup method for releasing system resources + (e.g. closing files) when the object referencing them becomes + inaccessible. + It is not an acceptable method to perform actions that must be performed + in a timely fashion. + See gc.h for details of the interface. + See here for a more detailed discussion + of the design. +

    + Note that an object may become inaccessible before client code is done + operating on its fields. Suitable synchronization is usually required. + See here + or here + for details. +

    +

    + If you are concerned with multiprocessor performance and scalability, + you should consider enabling and using thread local allocation (e.g. + GC_LOCAL_MALLOC, see gc_local_alloc.h. If your platform + supports it, you should build the collector with parallel marking support + (-DPARALLEL_MARK, or --enable-parallel-mark). +

    + If the collector is used in an environment in which pointer location + information for heap objects is easily available, this can be passed on + to the colllector using the interfaces in either gc_typed.h + or gc_gcj.h. +

    + The collector distribution also includes a string package that takes + advantage of the collector. For details see + cord.h + +

    C++ Interface

    + There are three distinct ways to use the collector from C++: +
    +
    STL allocators +
    + Users of the SGI extended STL + can include new_gc_alloc.h before including + STL header files. + (gc_alloc.h corresponds to now obsolete versions of the + SGI STL.) + This defines SGI-style allocators +
      +
    • alloc +
    • single_client_alloc +
    • gc_alloc +
    • single_client_gc_alloc +
    + which may be used either directly to allocate memory or to instantiate + container templates. The first two allocate uncollectable but traced + memory, while the second two allocate collectable memory. + The single_client versions are not safe for concurrent access by + multiple threads, but are faster. +

    + For an example, click here. +

    + Recent versions of the collector also include a more standard-conforming + allocator implemention in gc_allocator.h. It defines +

      +
    • traceable_allocator +
    • gc_allocator +
    + Again the former allocates uncollectable but traced memory. + This should work with any fully standard-conforming C++ compiler. +
    Class inheritance based interface +
    + Users may include gc_cpp.h and then cause members of certain classes to + be allocated in garbage collectable memory by inheriting from class gc. + For details see gc_cpp.h. +
    C interface +
    + It is also possible to use the C interface from + gc.h directly. + On platforms which use malloc to implement ::new, it should usually be possible + to use a version of the collector that has been compiled as a malloc + replacement. It is also possible to replace ::new and other allocation + functions suitably. +

    + Note that user-implemented small-block allocation often works poorly with + an underlying garbage-collected large block allocator, since the collector + has to view all objects accessible from the user's free list as reachable. + This is likely to cause problems if GC_malloc is used with something like + the original HP version of STL. + This approach works with the SGI versions of the STL only if the + malloc_alloc allocator is used. +

    + + diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/leak.html gcc-3.4.0/boehm-gc/doc/leak.html *** gcc-3.3.3/boehm-gc/doc/leak.html 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/leak.html 2003-07-28 03:46:20.000000000 +0000 *************** *** 0 **** --- 1,197 ---- + + + Using the Garbage Collector as Leak Detector + + +

    Using the Garbage Collector as Leak Detector

    + The garbage collector may be used as a leak detector. + In this case, the primary function of the collector is to report + objects that were allocated (typically with GC_MALLOC), + not deallocated (normally with GC_FREE), but are + no longer accessible. Since the object is no longer accessible, + there in normally no way to deallocate the object at a later time; + thus it can safely be assumed that the object has been "leaked". +

    + This is substantially different from counting leak detectors, + which simply verify that all allocated objects are eventually + deallocated. A garbage-collector based leak detector can provide + somewhat more precise information when an object was leaked. + More importantly, it does not report objects that are never + deallocated because they are part of "permanent" data structures. + Thus it does not require all objects to be deallocated at process + exit time, a potentially useless activity that often triggers + large amounts of paging. +

    + All non-ancient versions of the garbage collector provide + leak detection support. Version 5.3 adds the following + features: +

      +
    1. Leak detection mode can be initiated at run-time by + setting GC_find_leak instead of building the collector with FIND_LEAK + defined. This variable should be set to a nonzero value + at program startup. +
    2. Leaked objects should be reported and then correctly garbage collected. + Prior versions either reported leaks or functioned as a garbage collector. +
    + For the rest of this description we will give instructions that work + with any reasonable version of the collector. +

    + To use the collector as a leak detector, follow the following steps: +

      +
    1. Build the collector with -DFIND_LEAK. Otherwise use default + build options. +
    2. Change the program so that all allocation and deallocation goes + through the garbage collector. +
    3. Arrange to call GC_gcollect at appropriate points to check + for leaks. + (For sufficiently long running programs, this will happen implicitly, + but probably not with sufficient frequency.) +
    + The second step can usually be accomplished with the + -DREDIRECT_MALLOC=GC_malloc option when the collector is built, + or by defining malloc, calloc, + realloc and free + to call the corresponding garbage collector functions. + But this, by itself, will not yield very informative diagnostics, + since the collector does not keep track of information about + how objects were allocated. The error reports will include + only object addresses. +

    + For more precise error reports, as much of the program as possible + should use the all uppercase variants of these functions, after + defining GC_DEBUG, and then including gc.h. + In this environment GC_MALLOC is a macro which causes + 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, + 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. +

    + The same is generally true of thread support. However, as of 6.0alpha4, + correct leak reports should be generated with linuxthreads. +

    + On a few platforms (currently Solaris/SPARC, Irix, and, with -DSAVE_CALL_CHAIN, + Linux/X86), GC_MALLOC + also causes some more information about its call stack to be saved + in the object. Such information is reproduced in the error + reports in very non-symbolic form, but it can be very useful with the + aid of a debugger. +

    An Example

    + The following header file leak_detector.h is included in the + "include" subdirectory of the distribution: +
    + #define GC_DEBUG
    + #include "gc.h"
    + #define malloc(n) GC_MALLOC(n)
    + #define calloc(m,n) GC_MALLOC((m)*(n))
    + #define free(p) GC_FREE(p)
    + #define realloc(p,n) GC_REALLOC((p),(n))
    + #define CHECK_LEAKS() GC_gcollect()
    + 
    +

    + Assume the collector has been built with -DFIND_LEAK. (For very + new versions of the collector, we could instead add the statement + GC_find_leak = 1 as the first statement in main. +

    + The program to be tested for leaks can then look like: +

    + #include "leak_detector.h"
    + 
    + main() {
    +     int *p[10];
    +     int i;
    +     /* GC_find_leak = 1; for new collector versions not 	*/
    +     /* compiled with -DFIND_LEAK.				*/
    +     for (i = 0; i < 10; ++i) {
    + 	p[i] = malloc(sizeof(int)+i);
    +     }
    +     for (i = 1; i < 10; ++i) {
    + 	free(p[i]);
    +     }
    +     for (i = 0; i < 9; ++i) {
    + 	p[i] = malloc(sizeof(int)+i);
    +     }
    +     CHECK_LEAKS();
    + }	
    + 
    +

    + On an Intel X86 Linux system this produces on the stderr stream: +

    + Leaked composite object at 0x806dff0 (leak_test.c:8, sz=4)
    + 
    + (On most unmentioned operating systems, the output is similar to this. + If the collector had been built on Linux/X86 with -DSAVE_CALL_CHAIN, + the output would be closer to the Solaris example. For this to work, + the program should not be compiled with -fomit_frame_pointer.) +

    + On Irix it reports +

    + Leaked composite object at 0x10040fe0 (leak_test.c:8, sz=4)
    +         Caller at allocation:
    +                 ##PC##= 0x10004910
    + 
    + and on Solaris the error report is +
    + Leaked composite object at 0xef621fc8 (leak_test.c:8, sz=4)
    +         Call chain at allocation:
    +                 args: 4 (0x4), 200656 (0x30FD0)
    +                 ##PC##= 0x14ADC
    +                 args: 1 (0x1), -268436012 (0xEFFFFDD4)
    +                 ##PC##= 0x14A64
    + 
    + In the latter two cases some additional information is given about + how malloc was called when the leaked object was allocated. For + Solaris, the first line specifies the arguments to GC_debug_malloc + (the actual allocation routine), The second the program counter inside + main, the third the arguments to main, and finally the program + counter inside the caller to main (i.e. in the C startup code). +

    + In the Irix case, only the address inside the caller to main is given. +

    + In many cases, a debugger is needed to interpret the additional information. + On systems supporting the "adb" debugger, the callprocs script + can be used to replace program counter values with symbolic names. + As of version 6.1, the collector tries to generate symbolic names for + call stacks if it knows how to do so on the platform. This is true on + Linux/X86, but not on most other platforms. +

    Simplified leak detection under Linux

    + Since version 6.1, it should be possible to run the collector in leak + detection mode on a program a.out under Linux/X86 as follows: +
      +
    1. Ensure that a.out is a single-threaded executable. This doesn't yet work + for multithreaded programs. +
    2. If possible, ensure that the addr2line program is installed in + /usr/bin. (It comes with RedHat Linux.) +
    3. If possible, compile a.out with full debug information. + This will improve the quality of the leak reports. With this approach, it is + no longer necessary to call GC_ routines explicitly, though that can also + improve the quality of the leak reports. +
    4. Build the collector and install it in directory foo as follows: +
        +
      • configure --prefix=foo --enable-full-debug --enable-redirect-malloc + --disable-threads +
      • make +
      • make install +
      +
    5. Set environment variables as follows: +
        +
      • LD_PRELOAD=foo/lib/libgc.so +
      • GC_FIND_LEAK +
      • You may also want to set GC_PRINT_STATS (to confirm that the collector + is running) and/or GC_LOOP_ON_ABORT (to facilitate debugging from another + window if something goes wrong). +
      Simply run a.out as you normally would. Note that if you run anything + else (e.g. your editor) with those environment variables set, + it will also be leak tested. This may or may not be useful and/or + embarrassing. It can generate + mountains of leak reports if the application wasn't designed to avoid leaks, + e.g. because it's always short-lived. +
    + This has not yet been thropughly tested on large applications, but it's known + to do the right thing on at least some small ones. + + diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README gcc-3.4.0/boehm-gc/doc/README *** gcc-3.3.3/boehm-gc/doc/README 2002-02-12 04:37:55.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README 2003-07-28 04:18:22.000000000 +0000 *************** *** 1,7 **** Copyright (c) 1988, 1989 Hans-J. Boehm, Alan J. Demers Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved. Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. ! Copyright (c) 1999-2001 by Hewlett-Packard Company. All rights reserved. The file linux_threads.c is also Copyright (c) 1998 by Fergus Henderson. All rights reserved. --- 1,7 ---- Copyright (c) 1988, 1989 Hans-J. Boehm, Alan J. Demers Copyright (c) 1991-1996 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. The file linux_threads.c is also Copyright (c) 1998 by Fergus Henderson. All rights reserved. *************** Copyright (c) 1998 by Fergus Henderson. *** 9,16 **** The files Makefile.am, and configure.in are Copyright (c) 2001 by Red Hat Inc. All rights reserved. ! The files config.guess and a few others are copyrighted by the Free ! Software Foundation. THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. --- 9,17 ---- The files Makefile.am, and configure.in are Copyright (c) 2001 by Red Hat Inc. All rights reserved. ! Several files supporting GNU-style builds are copyrighted by the Free ! Software Foundation, and carry a different license from that given ! below. THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. *************** are GPL'ed, but with an exception that s *** 27,33 **** collector. (If you are concerned about such things, I recommend you look at the notice in config.guess or ltmain.sh.) ! This is version 6.1alpha3 of a conservative garbage collector for C and C++. You might find a more recent version of this at --- 28,34 ---- collector. (If you are concerned about such things, I recommend you look at the notice in config.guess or ltmain.sh.) ! This is version 6.3alpha1 of a conservative garbage collector for C and C++. You might find a more recent version of this at *************** and several of those are compatible with *** 228,237 **** or equivalent is supplied. Many of these have separate README.system files. ! Dynamic libraries are completely supported only under SunOS (and even that support is not functional on the last Sun 3 release), ! Linux, IRIX 5&6, HP-PA, Win32 (not Win32S) and OSF/1 on DEC AXP machines. ! On other machines we recommend that you do one of the following: 1) Add dynamic library support (and send us the code). 2) Use static versions of the libraries. --- 229,240 ---- or equivalent is supplied. Many of these have separate README.system files. ! Dynamic libraries are completely supported only under SunOS/Solaris, (and even that support is not functional on the last Sun 3 release), ! Linux, FreeBSD, NetBSD, IRIX 5&6, HP/UX, Win32 (not Win32S) and OSF/1 ! on DEC AXP machines plus perhaps a few others listed near the top ! of dyn_load.c. On other machines we recommend that you do one of ! the following: 1) Add dynamic library support (and send us the code). 2) Use static versions of the libraries. *************** On other machines we recommend that you *** 245,250 **** --- 248,255 ---- In all cases we assume that pointer alignment is consistent with that enforced by the standard C compilers. If you use a nonstandard compiler you may have to adjust the alignment parameters defined in gc_priv.h. + Note that this may also be an issue with packed records/structs, if those + enforce less alignment for pointers. A port to a machine that is not byte addressed, or does not use 32 bit or 64 bit addresses will require a major effort. A port to plain MSDOS diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README.arm.cross gcc-3.4.0/boehm-gc/doc/README.arm.cross *** gcc-3.3.3/boehm-gc/doc/README.arm.cross 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README.arm.cross 2003-07-28 03:46:20.000000000 +0000 *************** *** 0 **** --- 1,68 ---- + From: Margaret Fleck + + Here's the key details of what worked for me, in case anyone else needs them. + There may well be better ways to do some of this, but .... + -- Margaret + + + The badge4 has a StrongArm-1110 processor and a StrongArm-1111 coprocessor. + + Assume that the garbage collector distribution is unpacked into /home/arm/gc6.0, + which is visible to both the ARM machine and a linux desktop (e.g. via NFS mounting). + + Assume that you have a file /home/arm/config.site with contents something like the + example attached below. Notice that our local ARM toolchain lives in + /skiff/local. + + Go to /home/arm/gc6.0 directory. Do + CONFIG_SITE=/home/arm/config.site ./configure --target=arm-linux + --prefix=/home/arm/gc6.0 + + On your desktop, do: + make + make install + The main garbage collector library should now be in ../gc6.0/lib/libgc.so. + + To test the garbage collector, first do the following on your desktop + make gctest + ./gctest + Then do the following on the ARM machine + cd .libs + ./lt-gctest + + Do not try to do "make test" (the usual way of running the test + program). This does not work and seems to erase some of the important + files. + + The gctest program claims to have succeeded. Haven't run any further tests + with it, though I'll be doing so in the near future. + + ------------------------------- + # config.site for configure + + # Modified from the one provided by Bradley D. LaRonde + # Edited by Andrej Cedilnik + # Used some of solutions by Tilman Vogel + # Ported for iPAQ Familiar by Oliver Kurth + # Further modified by Margaret Fleck for the badge4 + + HOSTCC=gcc + + # Names of the cross-compilers + CC=/skiff/local/bin/arm-linux-gcc + CXX=/skiff/local/bin/arm-linux-gcc + + # The cross compiler specific options + CFLAGS="-O2 -fno-exceptions" + CXXFLAGS="-O2 -fno-exceptions" + CPPFLAGS="-O2 -fno-exceptions" + LDFLAGS="" + + # Some other programs + AR=/skiff/local/bin/arm-linux-ar + RANLIB=/skiff/local/bin/arm-linux-ranlib + NM=/skiff/local/bin/arm-linux-nm + ac_cv_path_NM=/skiff/local/bin/arm-linux-nm + ac_cv_func_setpgrp_void=yes + x_includes=/skiff/local/arm-linux/include/X11 + x_libraries=/skiff/local/arm-linux/lib/X11 diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README.changes gcc-3.4.0/boehm-gc/doc/README.changes *** gcc-3.3.3/boehm-gc/doc/README.changes 2002-02-12 04:37:55.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README.changes 2003-07-28 04:18:22.000000000 +0000 *************** Since 6.1 alpha2: *** 1469,1476 **** --- 1469,1907 ---- - Caused the Solaris and Irix thread creation primitives to call GC_init_inner(). + Since 6.1alpha3: + - Fixed typo in sparc_mach_dep.S, preventing the 64-bit version from + building. Increased 64-bit heap size limit in test.c slightly, since + a functional SPARC collector seems to slightly exceed the old limits. + (Thanks again to Jeff Sturm.) + - Use NPRGREG in solaris_threads.c, thus printing all registers if things + go wrong. + - Added GC_MARKERS environment variable to allow use of a single marker + thread on an MP without confusing the lock implementation. + - Collect much less aggressively in incremental mode with GC_TIME_UNLIMITED. + 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. + - 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 Ryan Murray.) + - Fixed a formatting error in dbg_mlc.c. Added prototype to GC_abort() + declaration. (Thanks to Michael Smith.) + - Removed "source" argument to GC_find_start(). Eliminate GC_FIND_START(). + - Added win32 recognition code in configure.in. Changed some of the + dllimport/export defines in gc.h. (Thanks to Adam Megacz.) + - GC_malloc_many didn't set hb_last_reclaimed when it called + GC_reclaim_generic. (I'm not sure this matters much, but ...) + - Allocating uncollectable objects with debug information sometimes + allocated objects that were one byte too small, since uncollectable + objects don't have the extra byte added at the end. (Thanks to + 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 + 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. + - Some win32-specific patches, including the introduction of + GC_CreateThread. (Thanks to Adam Megacz.) + - Merged in gcj changes from Anthony Green to support embedded systems. + - Tried to consistently rename preprocessed assembly files with a capital + .S extension. + - Use alpha_mach_dep.S on ALPHA again. It doesn't really matter, but this + makes our distribution consistent with the gcc one, avoiding future merge + problems. + - Move GET_MEM definition into gcconfig.h. Include gcconfig.h slightly + later in gc_priv.h to avoid forward references to ptr_t. + - Add some testing of local allocation to test.c. + - Change definition of INVALID_QTID in specific.h. The -1 value was used + inconsistently, and too likely to collide with a valid stack address. + Some general clean-up of specific.[ch]. Added assertions. (Thanks + to Michael Smith for tracking down an intermittent bug to this + general area. I'm not sure it has been squashed yet, however.) + - On Pthread systems it was not safe to call GC_malloc() between fork() + and exec(). According to the applicable standards, it doesn't appear + to be safe to call malloc() or many other libc functions either, thus + it's not clear this is fixable. Added experimental support for + -DHANDLE_FORK in linux_threads.c which tries to support it. It may + succeed if libc does the right thing. I'm not sure whether it does. + (Thanks to Kenneth Schalk for pointing out this issue.) + - Documented thread local allocation primitives to require an + explicit GC_init call. GC_init_parallel is no longer declared to + be a constructor function, since that isn't portable and often + seems to lead to initialization order problems. + - Changed gc_cpp.cc and gc_cpp.h in one more attempt to make them + compatible with Visual C++ 6. (Thanks to Wink Saville for the + patch.) + - Some more patches for Linux on HP PA-RISC. + - Added include/gc_allocator.h. It implements (hopefully) standard + conforming (as opposed to SGI-style) allocators that allocate + collectable (gc_allocator) or GC-traceable, but not collectable + (traceable_allocator) objects. This borrows heavily from libstc++, + which borrows heavily from the SGI implementation, this part of + which was written by Matt Austern. Changed test_cpp.cc to very + minimally test this. + - On Linux/X86, retry mmap with a different start argument. That should + allow the collector to use more (closer to 3GB) of the address space. + (Thanks to Jeffrey Mark Siskind for tracking this down.) + - Force 64 bit alignment with GCJ support. (Reflects Bryce McKinley's + patch to the gcc tree.) + - Refined the choice of sa_handler vs. sa_sigaction in GC_dirty_init + to accomodate some glibc5 systems. (Thanks to Dan Fandrich for the + patch.) + - Compensated for the fact that current versions of glibc set + __libc_stack_end incorrectly on Linux/IA64 while initialization code + is running. This could cause the collector to miss 16 bytes of + the memory stack if GC_malloc or friends where called before main(). + - Mostly integrated Takis Psarogiannakopoulos' port to DG/UX Inix 86. + This will probably take another iteration to work, since his + patch conflicted with the libtool upgrade. + - Added README.arm.cross containing some information about cross- + compiling to an ARM processor from Margaret Fleck. + + Since 6.1alpha4: + - Added GC_finalizer_mem_freed, and changed some of the code that + decided on heap expansion to look at it. Memory explicitly + deallocated by finalizers essentially needs to be counted as reclaimed + by the GC. Otherwise there are cases in which the heap can grow + unboundedly. (Thanks to Mark Reichert for the test case.) + - Integrated Adam Megacz patches to not scan dynamic libraries if + we are compiling with gcc on win32. Otherwise we need structured + exception handling to deal with asynchronously unmapped root + segments, and gcc doesn't directly support that. + - Integrated Anthony Green's patch to support Wine. + - GC_OPERATOR_NEW_ARRAY was misspelled OPERATOR_NEW_ARRAY in several + places, including gc_cpp.cc. (Thanks to Wink Saville for pointing + this out.) + - Integrated Loren James Rittle's Alpha FreeBSD patches. In + response to Richard Henderson's suggestion, these also + changed the declarations of symbols like _end on many platforms to + that they wouldn't mistakenly be declared as short data symbols. + - Integrated changes from the Debian distribution. (Thanks to Ryan Murray + for pointing these out.) Fix C++ comments in POWERPC port. Add ARM32 + incremental GC support. Get rid of USE_GENERIC_PUSH_REGS for alpha/Linux, + this time for real. Use va_copy to get rid of cord printf problems + (finally). + - Close file descriptor used to count cpus. Thanks to Jeff Sturm for + pointing out the omission. + - Don't just drop gcj free lists in GC_start_reclaim, since that can + eventually cause the marker to see a bogus mark descriptor in the + dropped objects. The usual symptom was a very intermittent segmentation + fault in the marker. This mattered only if one of the GC_gcj_malloc + variants was used. (Thanks to Michael Smith, Jeff Sturm, Bryce + McKinley and Tom Tromey for helping to track this down.) + - Fixed Linux and Solaris/64 SPARC configuration. (Thanks to David Miller, + Jeff Sturm, Tom Tromey, and Christian Joensson.) + - Fixed a typo in strdup definition. (Thanks to Gerard A Allan.) + - Changed Makefile.direct to invoke $(CC) to assemble alpha_mach_dep.S. + This is needed on Linux. I'm not sure whether it's better or worse + on Tru64. + - Changed gc_cpp.h once more to declare operator new and friends only in + a Microsoft environment. This may need further fine tuning. (Thanks to + Johannes Schmidt for pointing out that the older code breaks on gcc3.0.4.) + - Don't ever override strdup if it's already macro defined. (Thanks to + Adnan Ali for pointing out the problem.) + - Changed gc_cpp.h yet again to also overload placement new. Due to the + C++ overloading rules, the other overloaded new operations otherwise hide + placement new, which causes many STL uses to break. (Thanks to Reza + Shahidi for reporting this, and to Matt Austern for proposing a fix.) + - Integrated cygwin pthreads support from Dan Bonachea. + - Turn on DYNAMIC_LOADING for NetBSD. (Thanks to Krister Walfridsson.) + - Changed printing code to print more complete GC times. + - Applied Mark Mitchell's Irix patch to correct some bitrot. + - Clarified which object-printing routines in dbg_mlc.c should hold + the allocation lock. Restructured the code to allow reasonable object + printing with -DREDIRECT_MALLOC. + - Fix the Linux mmap code to always start with 0x1000 as the initial hint. + Minor patches for 64-bit AIX, particularly to STACKBOTTOM. + (Thanks again to Jeffrey Mark Siskind.) + - Renamed "SUSPENDED" flag for Solaris threads support to avoid a conflict + with a system header. (Thanks to Philp Brown.) + - Cause win32_threads.c to handle an out of range stack pointer correctly, + though currently with a warning. (Thanks to Jonathan Clark for + observing that win32 applications may temporarily use the stack + pointer for other purposes, and suggesting a fix. Unfortunately, it's + not clear that there is a complete solution to this problem.) + + Since 6.1alpha5: + - Added GC_MAXIMUM_HEAP_SIZE environment variable. + - Fix configure.in for MIPS/LINUX. (Thanks to H.J. Lu.) + - Double page hash table size for -DLARGE_CONFIG. + - Integrated Bo Thorsen's X86-64 support. + - STACKBOTTOM definition for LINUX/MIPS was partially changed back. + (Thanks to H.J. Lu and Hiroshi Kawashima for resolving this.) + - Replaced all occurrences of LINUX_DATA_START in gcconfig.h with + SEARCH_FOR_DATA_START. It doesn't hurt to falll back to a search. + And __data_start doesn't seem to get defined correctly of the GC + library is loaded with LD_PRELOAD, e.g. for leak detection. + - If the GC_find_leak environment variable is set, do a + atexit(GC_gcollect) to give us at least one chance to detect leaks. + This may report some very benign leaks, but ... + - Addeded REDIRECT_FREE. It's necessary if we want leak detection with + LD_PRELOAD. + - Defer printing of leaked objects, as for smashed objects. + - Fixed process and descriptor leak in GC_print_callers. Try for + line number even if we got function name.) + - Ported parallel GC support and thread local allocation to Alpha. + Not yet well-tested. + - Added GC_DUMP_REGULARLY and added finalization statistics to GC_dump(). + - Fixed Makefile.am to mention alpha_mach_dep.S instead of the defunct + alpha_mach_dep.s. (Thanks to Fergus Henderson.) + - Incorporated a change to new_gc_alloc.h, suggested by Johannes Schmidt, + which should make it work with gcc3.1. (I would still like to encourage + use of gc_allocator.h instead.) + - Use alpha_mach_dep.S only on Linux. (It's not clear that this is + optimal, but it otherwise didn't build on Tru64. Thanks to Fergus + Henderson.) + - Added ifdef to guard free() in os_dep.c. Otherwise we get a + compilation error on Irix. (Thanks to Dai Sato.) + - Added an experimental version of GC_memalign to mallocx.c. This can't + always work, since we don't handle alignment requests in the hblk-level + allocator, and we can't handle arbitrary pointer displacements unless + GC_all_interior_pointers is enabled. But it should work for alignment + requests up to HBLKSIZE. This is not yet documented in the standard + places. + - Finally debugged the OSF1/Tru64 thread support. This needs more testing, + since I needed to add a somewhat unconvincing workaround for signal + delivery issues that I don't yet completely understand. But it does + pass my tests, even in parallel GC mode. Incremental GC support is + disabled if thread support is enabled, due to the signal issues. + - Eliminated name-space-incorrect definition of _cdecl from gc_cpp.h. + - Added GC_debug_malloc_replacement and GC_debug_realloc_replacement + declarations to gc.h. On IA64, this is required for REDIRECT_MALLOC + to work correctly with these. + - Fixed Linux USE_PROC_FOR_LIBRARIES to work with a 64-bit /proc format. + + Since 6.1: + - Guard the test for GC_DUMP_REGULARLY in misc.c with + "#ifndef NO_DEBUGGING". Otherwise it fails to build with NO_DEBUGGING + defined. (Thanks to Manuel Serrano.) + - Message about retrying suspend signals was incorrectly generated even when + flag was not set. + - Cleaned up MACOSX/NEXT root registration code. There was apparently a + separate ifdef case in GC_register_data_segments() for no reason. + - Removed MPROTECT_VDB for MACOSX port, based on one negative report. + - Arrange for gc.h and friends to be correctly installed with GNU-style + "make install". + - Enable the GNU-style build facility include C++ support in the library + with --enable-cplusplus. (Thanks to Thomas Maier for some of the patch.) + - Mark from GC_thread_key in linux_threads.c, in case that's allocated + from the garbage collected heap, as it is with our own thread-specific + storage implementation. (Thanks to Jeff Sturm.) + - Mark all free list header blocks if they are heap allocated. This avoids + some unnecessary tracing. And it remains correct if we clear the + root set. (Thanks to Jeff Sturm for identifying the bug.) + - Improved S390/Linux support. Add S390/Linux 64-bit support. (Thanks + to Ulrich Weigand.) + - Corrected the spelling of GC_{M,C}ALLOC_EXPLICTLY_TYPED to + GC_{M,C}ALLOC_EXPLICITLY_TYPED in gc_typed.h. This is technically + an interface change. Based on the fact that nobody reported this, + I suspect/hope there were no clients. + - Cleaned up gc_typed.h so that (1) it adds an extern "C" declaration + when appropriate, (2) doesn't generate references to undefined internal + macros, and (3) allows easier manual construction of descriptors. + - Close the file descriptor used by GC_print_address_map(). + - Set the "close-on-exec" bit for various file descriptors maintained + for the collector's internal use. + - Added a hack to find memory segments owned by the system allocator + under win32. Based on my tests, this tends to eventually find all + segments, though it may take a while. There appear to be cleaner, + but slower solutions under NT/XP. But they rely on an API that's + unsupported under 9X. + - Changed Linux PowerPC stack finding to LINUX_STACKBOTTOM. (Thanks + to Akira Tagoh for pointing out that HEURISTIC1 doesn't work on + 64-bit kernels.) + - Added GC_set_free_space_divisor to avoid some Windows dll issues. + - Added FIXUP_POINTER, POINTER_SHIFT, POINTER_MASK to allow preprocessing + of candidate pointers for tagging, etc. + - Always lock around GC_notify_full_gc(). Simplified code for + invoking GC_notify_full_gc(). + - Changed the way DATASTART is defined on FreeBSD to be robust against + an unmapped page after etext. (Thanks to Hironori Sakamoto for + tracking down the intermittent failure.) + - Made GC_enable() and GC_disable() official. Deprecated direct update + of GC_dont_gc. Changed GC_gcollect to be a noop when garbage collection + is disabled. + - Call GC_register_dynamic_libraries before stopping the world on Linux, + in order to avoid a potential deadlock due to the dl_iterate_phdr lock. + - Introduced a more general mechanism for platform-dependent code to + decide whether the main data segment should be handled separately + from dynamic libraries, or registered by GC_register_dynamic_libraries. + The latter is more reliable and easier on Linux with dl_iterate_phdr. + + Since 6.2alpha1: + - Fixed the completely broken FreeBSD code in 6.2alpha1. (Thanks to + Hironori Sakamoto for the patch.) + - Changed IRIX reference in dbg_mlc.c to IRIX5. (Thanks to Marcus Herbert.) + - Attempted to work around the problems with .S filenames and the SGI + compiler. (Reported by several people. Untested.) + - Worked around an HP/UX make issue with the GNU-style build process. + - Fixed the --enable-cplusplus build machinery to allow builds without + a C++ compiler. (That was always the intent ...) + - Changed the debugging allocation macros to explicitly pass the return + address for Linux and XXXBSD on hardware for which we can't get stack + traces. Use __builtin_return_address(0) to generate it when possible. + Some of the configuration work was cleaned up (good) and moved to gc.h + (bad, but necessary). This should make leak detection more useful + on a number of platforms. (Thanks to Fabian Thylman for the suggestion.) + - Fixed compilation problems in dbg_mlc.c with GC_ADD_CALLER. + - Bumped revision number for dynamic library. + + Since 6.2alpha2: + - Don't include execinfo.h in os_dep.c when it's not needed, and may not exist. + + Since 6.2alpha3: + - Use LINUX_STACKBOTTOM for >= glibc2.2 on Linux/MIPS. (See Debian bug + # 177204) + - Integrated Jeff Sturm and Jesse Rosenstock's MACOSX threads patches. + - Integrated Grzegorz Jakacki's substantial GNU build patch. "Make dist" + should now work for the GNU build process. Documentation files + are installed under share/gc. + - Tweaked gc_cpp.h to again support the Borland compiler. (Thanks to + Rene Girard for pointing out the problems.) + - Updated BCC_MAKEFILE (thanks to Rene Girard). + - Added GC_ASSERT check for minimum thread stack size. + - Added --enable-gc-assertions. + - Added some web documentation to the distribution. Updated it in the + process. + - Separate gc_conf_macros.h from gc.h. + - Added generic GC_THREADS client-defined macro to set the appropriate + GC_XXX_THREADS internal macro. (gc_config_macros.h.) + - Add debugging versions of _ignore_off_page allocation primitves. + - Moved declarations of GC_make_closure and GC_debug_invoke_finalizer + from gc.h to gc_priv.h. + - Reset GC_fail_count even if only a small allocation succeeds. + - Integrated Brian Alliet's patch for dynamic library support on Darwin. + - gc_cpp.h's gc_cleanup destructor called GC_REGISTER_FINALIZER_IGNORE_SELF + when it should have called the lower case version, since it was + explicitly computing a base pointer. + + Since 6.2alpha4: + - GC_invoke_finalizers could, under rare conditions, set + GC_finalizer_mem_freed to an essentially random value. This could + possibly cause unbounded heap growth for long-running applications + under some conditions. (The bug was introduced in 6.1alpha5, and + is not in gcc3.3. Thanks to Ben Hutchings for finding it.) + - Attempted to sanitize the various DLL macros. GC_USE_DLL disappeared. + GC_DLL is used instead. All internal tests are now on GC_DLL. + README.macros is now more precise about the intended meaning. + - Include DllMain in the multithreaded win32 version only if the + collector is actually built as a dll. (Thanks to Mohan Embar for + a version of the patch.) + - Hide the cygwin threadAttach/Detach functions. They were violating our + namespace rules. + - Fixed an assertion in GC_check_heap_proc. Added GC_STATIC_ASSERT. + (Thanks again to Ben Hutchings.) + - Removed some obsolete definitions for Linux/PowerPC in gcconfig.h. + - CORD_cat was not rebalancing unbalanced trees in some cases, violating + a CORD invariant. Also tweaked the rebalancing rule for + CORD_cat_char_star. (Thanks to Alexandr Petrosian for the bug report + and patch.) + - Added hand-coded structured exception handling support to mark.c. + 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. + - 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 + cleaned up tests for GC_PRIVATE_H in gcconfig.h a bit. + - The GC_LOOP_ON_ABORT environment variable interfered with incremental + collection, since the write fault handler was erroneously overridden. + Handlers are now set up in the correct order. + - It used to be possible to call GC_mark_thread_local_free_lists() while + the world was not stopped during an incremental GC. This was not safe. + Fortunately, it was also unnecessary. Added GC_world_stopped flag + to avoid it. (This caused occasional crashes in GC_set_fl_marks + with thread local allocation and incremental GC. This probably happened + primarily on old, slow multiprocessors.) + - Allowed overriding of MAX_THREADS in win32_threads.c from the build + command line. (Patch from Yannis Bres.) + - Taught the IA64/linux code to determine the register backing store base from + /proc/self/maps after checking the __libc symbol, but before guessing. + (__libc symbols are on the endangered list, and the guess is likely to not + always be right for 2.6 kernels.) Restructured the code to read and parse + /proc/self/maps so it only exists in one place (all platforms). + - The -DUSE_PROC_FOR_LIBRARIES code was broken on Linux. It claimed that it + also registered the main data segment, but didn't actually do so. (I don't + think anyone actually uses this configuration, but ...) + - Made another attempt to get --enablecplusplus to do the right thing. + Since there are unavoidable problems with C programs linking against a + dynamic library that includes C++ code, I separated out the c++ code into + libgccpp. + + Since 6.2alpha5: + - There was extra underscore in the name of GC_save_registers_in_stack + for NetBSD/SPARC. (Thanks to Jaap Boender for the patch.) + - Integrated Brian Alliet's patch for Darwin. This restructured the + linuxthreads/pthreads support to separate generic pthreads support + from more the system-dependent thread-stopping code. I believe this + should make it easier to eliminate the code duplication between + pthreads platforms in the future. The patch included some other + code cleanups. + - Integrated Dan Bonachea's patch to support AIX threads. This required + substantial manual integration, mostly due to conflicts with other + recent threads changes. It may take another iteration to + get it to work. + - Removed HPUX/PA-RISC support from aix_irix_threads.c. It wasn't used + anyway and it cluttered up the code. And anything we can do to migrate + towards generic pthreads support is a good thing. + - Added a more explicit test for tracing of function arguments to test.c. + (Thanks to Dan Grayson.) + - Added Akira Tagoh's PowerPC64 patch. + - Fixed some bit rot in the Cygwin port. (Thanks to Dan Bonachea for + pointing it out.) Gc.h now includes just windows.h, not winbase.h. + - Declared GC_save_regs_in_stack() in gc_priv.h. Remove other declarations. + - Changed --enable-cplusplus to use automake consitionals. The old way + confused libtool. "Make install" didn't work correctly for the old version. + Previously --enable-cplusplus was broken on cygwin. + - Changed the C version of GC_push_regs to fail at compile time if it is + generated with an empty body. This seems to have been the cause of one + or two subtle failures on unusual platforms. Those failures should + now occur at build time and be easily fixable. + + Since 6.2alpha6: + - Integrated a second round of Irix/AIX patches from Dan Bonachea. + Renamed mips_sgi_mach_dep.S back to mips_sgi_mach_dep.s, since it requires + the Irix assembler to do the C preprocessing; gcc -E doesn't work. + - Fixed Makefile.direct for DARWIN. (Thanks to Manuel Serrano.) + - There was a race between GC_pthread_detach and thread exit that could + result in a thread structure being deallocated by GC_pthread_detach + eventhough it was still needed by the thread exit code. (Thanks to + Dick Porter for the small test case that allowed this to be debugged.) + - Fixed version parsing for non-alpha versions in acinclude.m4 and + version checking in version.h. + + Since 6.2: + - Integrated some NetBSD patches forwarded to me by Marc Recht. These + were already in the NetBSD package. + - GC_pthread_create waited for the semaphore even if pthread_create failed. + Thanks to Dick Porter for the pthread_support.c patch. Applied the + analogous fix for aix_irix_threads.c. + - Added Rainer Orth's Tru64 fixes. + - The check for exceeding the thread table size in win32 threadDetach + was incorrect. (Thanks to Alexandr Petrosian for the patch.) + - Applied Andrew Begel's patch to correct some reentrancy issues + with dynamic loading on Darwin. + - GC_CreateThread() was neglecting to duplicate the thread handle in + the table. (Thanks to Tum Nguyen for the patch.) + - Pass +ESdbgasm only on PA-RISC machines with vendor compiler. + (Thanks to Roger Sayle for the patch.) + - Applied more AIX threads patches from Scott Ananian. To do: + - A dynamic libgc.so references dlopen unconditionally, but doesn't link + against libdl. + - GC_proc_fd for Solaris is not correctly updated in response to a + fork() call. Thus incremental collection in the child won't work + correctly. (Thanks to Ben Cottrell for pointing this out.) + - --enable-redirect-malloc is mostly untested and known not to work + on some platforms. - There seem to be outstanding issues on Solaris/X86, possibly with finding the data segment starting address. Information/patches would be appreciated. *************** To do: *** 1488,1494 **** - Incremental collector should handle large objects better. Currently, it looks like the whole object is treated as dirty if any part of it is. ! - Cord/cordprnt.c doesn't build on a few platforms (notably PowerPC), since ! we make some unwarranted assumptions about how varargs are handled. This ! currently makes the cord-aware versions of printf unusable on some platforms. ! Fixing this is unfortunately not trivial. --- 1919,1922 ---- - Incremental collector should handle large objects better. Currently, it looks like the whole object is treated as dirty if any part of it is. ! diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README.darwin gcc-3.4.0/boehm-gc/doc/README.darwin *** gcc-3.3.3/boehm-gc/doc/README.darwin 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README.darwin 2003-07-28 03:46:20.000000000 +0000 *************** *** 0 **** --- 1,106 ---- + Darwin/MacOSX Support - July 22, 2003 + ==================================== + + Important Usage Notes + ===================== + + GC_init() MUST be called before calling any other GC functions. This + is necessary to properly register segments in dynamic libraries. This + call is required even if you code does not use dynamic libraries as the + dyld code handles registering all data segments. + + When your use of the garbage collector is confined to dylibs and you + 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 + void my_library_init() { GC_init(); } + + Compile this code into a my_library_init.o, and link it into your + dylib. When you link the dylib, pass the -init argument with + _my_library_init (e.g. gcc -dynamiclib -o my_library.dylib a.o b.o c.o + my_library_init.o -init _my_library_init). This causes + my_library_init() to be called before any static initializers, and + will initialize the garbage collector properly. + + Note: It doesn't hurt to call GC_init() more than once, so it's best, + if you have an application or set of libraries that all use the + garbage collector, to create an initialization routine for each of + them that calls GC_init(). Better safe than sorry. + + The incremental collector is still a bit flaky on darwin. It seems to + work reliably with workarounds for a few possible bugs in place however + these workaround may not work correctly in all cases. There may also + be additional problems that I have not found. + + Implementation Information + ========================== + Darwin/MacOSX support is nearly complete. Thread support is reliable on + Darwin 6.x (MacOSX 10.2) and there have been reports of success on older + Darwin versions (MacOSX 10.1). Shared library support had also been + added and the gc can be run from a shared library. There is currently only + support for Darwin/PPC although adding x86 support should be trivial. + + Thread support is implemented in terms of mach thread_suspend and + thread_resume calls. These provide a very clean interface to thread + suspension. This implementation doesn't rely on pthread_kill so the + code works on Darwin < 6.0 (MacOSX 10.1). All the code to stop the + world is located in darwin_stop_world.c. + + The original incremental collector support unfortunatelly no longer works + on recent Darwin versions. It also relied on some undocumented kernel + structures. Mach, however, does have a very clean interface to exception + handing. The current implementation uses Mach's exception handling. + + Much thanks goes to Andrew Stone, Dietmar Planitzer, Andrew Begel, + Jeff Sturm, and Jesse Rosenstock for all their work on the + Darwin/OS X port. + + -Brian Alliet + brian@brianweb.net + + + Older Information (Most of this no longer applies to the current code) + ====================================================================== + + While the GC should work on MacOS X Server, MacOS X and Darwin, I only tested + it on MacOS X Server. + I've added a PPC assembly version of GC_push_regs(), thus the setjmp() hack is + no longer necessary. Incremental collection is supported via mprotect/signal. + The current solution isn't really optimal because the signal handler must decode + the faulting PPC machine instruction in order to find the correct heap address. + Further, it must poke around in the register state which the kernel saved away + in some obscure register state structure before it calls the signal handler - + needless to say the layout of this structure is no where documented. + Threads and dynamic libraries are not yet supported (adding dynamic library + support via the low-level dyld API shouldn't be that hard). + + The original MacOS X port was brought to you by Andrew Stone. + + + June, 1 2000 + + Dietmar Planitzer + dave.pl@ping.at + + Note from Andrew Begel: + + One more fix to enable gc.a to link successfully into a shared library for + MacOS X. You have to add -fno-common to the CFLAGS in the Makefile. MacOSX + disallows common symbols in anything that eventually finds its way into a + shared library. (I don't completely understand why, but -fno-common seems to + work and doesn't mess up the garbage collector's functionality). + + Feb 26, 2003 + + Jeff Sturm and Jesse Rosenstock provided a patch that adds thread support. + GC_MACOSX_THREADS should be defined in the build and in clients. Real + dynamic library support is still missing, i.e. dynamic library data segments + are still not scanned. Code that stores pointers to the garbage collected + heap in statically allocated variables should not reside in a dynamic + library. This still doesn't appear to be 100% reliable. + + Mar 10, 2003 + Brian Alliet contributed dynamic library support for MacOSX. It could also + use more testing. diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README.DGUX386 gcc-3.4.0/boehm-gc/doc/README.DGUX386 *** gcc-3.3.3/boehm-gc/doc/README.DGUX386 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README.DGUX386 2003-07-28 03:46:20.000000000 +0000 *************** *** 0 **** --- 1,215 ---- + Garbage Collector (parallel iversion) for ix86 DG/UX Release R4.20MU07 + + + *READ* the file README.QUICK. + + You need the GCC-3.0.3 rev (DG/UX) compiler to build this tree. + 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. + To build the garbage collector do: + + ./configure --enable-parallel-mark + make + make gctest + + Before you run "gctest" you need to set your LD_LIBRARY_PATH + correctly so that "gctest" can find the shared library libgc. + Alternatively you can do a configuration + + ./configure --enable-parallel-mark --disable-shared + + to build only the static version of libgc. + + To enable debugging messages please do: + 1) Add the "--enable-full-debug" flag during configuration. + 2) Edit the file linux-threads.c and uncommnect the line: + + /* #define DEBUG_THREADS 1 */ to ---> + + #define DEBUG_THREADS 1 + + Then give "make" as usual. + + In a machine with 4 CPUs (my own machine) the option parallel + mark (aka --enable-parallel-mark) makes a BIG difference. + + Takis Psarogiannakopoulos + University of Cambridge + Centre for Mathematical Sciences + Department of Pure Mathematics + Wilberforce Road + Cambridge CB3 0WB ,UK , + January 2002 + + + Note (HB): + The integration of this patch is currently not complete. + The following patches against 6.1alpha3 where hard to move + to alpha4, and are not integrated. There may also be minor + problems with stylistic corrections made by me. + + + --- ltconfig.ORIG Mon Jan 28 20:22:18 2002 + +++ ltconfig Mon Jan 28 20:44:00 2002 + @@ -689,6 +689,11 @@ + pic_flag=-Kconform_pic + fi + ;; + + dgux*) + + pic_flag='-fPIC' + + link_static='-Bstatic' + + wl='-Wl,' + + ;; + *) + pic_flag='-fPIC' + ;; + @@ -718,6 +723,12 @@ + # We can build DLLs from non-PIC. + ;; + + + dgux*) + + pic_flag='-KPIC' + + link_static='-Bstatic' + + wl='-Wl,' + + ;; + + + osf3* | osf4* | osf5*) + # All OSF/1 code is PIC. + wl='-Wl,' + @@ -1154,6 +1165,22 @@ + fi + ;; + + + dgux*) + + ld_shlibs=yes + + # For both C/C++ ommit the deplibs. This is because we relying on the fact + + # that compilation of execitables will put them in correct order + + # in any case and sometimes are wrong when listed as deplibs (or missing some deplibs) + + # However when GNU ld and --whole-archive needs to be used we have the problem + + # that if the -fPIC *_s.a archive is linked through deplibs list we ommiting crucial + + # .lo/.o files from the created shared lib. This I think is not the case here. + + archive_cmds='$CC -shared -h $soname -o $lib $libobjs $linkopts' + + thread_safe_flag_spec='-pthread' + + wlarc= + + hardcode_libdir_flag_spec='-L$libdir' + + hardcode_shlibpath_var=no + + ac_cv_archive_cmds_needs_lc=no + + ;; + + + cygwin* | mingw*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + @@ -1497,7 +1524,7 @@ + ;; + + dgux*) + - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + + archive_cmds='$CC -shared -h $soname -o $lib $libobjs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + @@ -2092,12 +2119,17 @@ + ;; + + dgux*) + - version_type=linux + + version_type=dgux + need_lib_prefix=no + need_version=no + - library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + - soname_spec='${libname}${release}.so$major' + + library_names_spec='$libname.so$versuffix' + + soname_spec='$libname.so$versuffix' + shlibpath_var=LD_LIBRARY_PATH + + thread_safe_flag_spec='-pthread' + + wlarc= + + hardcode_libdir_flag_spec='-L$libdir' + + hardcode_shlibpath_var=no + + ac_cv_archive_cmds_needs_lc=no + ;; + + sysv4*MP*) + + + --- ltmain.sh.ORIG Mon Jan 28 20:31:18 2002 + +++ ltmain.sh Tue Jan 29 00:11:29 2002 + @@ -1072,11 +1072,38 @@ + esac + ;; + + + -thread*) + + # DG/UX GCC 2.95.x, 3.x.x rev (DG/UX) links -lthread + + # with the switch -threads + + if test "$arg" = "-threads"; then + + case "$host" in + + i[3456]86-*-dgux*) + + deplibs="$deplibs $arg" + + continue + + ;; + + esac + + fi + + ;; + + + + -pthread*) + + # DG/UX GCC 2.95.x, 3.x.x rev (DG/UX) links -lthread + + # with the switch -pthread + + if test "$arg" = "-pthread"; then + + case "$host" in + + i[3456]86-*-dgux*) + + deplibs="$deplibs $arg" + + continue + + ;; + + esac + + fi + + ;; + + + -l*) + if test "$arg" = "-lc"; then + case "$host" in + - *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) + + *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos* | i[3456]86-*-dgux*) + # These systems don't actually have c library (as such) + + # It is wrong in DG/UX to add -lc when creating shared/dynamic objs/libs + continue + ;; + esac + @@ -1248,6 +1275,12 @@ + temp_deplibs= + for deplib in $dependency_libs; do + case "$deplib" in + + -thread*) + + temp_deplibs="$temp_deplibs $deplib" + + ;; + + -pthread) + + temp_deplibs="$temp_deplibs $deplib" + + ;; + -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + case " $rpath $xrpath " in + *" $temp_xrpath "*) ;; + @@ -1709,6 +1742,13 @@ + done + ;; + + + dgux) + + # Leave mostly blank for DG/UX + + major= + + versuffix=".$current.$revision"; + + verstring= + + ;; + + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + @@ -1792,8 +1832,9 @@ + + dependency_libs="$deplibs" + case "$host" in + - *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) + + *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos* | i[3456]86-*-dgux*) + # these systems don't actually have a c library (as such)! + + # It is wrong in DG/UX to add -lc when creating shared/dynamic objs/libs + ;; + *) + # Add libc to deplibs on all other systems. diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README.environment gcc-3.4.0/boehm-gc/doc/README.environment *** gcc-3.3.3/boehm-gc/doc/README.environment 2002-04-09 00:39:16.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README.environment 2003-07-28 04:18:22.000000000 +0000 *************** platforms. *** 5,10 **** --- 5,12 ---- GC_INITIAL_HEAP_SIZE= - Initial heap size in bytes. May speed up process start-up. + GC_MAXIMUM_HEAP_SIZE= - Maximum collected heap size. + GC_LOOP_ON_ABORT - Causes the collector abort routine to enter a tight loop. This may make it easier to debug, such a process, especially for multithreaded platforms that don't produce usable core *************** GC_PRINT_STATS - Turn on as much logging *** 19,24 **** --- 21,31 ---- by setting GC_quiet. On by default if the collector was built without -DSILENT. + GC_DUMP_REGULARLY - Generate a GC debugging dump GC_dump() on startup + and during every collection. Very verbose. Useful + if you have a bug to report, but please include only the + last complete dump. + GC_PRINT_ADDRESS_MAP - Linux only. Dump /proc/self/maps, i.e. various address maps for the process, to stderr on every GC. Useful for mapping root addresses to source for deciphering leak *************** GC_PRINT_ADDRESS_MAP - Linux only. Dump *** 27,33 **** GC_NPROCS= - Linux w/threads only. Explicitly sets the number of processors that the GC should expect to use. Note that setting this to 1 when multiple processors are available will preserve ! correctness, but may lead to really horrible performance. GC_NO_BLACKLIST_WARNING - Prevents the collector from issuing warnings about allocations of very large blocks. --- 34,47 ---- GC_NPROCS= - Linux w/threads only. Explicitly sets the number of processors that the GC should expect to use. Note that setting this to 1 when multiple processors are available will preserve ! correctness, but may lead to really horrible performance, ! since the lock implementation will immediately yield without ! first spinning. ! ! GC_MARKERS= - Linux w/threads and parallel marker only. Set the number ! of marker threads. This is normaly set to the number of ! processors. It is safer to adjust GC_MARKERS than GC_NPROCS, ! since GC_MARKERS has no impact on the lock implementation. GC_NO_BLACKLIST_WARNING - Prevents the collector from issuing warnings about allocations of very large blocks. *************** GC_PRINT_BACK_HEIGHT - Print max length *** 62,67 **** --- 76,95 ---- of Conservative Garbage Collectors", POPL 2001, or http://lib.hpl.hp.com/techpubs/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 + 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 + some versions of Tru64. Since we've previously seen + similar issues on some other operating systems, it + was turned into a runtime flag to enable last-minute + work-arounds. + + The following turn on runtime flags that are also program settable. Checked + only during initialization. We expect that they will usually be set through + other means, but this may help with debugging and testing: + GC_ENABLE_INCREMENTAL - Turn on incremental collection at startup. Note that, depending on platform and collector configuration, this may involve write protecting pieces of the heap to *************** GC_ENABLE_INCREMENTAL - Turn on incremen *** 71,92 **** Use with caution. GC_PAUSE_TIME_TARGET - Set the desired garbage collector pause time in msecs. ! This only has an effect if incremental collection is enabled. ! If a collection requires appreciably more time than this, ! the client will be restarted, and the collector will need ! to do additional work to compensate. The special value ! "999999" indicates that pause time is unlimited, and the ! incremental collector will behave completely like a ! simple generational collector. If the collector is ! configured for parallel marking, and run on a multiprocessor, ! incremental collection should only be used with unlimited ! pause time. ! ! The following turn on runtime flags that are also program settable. Checked ! only during initialization. We expect that they will usually be set through ! other means, but this may help with debugging and testing: ! GC_FIND_LEAK - Turns on GC_find_leak and thus leak detection. GC_ALL_INTERIOR_POINTERS - Turns on GC_all_interior_pointers and thus interior pointer recognition. --- 99,118 ---- Use with caution. GC_PAUSE_TIME_TARGET - Set the desired garbage collector pause time in msecs. ! This only has an effect if incremental collection is ! enabled. If a collection requires appreciably more time ! than this, the client will be restarted, and the collector ! will need to do additional work to compensate. The ! special value "999999" indicates that pause time is ! unlimited, and the incremental collector will behave ! completely like a simple generational collector. If ! the collector is configured for parallel marking, and ! run on a multiprocessor, incremental collection should ! only be used with unlimited pause time. ! GC_FIND_LEAK - Turns on GC_find_leak and thus leak detection. Forces a ! collection at program termination to detect leaks that would ! otherwise occur after the last GC. GC_ALL_INTERIOR_POINTERS - Turns on GC_all_interior_pointers and thus interior pointer recognition. diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README.ews4800 gcc-3.4.0/boehm-gc/doc/README.ews4800 *** gcc-3.3.3/boehm-gc/doc/README.ews4800 2002-01-31 02:48:54.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README.ews4800 2003-07-28 04:18:22.000000000 +0000 *************** GC on EWS4800 *** 73,75 **** --- 73,81 ---- -- 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 + understood. (HB, paraphrasing message from Hironori SAKAMOTO.) + diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README.linux gcc-3.4.0/boehm-gc/doc/README.linux *** gcc-3.3.3/boehm-gc/doc/README.linux 2001-08-17 18:30:49.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README.linux 2003-07-28 04:18:22.000000000 +0000 *************** *** 1,21 **** See README.alpha for Linux on DEC AXP info. ! This file applies mostly to Linux/Intel IA32. Ports to Linux on an M68K ! and PowerPC are also integrated. They should behave similarly, except that ! the PowerPC port lacks incremental GC support, and it is unknown to what ! extent the Linux threads code is functional. See below for M68K specific ! notes. ! Incremental GC is supported on Intel IA32 and M68K. Dynamic libraries are supported on an ELF system. A static executable should be linked with the gcc option "-Wl,-defsym,_DYNAMIC=0". ! The collector appears to work with Linux threads. We have seen ! intermittent hangs in sem_wait. So far we have been unable to reproduce ! these unless the process was being debugged or traced. Thus it's ! possible that the only real issue is that the debugger loses ! signals on rare occasions. The garbage collector uses SIGPWR and SIGXCPU if it is used with Linux threads. These should not be touched by the client program. --- 1,18 ---- See README.alpha for Linux on DEC AXP info. ! This file applies mostly to Linux/Intel IA32. Ports to Linux on an M68K, IA64, ! SPARC, MIPS, Alpha and PowerPC are also integrated. They should behave ! similarly, except that the PowerPC port lacks incremental GC support, and ! it is unknown to what extent the Linux threads code is functional. ! 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". ! The collector appears to work reliably with Linux threads, but beware ! of older versions of glibc and gdb. The garbage collector uses SIGPWR and SIGXCPU if it is used with Linux threads. These should not be touched by the client program. diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README.MacOSX gcc-3.4.0/boehm-gc/doc/README.MacOSX *** gcc-3.3.3/boehm-gc/doc/README.MacOSX 2001-08-18 01:04:43.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README.MacOSX 2003-07-28 04:18:22.000000000 +0000 *************** *** 1,27 **** ! While the GC should work on MacOS X Server, MacOS X and Darwin, I only tested ! it on MacOS X Server. ! I've added a PPC assembly version of GC_push_regs(), thus the setjmp() hack is ! no longer necessary. Incremental collection is supported via mprotect/signal. ! The current solution isn't really optimal because the signal handler must decode ! the faulting PPC machine instruction in order to find the correct heap address. ! Further, it must poke around in the register state which the kernel saved away ! in some obscure register state structure before it calls the signal handler - ! needless to say the layout of this structure is no where documented. ! Threads and dynamic libraries are not yet supported (adding dynamic library ! support via the low-level dyld API shouldn't be that hard). ! ! The original MacOS X port was brought to you by Andrew Stone. ! ! ! June, 1 2000 ! ! Dietmar Planitzer ! dave.pl@ping.at ! ! Note from Andrew Begel: ! ! One more fix to enable gc.a to link successfully into a shared library for ! MacOS X. You have to add -fno-common to the CFLAGS in the Makefile. MacOSX ! disallows common symbols in anything that eventually finds its way into a ! shared library. (I don't completely understand why, but -fno-common seems to ! work and doesn't mess up the garbage collector's functionality). --- 1 ---- ! See README.darwin for the latest Darwin/MacOSX information. diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README.macros gcc-3.4.0/boehm-gc/doc/README.macros *** gcc-3.3.3/boehm-gc/doc/README.macros 2001-08-17 18:39:18.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README.macros 2003-07-28 04:18:22.000000000 +0000 *************** _DLL Defined by Visual C++ if dynamic l *** 51,57 **** __declspec(dllexport) needs to be added to declarations to support the case in which the collector is in a dll. ! GC_DLL User-settable macro that forces the effect of _DLL. GC_NOT_DLL User-settable macro that overrides _DLL, e.g. if dynamic libraries are used, but the collector is in a static library. --- 51,68 ---- __declspec(dllexport) needs to be added to declarations to support the case in which the collector is in a dll. ! GC_DLL User-settable macro that forces the effect of _DLL. Set ! by gc.h if _DLL is defined and GC_NOT_DLL is undefined. ! This is the macro that is tested internally to determine ! whether the GC is in its own dynamic library. May need ! to be set by clients before including gc.h. Note that ! inside the GC implementation it indicates that the ! collector is in its own dynamic library, should export ! its symbols, etc. But in clients it indicates that the ! GC resides in a different DLL, its entry points should ! be referenced accordingly, and precautions may need to ! be taken to properly deal with statically allocated ! variables in the main program. Used only for MS Windows. GC_NOT_DLL User-settable macro that overrides _DLL, e.g. if dynamic libraries are used, but the collector is in a static library. diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/README.win32 gcc-3.4.0/boehm-gc/doc/README.win32 *** gcc-3.3.3/boehm-gc/doc/README.win32 2002-02-12 04:37:55.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/README.win32 2003-07-28 04:18:22.000000000 +0000 *************** registrations are ignored, but not terri *** 21,26 **** --- 21,33 ---- pointers. And the VirtualQuery call has different semantics under the two systems, and under different versions of win32s.) + Win32 applications compiled with some flavor of gcc currently behave + like win32s applications, in that dynamic library data segments are + not scanned. (Gcc does not directly support Microsoft's "structured + exception handling". It turns out that use of this feature is + unavoidable if you scan arbitrary memory segments obtained from + VirtualQuery.) + The collector test program "gctest" is linked as a GUI application, but does not open any windows. Its output appears in the file "gc.log". It may be started from the file manager. The hour glass *************** This appears to cause problems under Win *** 50,62 **** not Windows 95/98) if the memory is later passed to CreateDIBitmap. To work around this problem, build the collector with -DUSE_GLOBAL_ALLOC. This is currently incompatible with -DUSE_MUNMAP. (Thanks to Jonathan ! Clark for tracking this down.) 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. Clients may need to define GC_NOT_DLL before including gc.h, if the collector was built as a static library (as it normally is in the absence of thread support). --- 57,76 ---- not Windows 95/98) if the memory is later passed to CreateDIBitmap. To work around this problem, build the collector with -DUSE_GLOBAL_ALLOC. This is currently incompatible with -DUSE_MUNMAP. (Thanks to Jonathan ! Clark for tracking this down. There's some chance this may be fixed ! in 6.1alpha4, since we now separate heap sections with an unused page.) 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. + If you would prefer a VC++.NET project file, ask boehm@acm.org. One has + been contributed, but it seems to contain some absolute paths etc., so + it can presumably only be a starting point, and is not in the standard + distribution. It is unclear (to me, Hans Boehm) whether it is feasible to + change that. + Clients may need to define GC_NOT_DLL before including gc.h, if the collector was built as a static library (as it normally is in the absence of thread support). *************** absence of thread support). *** 64,70 **** For GNU-win32, use the regular makefile, possibly after uncommenting the line "include Makefile.DLLs". The latter should be necessary only if you want to package the collector as a DLL. The GNU-win32 port is ! believed to work only for b18, not b19, probably dues to linker changes in b19. This is probably fixable with a different definition of DATASTART and DATAEND in gcconfig.h. --- 78,84 ---- For GNU-win32, use the regular makefile, possibly after uncommenting the line "include Makefile.DLLs". The latter should be necessary only if you want to package the collector as a DLL. The GNU-win32 port is ! believed to work only for b18, not b19, probably due to linker changes in b19. This is probably fixable with a different definition of DATASTART and DATAEND in gcconfig.h. *************** To compile the collector and testing pro *** 147,153 **** All programs using gc should be compiled with 4-byte alignment. For further explanations on this see comments about Borland. ! If gc compiled as dll, the macro ``GC_DLL'' should be defined before including "gc.h" (for example, with -DGC_DLL compiler option). It's important, otherwise resulting programs will not run. --- 161,167 ---- All programs using gc should be compiled with 4-byte alignment. For further explanations on this see comments about Borland. ! If the gc is compiled as dll, the macro ``GC_DLL'' should be defined before including "gc.h" (for example, with -DGC_DLL compiler option). It's important, otherwise resulting programs will not run. diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/scale.html gcc-3.4.0/boehm-gc/doc/scale.html *** gcc-3.3.3/boehm-gc/doc/scale.html 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/scale.html 2003-07-28 03:46:20.000000000 +0000 *************** *** 0 **** --- 1,210 ---- + + + Garbage collector scalability + + +

    Garbage collector scalability

    + In its default configuration, the Boehm-Demers-Weiser garbage collector + is not thread-safe. It can be made thread-safe for a number of environments + by building the collector with the appropriate + -DXXX-THREADS compilation + flag. This has primarily two effects: +
      +
    1. It causes the garbage collector to stop all other threads when + it needs to see a consistent memory state. +
    2. It causes the collector to acquire a lock around essentially all + allocation and garbage collection activity. +
    + Since a single lock is used for all allocation-related activity, only one + thread can be allocating or collecting at one point. This inherently + limits performance of multi-threaded applications on multiprocessors. +

    + On most platforms, the allocator/collector lock is implemented as a + spin lock with exponential back-off. Longer wait times are implemented + by yielding and/or sleeping. If a collection is in progress, the pure + spinning stage is skipped. This has the advantage that uncontested and + thus most uniprocessor lock acquisitions are very cheap. It has the + disadvantage that the application may sleep for small periods of time + even when there is work to be done. And threads may be unnecessarily + woken up for short periods. Nonetheless, this scheme empirically + outperforms native queue-based mutual exclusion implementations in most + cases, sometimes drastically so. +

    Options for enhanced scalability

    + Version 6.0 of the collector adds two facilities to enhance collector + scalability on multiprocessors. As of 6.0alpha1, these are supported + only under Linux on X86 and IA64 processors, though ports to other + otherwise supported Pthreads platforms should be straightforward. + They are intended to be used together. +
      +
    • + Building the collector with -DPARALLEL_MARK allows the collector to + run the mark phase in parallel in multiple threads, and thus on multiple + processors. The mark phase typically consumes the large majority of the + collection time. Thus this largely parallelizes the garbage collector + itself, though not the allocation process. Currently the marking is + performed by the thread that triggered the collection, together with + N-1 dedicated + threads, where N is the number of processors detected by the collector. + The dedicated threads are created once at initialization time. +

      + A second effect of this flag is to switch to a more concurrent + implementation of GC_malloc_many, so that free lists can be + built, and memory can be cleared, by more than one thread concurrently. +

    • + Building the collector with -DTHREAD_LOCAL_ALLOC adds support for thread + local allocation. It does not, by itself, cause thread local allocation + to be used. It simply allows the use of the interface in + gc_local_alloc.h. +

      + Memory returned from thread-local allocators is completely interchangeable + with that returned by the standard allocators. It may be used by other + threads. The only difference is that, if the thread allocates enough + memory of a certain kind, it will build a thread-local free list for + objects of that kind, and allocate from that. This greatly reduces + 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. + 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 is 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 + Endo, Taura, and Yonezawa at the University of Tokyo. + However, the data structures and implementation are different, + and represent a smaller change to the original collector source, + probably at the expense of extreme scalability. Some of + the refinements they suggest, e.g. splitting large + objects, were also incorporated into out approach. +

    + The global mark stack is transformed into a global work queue. + Unlike the usual case, it never shrinks during a mark phase. + The mark threads remove objects from the queue by copying them to a + local mark stack and changing the global descriptor to zero, indicating + that there is no more work to be done for this entry. + This removal + is done with no synchronization. Thus it is possible for more than + one worker to remove the same entry, resulting in some work duplication. +

    + The global work queue grows only if a marker thread decides to + return some of its local mark stack to the global one. This + is done if the global queue appears to be running low, or if + the local stack is in danger of overflowing. It does require + synchronization, but should be relatively rare. +

    + The sequential marking code is reused to process local mark stacks. + Hence the amount of additional code required for parallel marking + is minimal. +

    + It should be possible to use generational collection in the presence of the + parallel collector, by calling GC_enable_incremental(). + This does not result in fully incremental collection, since parallel mark + phases cannot currently be interrupted, and doing so may be too + expensive. +

    + Gcj-style mark descriptors do not currently mix with the combination + of local allocation and incremental collection. They should work correctly + with one or the other, but not both. +

    + The number of marker threads is set on startup to the number of + available processors (or to the value of the GC_NPROCS + environment variable). If only a single processor is detected, + parallel marking is disabled. +

    + Note that setting GC_NPROCS to 1 also causes some lock acquisitions inside + the collector to immediately yield the processor instead of busy waiting + first. In the case of a multiprocessor and a client with multiple + simultaneously runnable threads, this may have disastrous performance + consequences (e.g. a factor of 10 slowdown). +

    Performance

    + We conducted some simple experiments with a version of + our GC benchmark that was slightly modified to + run multiple concurrent client threads in the same address space. + Each client thread does the same work as the original benchmark, but they share + a heap. + This benchmark involves very little work outside of memory allocation. + This was run with GC 6.0alpha3 on a dual processor Pentium III/500 machine + under Linux 2.2.12. +

    + 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 + with glibc malloc + are 10.51 (standard library, pthreads not linked), + 20.90 (one thread, pthreads linked), + and 24.55 seconds respectively. The benchmark favors a + garbage collector, since most objects are small.) +

    + The following table gives execution times for the collector built + with parallel marking and thread-local allocation support + (-DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC). We tested + the client using either one or two marker threads, and running + one or two client threads. Note that the client uses thread local + allocation exclusively. With -DTHREAD_LOCAL_ALLOC the collector + switches to a locking strategy that is better tuned to less frequent + lock acquisition. The standard allocation primitives thus peform + slightly worse than without -DTHREAD_LOCAL_ALLOC, and should be + avoided in time-critical code. +

    + (The results using pthread_mutex_lock + 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. + After a fixed number of attempts, we use pthread_mutex_lock().) +

    + These measurements do not use incremental collection, nor was prefetching + enabled in the marker. We used the C version of the benchmark. + All measurements are in elapsed seconds on an unloaded machine. +

    + + + + + +
    Number of threads1 marker thread (secs.)2 marker threads (secs.)
    1 client10.457.85
    2 clients19.9512.3
    + + The execution time for the single threaded case is slightly worse than with + simple locking. However, even the single-threaded benchmark runs faster than + even the thread-unsafe version if a second processor is available. + The execution time for two clients with thread local allocation time is + only 1.4 times the sequential execution time for a single thread in a + thread-unsafe environment, even though it involves twice the client work. + That represents close to a + factor of 2 improvement over the 2 client case with the old collector. + The old collector clearly + still suffered from some contention overhead, in spite of the fact that the + locking scheme had been fairly well tuned. +

    + Full linear speedup (i.e. the same execution time for 1 client on one + processor as 2 clients on 2 processors) + is probably not achievable on this kind of + hardware even with such a small number of processors, + since the memory system is + a major constraint for the garbage collector, + the processors usually share a single memory bus, and thus + the aggregate memory bandwidth does not increase in + proportion to the number of processors. +

    + These results are likely to be very sensitive to both hardware and OS + issues. Preliminary experiments with an older Pentium Pro machine running + an older kernel were far less encouraging. + + + diff -Nrc3pad gcc-3.3.3/boehm-gc/doc/tree.html gcc-3.4.0/boehm-gc/doc/tree.html *** gcc-3.3.3/boehm-gc/doc/tree.html 2001-08-17 18:39:18.000000000 +0000 --- gcc-3.4.0/boehm-gc/doc/tree.html 2003-07-28 04:18:22.000000000 +0000 *************** *** 1,13 **** Two-Level Tree Structure for Fast Pointer Lookup ! Hans-J. Boehm, Silicon Graphics

    Two-Level Tree Structure for Fast Pointer Lookup

    The conservative garbage collector described ! here uses a 2-level tree data structure to aid in fast pointer identification. This data structure is described in a bit more detail here, since

      --- 1,14 ---- Two-Level Tree Structure for Fast Pointer Lookup ! Hans-J. Boehm, Silicon Graphics (now at HP)

      Two-Level Tree Structure for Fast Pointer Lookup

      The conservative garbage collector described ! here ! uses a 2-level tree data structure to aid in fast pointer identification. This data structure is described in a bit more detail here, since

        diff -Nrc3pad gcc-3.3.3/boehm-gc/dyn_load.c gcc-3.4.0/boehm-gc/dyn_load.c *** gcc-3.3.3/boehm-gc/dyn_load.c 2003-03-04 06:38:30.000000000 +0000 --- gcc-3.4.0/boehm-gc/dyn_load.c 2003-07-30 17:42:28.000000000 +0000 *************** *** 55,63 **** !defined(MSWIN32) && !defined(MSWINCE) && \ !(defined(ALPHA) && defined(OSF1)) && \ !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \ ! !defined(RS6000) && !defined(SCO_ELF) && \ !(defined(FREEBSD) && defined(__ELF__)) && \ ! !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) --> We only know how to find data segments of dynamic libraries for the --> above. Additional SVR4 variants might not be too --> hard to add. --- 55,64 ---- !defined(MSWIN32) && !defined(MSWINCE) && \ !(defined(ALPHA) && defined(OSF1)) && \ !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \ ! !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \ !(defined(FREEBSD) && defined(__ELF__)) && \ ! !(defined(NETBSD) && defined(__ELF__)) && !defined(HURD) && \ ! !defined(DARWIN) --> We only know how to find data segments of dynamic libraries for the --> above. Additional SVR4 variants might not be too --> hard to add. *************** *** 80,86 **** #endif #if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \ ! (defined(FREEBSD) && defined(__ELF__)) || \ (defined(NETBSD) && defined(__ELF__)) || defined(HURD) # include # include --- 81,87 ---- #endif #if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \ ! (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \ (defined(NETBSD) && defined(__ELF__)) || defined(HURD) # include # include *************** void GC_register_dynamic_libraries() *** 264,270 **** # endif /* SUNOS */ #if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \ ! (defined(FREEBSD) && defined(__ELF__)) || \ (defined(NETBSD) && defined(__ELF__)) || defined(HURD) --- 265,271 ---- # endif /* SUNOS */ #if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \ ! (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \ (defined(NETBSD) && defined(__ELF__)) || defined(HURD) *************** extern ssize_t GC_repeat_read(int fd, ch *** 282,337 **** /* Repeatedly read until buffer is filled, or EOF is encountered */ /* Defined in os_dep.c. */ ! static char *parse_map_entry(char *buf_ptr, word *start, word *end, ! char *prot_buf, unsigned int *maj_dev); ! void GC_register_dynamic_libraries() { - int f; - int result; char prot_buf[5]; ! int maps_size; ! char maps_temp[32768]; ! char *maps_buf; ! char *buf_ptr; int count; word start, end; ! unsigned int maj_dev, min_dev; word least_ha, greatest_ha; unsigned i; word datastart = (word)(DATASTART); ! /* Read /proc/self/maps */ ! /* Note that we may not allocate, and thus can't use stdio. */ ! f = open("/proc/self/maps", O_RDONLY); ! if (-1 == f) ABORT("Couldn't open /proc/self/maps"); ! /* stat() doesn't work for /proc/self/maps, so we have to ! read it to find out how large it is... */ ! maps_size = 0; ! do { ! result = GC_repeat_read(f, maps_temp, sizeof(maps_temp)); ! if (result <= 0) ABORT("Couldn't read /proc/self/maps"); ! maps_size += result; ! } while (result == sizeof(maps_temp)); ! ! if (maps_size > sizeof(maps_temp)) { ! /* If larger than our buffer, close and re-read it. */ ! close(f); ! f = open("/proc/self/maps", O_RDONLY); ! if (-1 == f) ABORT("Couldn't open /proc/self/maps"); ! maps_buf = alloca(maps_size); ! if (NULL == maps_buf) ABORT("/proc/self/maps alloca failed"); ! result = GC_repeat_read(f, maps_buf, maps_size); ! if (result <= 0) ABORT("Couldn't read /proc/self/maps"); ! } else { ! /* Otherwise use the fixed size buffer */ ! maps_buf = maps_temp; ! } ! ! close(f); ! maps_buf[result] = '\0'; ! buf_ptr = maps_buf; ! /* Compute heap bounds. Should be done by add_to_heap? */ least_ha = (word)(-1); greatest_ha = 0; for (i = 0; i < GC_n_heap_sects; ++i) { --- 283,305 ---- /* Repeatedly read until buffer is filled, or EOF is encountered */ /* Defined in os_dep.c. */ ! char *GC_parse_map_entry(char *buf_ptr, word *start, word *end, ! char *prot_buf, unsigned int *maj_dev); ! word GC_apply_to_maps(word (*fn)(char *)); ! /* From os_dep.c */ ! word GC_register_map_entries(char *maps) { char prot_buf[5]; ! char *buf_ptr = maps; int count; word start, end; ! unsigned int maj_dev; word least_ha, greatest_ha; unsigned i; word datastart = (word)(DATASTART); ! /* Compute heap bounds. FIXME: Should be done by add_to_heap? */ least_ha = (word)(-1); greatest_ha = 0; for (i = 0; i < GC_n_heap_sects; ++i) { *************** void GC_register_dynamic_libraries() *** 342,352 **** } if (greatest_ha < (word)GC_scratch_last_end_ptr) greatest_ha = (word)GC_scratch_last_end_ptr; - for (;;) { - - buf_ptr = parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev); - if (buf_ptr == NULL) return; if (prot_buf[1] == 'w') { /* This is a writable mapping. Add it to */ /* the root set unless it is already otherwise */ --- 310,319 ---- } if (greatest_ha < (word)GC_scratch_last_end_ptr) greatest_ha = (word)GC_scratch_last_end_ptr; + for (;;) { + buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev); + if (buf_ptr == NULL) return 1; if (prot_buf[1] == 'w') { /* This is a writable mapping. Add it to */ /* the root set unless it is already otherwise */ *************** void GC_register_dynamic_libraries() *** 358,373 **** # ifdef THREADS if (GC_segment_is_thread_stack(start, end)) continue; # endif ! /* The rest of this assumes that there is no mapping */ ! /* spanning the beginning of the data segment, or extending */ ! /* beyond the entire heap at both ends. */ ! /* Empirically these assumptions hold. */ ! ! if (start < (word)DATAEND && end > (word)DATAEND) { ! /* Rld may use space at the end of the main data */ ! /* segment. Thus we add that in. */ ! start = (word)DATAEND; ! } if (start < least_ha && end > least_ha) { end = least_ha; } --- 325,331 ---- # ifdef THREADS if (GC_segment_is_thread_stack(start, end)) continue; # endif ! /* We no longer exclude the main data segment. */ if (start < least_ha && end > least_ha) { end = least_ha; } *************** void GC_register_dynamic_libraries() *** 377,383 **** if (start >= least_ha && end <= greatest_ha) continue; GC_add_roots_inner((char *)start, (char *)end, TRUE); } ! } } /* We now take care of the main data segment ourselves: */ --- 335,348 ---- if (start >= least_ha && end <= greatest_ha) continue; GC_add_roots_inner((char *)start, (char *)end, TRUE); } ! } ! return 1; ! } ! ! void GC_register_dynamic_libraries() ! { ! if (!GC_apply_to_maps(GC_register_map_entries)) ! ABORT("Failed to read /proc for library registration."); } /* We now take care of the main data segment ourselves: */ *************** GC_bool GC_register_main_static_data() *** 387,446 **** } # define HAVE_REGISTER_MAIN_STATIC_DATA - // - // parse_map_entry parses an entry from /proc/self/maps so we can - // locate all writable data segments that belong to shared libraries. - // The format of one of these entries and the fields we care about - // is as follows: - // XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n - // ^^^^^^^^ ^^^^^^^^ ^^^^ ^^ - // start end prot maj_dev - // 0 9 18 32 - // - // The parser is called with a pointer to the entry and the return value - // is either NULL or is advanced to the next entry(the byte after the - // trailing '\n'.) - // - #define OFFSET_MAP_START 0 - #define OFFSET_MAP_END 9 - #define OFFSET_MAP_PROT 18 - #define OFFSET_MAP_MAJDEV 32 - - static char *parse_map_entry(char *buf_ptr, word *start, word *end, - char *prot_buf, unsigned int *maj_dev) - { - int i; - unsigned int val; - char *tok; - - if (buf_ptr == NULL || *buf_ptr == '\0') { - return NULL; - } - - memcpy(prot_buf, buf_ptr+OFFSET_MAP_PROT, 4); // do the protections first - prot_buf[4] = '\0'; - - if (prot_buf[1] == 'w') { // we can skip all of this if it's not writable - - tok = buf_ptr; - buf_ptr[OFFSET_MAP_START+8] = '\0'; - *start = strtoul(tok, NULL, 16); - - tok = buf_ptr+OFFSET_MAP_END; - buf_ptr[OFFSET_MAP_END+8] = '\0'; - *end = strtoul(tok, NULL, 16); - - buf_ptr += OFFSET_MAP_MAJDEV; - tok = buf_ptr; - while (*buf_ptr != ':') buf_ptr++; - *buf_ptr++ = '\0'; - *maj_dev = strtoul(tok, NULL, 16); - } - - while (*buf_ptr && *buf_ptr++ != '\n'); - - return buf_ptr; - } #endif /* USE_PROC_FOR_LIBRARIES */ --- 352,357 ---- *************** GC_bool GC_register_dynamic_libraries_dl *** 508,513 **** --- 419,425 ---- GC_add_roots_inner(DATASTART2, (char *)(DATAEND2), TRUE); # endif } + return TRUE; } else { return FALSE; *************** GC_bool GC_register_main_static_data() *** 534,539 **** --- 446,461 ---- #if defined(NETBSD) # include + /* for compatibility with 1.4.x */ + # ifndef DT_DEBUG + # define DT_DEBUG 21 + # endif + # ifndef PT_LOAD + # define PT_LOAD 1 + # endif + # ifndef PF_W + # define PF_W 2 + # endif #else # include #endif *************** void GC_register_dynamic_libraries() *** 1048,1054 **** len = ldi->ldinfo_next; GC_add_roots_inner( ldi->ldinfo_dataorg, ! (unsigned long)ldi->ldinfo_dataorg + ldi->ldinfo_datasize, TRUE); ldi = len ? (struct ld_info *)((char *)ldi + len) : 0; --- 970,976 ---- len = ldi->ldinfo_next; GC_add_roots_inner( ldi->ldinfo_dataorg, ! (ptr_t)(unsigned long)ldi->ldinfo_dataorg + ldi->ldinfo_datasize, TRUE); ldi = len ? (struct ld_info *)((char *)ldi + len) : 0; *************** void GC_register_dynamic_libraries() *** 1056,1062 **** --- 978,1116 ---- } #endif /* RS6000 */ + #ifdef DARWIN + + #ifndef __private_extern__ + #define __private_extern__ extern + #include + #undef __private_extern__ + #else + #include + #endif + #include + + /*#define DARWIN_DEBUG*/ + + const static struct { + const char *seg; + const char *sect; + } GC_dyld_sections[] = { + { SEG_DATA, SECT_DATA }, + { SEG_DATA, SECT_BSS }, + { SEG_DATA, SECT_COMMON } + }; + + #ifdef DARWIN_DEBUG + static const char *GC_dyld_name_for_hdr(struct mach_header *hdr) { + unsigned long i,c; + c = _dyld_image_count(); + for(i=0;isize == 0) continue; + start = slide + sec->addr; + end = start + sec->size; + # ifdef DARWIN_DEBUG + GC_printf4("Adding section at %p-%p (%lu bytes) from image %s\n", + start,end,sec->size,GC_dyld_name_for_hdr(hdr)); + # endif + GC_add_roots((char*)start,(char*)end); + } + # ifdef DARWIN_DEBUG + GC_print_static_roots(); + # endif + } + + /* This should never be called by a thread holding the lock */ + static void GC_dyld_image_remove(struct mach_header* hdr, unsigned long slide) { + unsigned long start,end,i; + const struct section *sec; + for(i=0;isize == 0) continue; + start = slide + sec->addr; + end = start + sec->size; + # ifdef DARWIN_DEBUG + GC_printf4("Removing section at %p-%p (%lu bytes) from image %s\n", + start,end,sec->size,GC_dyld_name_for_hdr(hdr)); + # endif + GC_remove_roots((char*)start,(char*)end); + } + # ifdef DARWIN_DEBUG + GC_print_static_roots(); + # endif + } + + void GC_register_dynamic_libraries() { + /* Currently does nothing. The callbacks are setup by GC_init_dyld() + The dyld library takes it from there. */ + } + /* The _dyld_* functions have an internal lock so no _dyld functions + can be called while the world is stopped without the risk of a deadlock. + Because of this we MUST setup callbacks BEFORE we ever stop the world. + This should be called BEFORE any thread in created and WITHOUT the + allocation lock held. */ + + void GC_init_dyld() { + static GC_bool initialized = FALSE; + char *bind_fully_env = NULL; + + if(initialized) return; + + # ifdef DARWIN_DEBUG + GC_printf0("Registering dyld callbacks...\n"); + # endif + + /* Apple's Documentation: + When you call _dyld_register_func_for_add_image, the dynamic linker runtime + calls the specified callback (func) once for each of the images that is + currently loaded into the program. When a new image is added to the program, + your callback is called again with the mach_header for the new image, and the + virtual memory slide amount of the new image. + + 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); + + /* Set this early to avoid reentrancy issues. */ + initialized = TRUE; + + bind_fully_env = getenv("DYLD_BIND_AT_LAUNCH"); + + if (bind_fully_env == NULL) { + # ifdef DARWIN_DEBUG + GC_printf0("Forcing full bind of GC code...\n"); + # endif + + if(!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc)) + GC_abort("_dyld_bind_fully_image_containing_address failed"); + } + + } + + #define HAVE_REGISTER_MAIN_STATIC_DATA + GC_bool GC_register_main_static_data() + { + /* Already done through dyld callbacks */ + return FALSE; + } + + #endif /* DARWIN */ #else /* !DYNAMIC_LOADING */ diff -Nrc3pad gcc-3.3.3/boehm-gc/finalize.c gcc-3.4.0/boehm-gc/finalize.c *** gcc-3.3.3/boehm-gc/finalize.c 2002-02-12 04:37:53.000000000 +0000 --- gcc-3.4.0/boehm-gc/finalize.c 2003-07-28 04:18:20.000000000 +0000 *************** signed_word * log_size_ptr; *** 207,213 **** UNLOCK(); ENABLE_SIGNALS(); # endif ! new_dl = GC_oom_fn(sizeof(struct disappearing_link)); if (0 == new_dl) { GC_finalization_failures++; return(0); --- 207,214 ---- UNLOCK(); ENABLE_SIGNALS(); # endif ! new_dl = (struct disappearing_link *) ! GC_oom_fn(sizeof(struct disappearing_link)); if (0 == new_dl) { GC_finalization_failures++; return(0); *************** finalization_mark_proc * mp; *** 433,439 **** UNLOCK(); ENABLE_SIGNALS(); # endif ! new_fo = GC_oom_fn(sizeof(struct finalizable_object)); if (0 == new_fo) { GC_finalization_failures++; return; --- 434,441 ---- UNLOCK(); ENABLE_SIGNALS(); # endif ! new_fo = (struct finalizable_object *) ! GC_oom_fn(sizeof(struct finalizable_object)); if (0 == new_fo) { GC_finalization_failures++; return; *************** int GC_should_invoke_finalizers GC_PROTO *** 759,766 **** /* Should be called without allocation lock. */ int GC_invoke_finalizers() { ! register struct finalizable_object * curr_fo; ! register int count = 0; DCL_LOCK_STATE; while (GC_finalize_now != 0) { --- 761,769 ---- /* Should be called without allocation lock. */ int GC_invoke_finalizers() { ! struct finalizable_object * curr_fo; ! int count = 0; ! word mem_freed_before; DCL_LOCK_STATE; while (GC_finalize_now != 0) { *************** int GC_invoke_finalizers() *** 768,773 **** --- 771,779 ---- DISABLE_SIGNALS(); LOCK(); # endif + if (count == 0) { + mem_freed_before = GC_mem_freed; + } curr_fo = GC_finalize_now; # ifdef THREADS if (curr_fo != 0) GC_finalize_now = fo_next(curr_fo); *************** int GC_invoke_finalizers() *** 789,794 **** --- 795,805 ---- GC_free((GC_PTR)curr_fo); # endif } + if (count != 0 && mem_freed_before != GC_mem_freed) { + LOCK(); + GC_finalizer_mem_freed += (GC_mem_freed - mem_freed_before); + UNLOCK(); + } return count; } *************** void GC_notify_or_invoke_finalizers GC_P *** 801,807 **** if (GC_finalize_now == 0) return; if (!GC_finalize_on_demand) { (void) GC_invoke_finalizers(); ! GC_ASSERT(GC_finalize_now == 0); return; } if (GC_finalizer_notifier != (void (*) GC_PROTO((void)))0 --- 812,820 ---- if (GC_finalize_now == 0) return; if (!GC_finalize_on_demand) { (void) GC_invoke_finalizers(); ! # ifndef THREADS ! GC_ASSERT(GC_finalize_now == 0); ! # endif /* Otherwise GC can run concurrently and add more */ return; } if (GC_finalizer_notifier != (void (*) GC_PROTO((void)))0 *************** void GC_notify_or_invoke_finalizers GC_P *** 839,841 **** --- 852,868 ---- return(result); } + #if !defined(NO_DEBUGGING) + + void GC_print_finalization_stats() + { + struct finalizable_object *fo = GC_finalize_now; + size_t ready = 0; + + GC_printf2("%lu finalization table entries; %lu disappearing links\n", + GC_fo_entries, GC_dl_entries); + for (; 0 != fo; fo = fo_next(fo)) ++ready; + GC_printf1("%lu objects are eligible for immediate finalization\n", ready); + } + + #endif /* NO_DEBUGGING */ diff -Nrc3pad gcc-3.3.3/boehm-gc/gc_cpp.cc gcc-3.4.0/boehm-gc/gc_cpp.cc *** gcc-3.3.3/boehm-gc/gc_cpp.cc 2001-08-17 18:30:45.000000000 +0000 --- gcc-3.4.0/boehm-gc/gc_cpp.cc 2003-07-28 04:18:20.000000000 +0000 *************** Authors: John R. Ellis and Jesse Hull *** 26,40 **** #include "gc_cpp.h" - #ifndef _MSC_VER - /* In the Visual C++ case, we moved this into the header. */ void* operator new( size_t size ) { return GC_MALLOC_UNCOLLECTABLE( size );} void operator delete( void* obj ) { GC_FREE( obj );} ! #ifdef OPERATOR_NEW_ARRAY void* operator new[]( size_t size ) { return GC_MALLOC_UNCOLLECTABLE( size );} --- 26,38 ---- #include "gc_cpp.h" void* operator new( size_t size ) { return GC_MALLOC_UNCOLLECTABLE( size );} void operator delete( void* obj ) { GC_FREE( obj );} ! #ifdef GC_OPERATOR_NEW_ARRAY void* operator new[]( size_t size ) { return GC_MALLOC_UNCOLLECTABLE( size );} *************** void* operator new[]( size_t size ) { *** 42,49 **** void operator delete[]( void* obj ) { GC_FREE( obj );} ! #endif /* OPERATOR_NEW_ARRAY */ ! #endif /* _MSC_VER */ --- 40,61 ---- void operator delete[]( void* obj ) { 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 ) ! { ! #ifndef GC_DEBUG ! return GC_malloc_uncollectable( size ); ! #else ! return GC_debug_malloc_uncollectable(size, szFileName, nLine); ! #endif ! } + #endif /* _MSC_VER */ diff -Nrc3pad gcc-3.3.3/boehm-gc/gc_dlopen.c gcc-3.4.0/boehm-gc/gc_dlopen.c *** gcc-3.3.3/boehm-gc/gc_dlopen.c 2001-10-16 09:01:35.000000000 +0000 --- gcc-3.4.0/boehm-gc/gc_dlopen.c 2003-07-28 04:18:20.000000000 +0000 *************** *** 19,30 **** /* * This used to be in dyn_load.c. It was extracted into a separate file * to avoid having to link against libdl.{a,so} if the client doesn't call ! * dlopen. -HB */ #include "private/gc_priv.h" ! # if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) # if defined(dlopen) && !defined(GC_USE_LD_WRAP) /* To support various threads pkgs, gc.h interposes on dlopen by */ --- 19,32 ---- /* * This used to be in dyn_load.c. It was extracted into a separate file * to avoid having to link against libdl.{a,so} if the client doesn't call ! * dlopen. Of course this fails if the collector is in a dynamic ! * library. -HB */ #include "private/gc_priv.h" ! # if (defined(GC_PTHREADS) && !defined(GC_DARWIN_THREADS)) \ ! || defined(GC_SOLARIS_THREADS) # if defined(dlopen) && !defined(GC_USE_LD_WRAP) /* To support various threads pkgs, gc.h interposes on dlopen by */ *************** *** 44,62 **** /* calls in either a multithreaded environment, or if the library */ /* initialization code allocates substantial amounts of GC'ed memory. */ /* But I don't know of a better solution. */ ! /* This can still deadlock if the client explicitly starts a GC */ ! /* during the dlopen. He shouldn't do that. */ ! static GC_bool disable_gc_for_dlopen() { - GC_bool result; LOCK(); - result = GC_dont_gc; while (GC_incremental && GC_collection_in_progress()) { GC_collect_a_little_inner(1000); } ! GC_dont_gc = TRUE; UNLOCK(); - return(result); } /* Redefine dlopen to guarantee mutual exclusion with */ --- 46,59 ---- /* calls in either a multithreaded environment, or if the library */ /* initialization code allocates substantial amounts of GC'ed memory. */ /* But I don't know of a better solution. */ ! static void disable_gc_for_dlopen() { LOCK(); while (GC_incremental && GC_collection_in_progress()) { GC_collect_a_little_inner(1000); } ! ++GC_dont_gc; UNLOCK(); } /* Redefine dlopen to guarantee mutual exclusion with */ *************** *** 74,83 **** #endif { void * result; - GC_bool dont_gc_save; # ifndef USE_PROC_FOR_LIBRARIES ! dont_gc_save = disable_gc_for_dlopen(); # endif # ifdef GC_USE_LD_WRAP result = (void *)__real_dlopen(path, mode); --- 71,79 ---- #endif { void * result; # ifndef USE_PROC_FOR_LIBRARIES ! disable_gc_for_dlopen(); # endif # ifdef GC_USE_LD_WRAP result = (void *)__real_dlopen(path, mode); *************** *** 85,91 **** result = dlopen(path, mode); # endif # ifndef USE_PROC_FOR_LIBRARIES ! GC_dont_gc = dont_gc_save; # endif return(result); } --- 81,87 ---- result = dlopen(path, mode); # endif # ifndef USE_PROC_FOR_LIBRARIES ! GC_enable(); /* undoes disable_gc_for_dlopen */ # endif return(result); } diff -Nrc3pad gcc-3.3.3/boehm-gc/gcj_mlc.c gcc-3.4.0/boehm-gc/gcj_mlc.c *** gcc-3.3.3/boehm-gc/gcj_mlc.c 2002-02-12 04:37:53.000000000 +0000 --- gcc-3.4.0/boehm-gc/gcj_mlc.c 2003-07-28 04:18:20.000000000 +0000 *************** DCL_LOCK_STATE; *** 157,162 **** --- 157,163 ---- GC_words_allocd += lw; } *(void **)op = ptr_to_struct_containing_descr; + GC_ASSERT(((void **)op)[1] == 0); UNLOCK(); } else { LOCK(); diff -Nrc3pad gcc-3.3.3/boehm-gc/if_mach.c gcc-3.4.0/boehm-gc/if_mach.c *** gcc-3.3.3/boehm-gc/if_mach.c 2001-08-17 18:30:45.000000000 +0000 --- gcc-3.4.0/boehm-gc/if_mach.c 2003-07-28 04:18:20.000000000 +0000 *************** char ** envp; *** 14,20 **** if (strcmp(MACH_TYPE, argv[1]) != 0) return(0); if (strcmp(OS_TYPE, "") != 0 && strcmp(argv[2], "") != 0 && strcmp(OS_TYPE, argv[2]) != 0) return(0); ! printf("^^^^Starting command^^^^\n"); fflush(stdout); execvp(argv[3], argv+3); perror("Couldn't execute"); --- 14,20 ---- if (strcmp(MACH_TYPE, argv[1]) != 0) return(0); if (strcmp(OS_TYPE, "") != 0 && strcmp(argv[2], "") != 0 && strcmp(OS_TYPE, argv[2]) != 0) return(0); ! fprintf(stderr, "^^^^Starting command^^^^\n"); fflush(stdout); execvp(argv[3], argv+3); perror("Couldn't execute"); diff -Nrc3pad gcc-3.3.3/boehm-gc/include/gc_allocator.h gcc-3.4.0/boehm-gc/include/gc_allocator.h *** gcc-3.3.3/boehm-gc/include/gc_allocator.h 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/gc_allocator.h 2003-07-28 03:46:17.000000000 +0000 *************** *** 0 **** --- 1,232 ---- + /* + * Copyright (c) 1996-1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * Copyright (c) 2002 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + + /* + * This implements standard-conforming allocators that interact with + * the garbage collector. Gc_alloctor allocates garbage-collectable + * objects of type T. Traceable_allocator allocates objects that + * are not temselves garbage collected, but are scanned by the + * collector for pointers to collectable objects. Traceable_alloc + * should be used for explicitly managed STL containers that may + * point to collectable objects. + * + * This code was derived from an earlier version of the GNU C++ standard + * library, which itself was derived from the SGI STL implementation. + */ + + #include "gc.h" // For size_t + + /* First some helpers to allow us to dispatch on whether or not a type + * is known to be pointerfree. + * These are private, except that the client may invoke the + * GC_DECLARE_PTRFREE macro. + */ + + struct GC_true_type {}; + struct GC_false_type {}; + + template + struct GC_type_traits { + GC_false_type GC_is_ptr_free; + }; + + # define GC_DECLARE_PTRFREE(T) \ + template<> struct GC_type_traits { GC_true_type GC_is_ptr_free; } + + GC_DECLARE_PTRFREE(signed char); + GC_DECLARE_PTRFREE(unsigned char); + GC_DECLARE_PTRFREE(signed short); + GC_DECLARE_PTRFREE(unsigned short); + GC_DECLARE_PTRFREE(signed int); + GC_DECLARE_PTRFREE(unsigned int); + GC_DECLARE_PTRFREE(signed long); + GC_DECLARE_PTRFREE(unsigned long); + GC_DECLARE_PTRFREE(float); + GC_DECLARE_PTRFREE(double); + /* The client may want to add others. */ + + // In the following GC_Tp is GC_true_type iff we are allocating a + // pointerfree object. + template + inline void * GC_selective_alloc(size_t n, GC_Tp) { + return GC_MALLOC(n); + } + + template <> + inline void * GC_selective_alloc(size_t n, GC_true_type) { + return GC_MALLOC_ATOMIC(n); + } + + /* Now the public gc_allocator class: + */ + template + class gc_allocator { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef GC_Tp* pointer; + typedef const GC_Tp* const_pointer; + typedef GC_Tp& reference; + typedef const GC_Tp& const_reference; + typedef GC_Tp value_type; + + template struct rebind { + typedef gc_allocator other; + }; + + gc_allocator() {} + # ifndef _MSC_VER + // I'm not sure why this is needed here in addition to the following. + // The standard specifies it for the standard allocator, but VC++ rejects + // it. -HB + gc_allocator(const gc_allocator&) throw() {} + # endif + template gc_allocator(const gc_allocator&) throw() {} + ~gc_allocator() throw() {} + + pointer address(reference GC_x) const { return &GC_x; } + const_pointer address(const_reference GC_x) const { return &GC_x; } + + // 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) { + GC_type_traits traits; + return static_cast + (GC_selective_alloc(GC_n * sizeof(GC_Tp), + traits.GC_is_ptr_free)); + } + + // __p is not permitted to be a null pointer. + void deallocate(pointer __p, size_type GC_n) + { GC_FREE(__p); } + + size_type max_size() const throw() + { return size_t(-1) / sizeof(GC_Tp); } + + void construct(pointer __p, const GC_Tp& __val) { new(__p) GC_Tp(__val); } + void destroy(pointer __p) { __p->~GC_Tp(); } + }; + + template<> + class gc_allocator { + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + template struct rebind { + typedef gc_allocator other; + }; + }; + + + template + inline bool operator==(const gc_allocator&, const gc_allocator&) + { + return true; + } + + template + inline bool operator!=(const gc_allocator&, const gc_allocator&) + { + return false; + } + + /* + * And the public traceable_allocator class. + */ + + // Note that we currently don't specialize the pointer-free case, since a + // pointer-free traceable container doesn't make that much sense, + // though it could become an issue due to abstraction boundaries. + template + class traceable_allocator { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef GC_Tp* pointer; + typedef const GC_Tp* const_pointer; + typedef GC_Tp& reference; + typedef const GC_Tp& const_reference; + typedef GC_Tp value_type; + + template struct rebind { + typedef traceable_allocator other; + }; + + traceable_allocator() throw() {} + # ifndef _MSC_VER + traceable_allocator(const traceable_allocator&) throw() {} + # endif + template traceable_allocator + (const traceable_allocator&) throw() {} + ~traceable_allocator() throw() {} + + pointer address(reference GC_x) const { return &GC_x; } + const_pointer address(const_reference GC_x) const { return &GC_x; } + + // 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))); + } + + // __p is not permitted to be a null pointer. + void deallocate(pointer __p, size_type GC_n) + { GC_FREE(__p); } + + size_type max_size() const throw() + { return size_t(-1) / sizeof(GC_Tp); } + + void construct(pointer __p, const GC_Tp& __val) { new(__p) GC_Tp(__val); } + void destroy(pointer __p) { __p->~GC_Tp(); } + }; + + template<> + class traceable_allocator { + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + template struct rebind { + typedef traceable_allocator other; + }; + }; + + + template + inline bool operator==(const traceable_allocator&, const traceable_allocator&) + { + return true; + } + + template + inline bool operator!=(const traceable_allocator&, const traceable_allocator&) + { + return false; + } + diff -Nrc3pad gcc-3.3.3/boehm-gc/include/gc_config_macros.h gcc-3.4.0/boehm-gc/include/gc_config_macros.h *** gcc-3.3.3/boehm-gc/include/gc_config_macros.h 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/gc_config_macros.h 2003-07-28 03:46:17.000000000 +0000 *************** *** 0 **** --- 1,147 ---- + /* + * This should never be included directly. It is included only from gc.h. + * We separate it only to make gc.h more suitable as documentation. + * + * Some tests for old macros. These violate our namespace rules and will + * disappear shortly. Use the GC_ names. + */ + #if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) + # define GC_SOLARIS_THREADS + #endif + #if defined(_SOLARIS_PTHREADS) + # define GC_SOLARIS_PTHREADS + #endif + #if defined(IRIX_THREADS) + # define GC_IRIX_THREADS + #endif + #if defined(DGUX_THREADS) + # if !defined(GC_DGUX386_THREADS) + # define GC_DGUX386_THREADS + # endif + #endif + #if defined(AIX_THREADS) + # define GC_AIX_THREADS + #endif + #if defined(HPUX_THREADS) + # define GC_HPUX_THREADS + #endif + #if defined(OSF1_THREADS) + # define GC_OSF1_THREADS + #endif + #if defined(LINUX_THREADS) + # define GC_LINUX_THREADS + #endif + #if defined(WIN32_THREADS) + # define GC_WIN32_THREADS + #endif + #if defined(USE_LD_WRAP) + # define GC_USE_LD_WRAP + #endif + + #if !defined(_REENTRANT) && (defined(GC_SOLARIS_THREADS) \ + || defined(GC_SOLARIS_PTHREADS) \ + || defined(GC_HPUX_THREADS) \ + || defined(GC_AIX_THREADS) \ + || defined(GC_LINUX_THREADS)) + # define _REENTRANT + /* Better late than never. This fails if system headers that */ + /* depend on this were previously included. */ + #endif + + #if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE) + # define _POSIX4A_DRAFT10_SOURCE 1 + #endif + + # if defined(GC_SOLARIS_PTHREADS) || defined(GC_FREEBSD_THREADS) || \ + defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \ + defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \ + defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \ + defined(GC_AIX_THREADS) || \ + (defined(GC_WIN32_THREADS) && defined(__CYGWIN32__)) + # define GC_PTHREADS + # endif + + #if defined(GC_THREADS) && !defined(GC_PTHREADS) + # if defined(__linux__) + # define GC_LINUX_THREADS + # define GC_PTHREADS + # endif + # if !defined(LINUX) && (defined(_PA_RISC1_1) || defined(_PA_RISC2_0) \ + || defined(hppa) || defined(__HPPA)) + # define GC_HPUX_THREADS + # define GC_PTHREADS + # endif + # if !defined(__linux__) && (defined(__alpha) || defined(__alpha__)) + # define GC_OSF1_THREADS + # define GC_PTHREADS + # endif + # if defined(__mips) && !defined(__linux__) + # define GC_IRIX_THREADS + # define GC_PTHREADS + # endif + # if defined(__sparc) && !defined(__linux__) + # define GC_SOLARIS_PTHREADS + # define GC_PTHREADS + # endif + # if defined(__APPLE__) && defined(__MACH__) && defined(__ppc__) + # define GC_DARWIN_THREADS + # define GC_PTHREADS + # endif + # if !defined(GC_PTHREADS) && defined(__FreeBSD__) + # define GC_FREEBSD_THREADS + # define GC_PTHREADS + # endif + # if defined(DGUX) && (defined(i386) || defined(__i386__)) + # define GC_DGUX386_THREADS + # define GC_PTHREADS + # endif + #endif /* GC_THREADS */ + + #if defined(GC_THREADS) && !defined(GC_PTHREADS) && defined(MSWIN32) + # define GC_WIN32_THREADS + #endif + + #if defined(GC_SOLARIS_PTHREADS) && !defined(GC_SOLARIS_THREADS) + # define GC_SOLARIS_THREADS + #endif + + # define __GC + # include + # ifdef _WIN32_WCE + /* Yet more kluges for WinCE */ + # include /* size_t is defined here */ + typedef long ptrdiff_t; /* ptrdiff_t is not defined */ + # endif + + #if defined(_DLL) && !defined(GC_NOT_DLL) && !defined(GC_DLL) + # define GC_DLL + #endif + + #if defined(__MINGW32__) && defined(GC_DLL) + # ifdef GC_BUILD + # define GC_API __declspec(dllexport) + # else + # define GC_API __declspec(dllimport) + # endif + #endif + + #if (defined(__DMC__) || defined(_MSC_VER)) && defined(GC_DLL) + # ifdef GC_BUILD + # define GC_API extern __declspec(dllexport) + # else + # define GC_API __declspec(dllimport) + # endif + #endif + + #if defined(__WATCOMC__) && defined(GC_DLL) + # ifdef GC_BUILD + # define GC_API extern __declspec(dllexport) + # else + # define GC_API extern __declspec(dllimport) + # endif + #endif + + #ifndef GC_API + #define GC_API extern + #endif + diff -Nrc3pad gcc-3.3.3/boehm-gc/include/gc_cpp.h gcc-3.4.0/boehm-gc/include/gc_cpp.h *** gcc-3.3.3/boehm-gc/include/gc_cpp.h 2001-08-18 01:04:43.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/gc_cpp.h 2003-07-28 04:18:23.000000000 +0000 *************** by UseGC. GC is an alias for UseGC, unl *** 134,140 **** #include "gc.h" #ifndef THINK_CPLUS ! #define _cdecl #endif #if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \ --- 134,142 ---- #include "gc.h" #ifndef THINK_CPLUS ! # define GC_cdecl ! #else ! # define GC_cdecl _cdecl #endif #if ! defined( GC_NO_OPERATOR_NEW_ARRAY ) \ *************** enum GCPlacement {UseGC, *** 159,170 **** --- 161,182 ---- 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 ); + # ifndef __BORLANDC__ /* Confuses the Borland compiler. */ + inline void operator delete( void*, void* ); + # endif #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 ); + # ifndef __BORLANDC__ + inline void gc::operator delete[]( void*, void* ); + # endif #endif /* GC_OPERATOR_NEW_ARRAY */ }; /* *************** class gc_cleanup: virtual public gc {pub *** 176,182 **** inline gc_cleanup(); inline virtual ~gc_cleanup(); private: ! inline static void _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 --- 188,194 ---- inline gc_cleanup(); inline virtual ~gc_cleanup(); private: ! 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 *************** inline void* operator new( *** 211,217 **** classes derived from "gc_cleanup" or containing members derived from "gc_cleanup". */ - #ifdef GC_OPERATOR_NEW_ARRAY #ifdef _MSC_VER /** This ensures that the system default operator new[] doesn't get --- 223,228 ---- *************** inline void* operator new( *** 220,261 **** * There seems to be really redirect new in this environment without * including this everywhere. */ ! inline void *operator new[]( size_t size ) ! { ! return GC_MALLOC_UNCOLLECTABLE( size ); ! } ! ! inline void operator delete[](void* obj) ! { ! GC_FREE(obj); ! }; ! ! inline void* operator new( size_t size) ! { ! return GC_MALLOC_UNCOLLECTABLE( size); ! }; ! inline void operator delete(void* obj) ! { ! GC_FREE(obj); ! }; ! // This new operator is used by VC++ in case of Debug builds ! ! inline void* operator new( size_t size, int ,//nBlockUse, const char * szFileName, ! int nLine ! ) { ! # ifndef GC_DEBUG ! return GC_malloc_uncollectable( size ); ! # else ! return GC_debug_malloc_uncollectable(size, szFileName, nLine); ! # endif ! } ! #endif /* _MSC_VER */ inline void* operator new[]( size_t size, GCPlacement gcp, --- 231,254 ---- * There seems to be really redirect new in this environment without * including this everywhere. */ ! void *operator new[]( size_t size ); ! ! void operator delete[](void* obj); ! void* operator new( size_t size); + void operator delete(void* 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 */ + + #ifdef GC_OPERATOR_NEW_ARRAY + inline void* operator new[]( size_t size, GCPlacement gcp, *************** inline void* gc::operator new( size_t si *** 283,291 **** --- 276,290 ---- else return GC_MALLOC_UNCOLLECTABLE( size );} + inline void* gc::operator new( size_t size, void *p ) { + return p;} + inline void gc::operator delete( void* obj ) { GC_FREE( obj );} + #ifndef __BORLANDC__ + inline void gc::operator delete( void*, void* ) {} + #endif #ifdef GC_OPERATOR_NEW_ARRAY *************** inline void* gc::operator new[]( size_t *** 295,308 **** inline void* gc::operator new[]( size_t size, GCPlacement gcp ) { return gc::operator new( size, gcp );} inline void gc::operator delete[]( void* obj ) { gc::operator delete( obj );} #endif /* GC_OPERATOR_NEW_ARRAY */ inline gc_cleanup::~gc_cleanup() { ! GC_REGISTER_FINALIZER_IGNORE_SELF( GC_base(this), 0, 0, 0, 0 );} inline void gc_cleanup::cleanup( void* obj, void* displ ) { ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();} --- 294,314 ---- 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 ) { + return p;} + inline void gc::operator delete[]( void* obj ) { gc::operator delete( obj );} + + #ifndef __BORLANDC__ + inline void gc::operator delete[]( void*, void* ) {} + #endif #endif /* GC_OPERATOR_NEW_ARRAY */ inline gc_cleanup::~gc_cleanup() { ! GC_register_finalizer_ignore_self( GC_base(this), 0, 0, 0, 0 );} inline void gc_cleanup::cleanup( void* obj, void* displ ) { ((gc_cleanup*) ((char*) obj + (ptrdiff_t) displ))->~gc_cleanup();} diff -Nrc3pad gcc-3.3.3/boehm-gc/include/gc.h gcc-3.4.0/boehm-gc/include/gc.h *** gcc-3.3.3/boehm-gc/include/gc.h 2002-02-12 04:37:56.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/gc.h 2003-07-31 04:52:36.000000000 +0000 *************** *** 30,120 **** # define _GC_H ! /* ! * Some tests for old macros. These violate our namespace rules and will ! * disappear shortly. Use the GC_ names. ! */ ! #if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) ! # define GC_SOLARIS_THREADS ! #endif ! #if defined(_SOLARIS_PTHREADS) ! # define GC_SOLARIS_PTHREADS ! #endif ! #if defined(IRIX_THREADS) ! # define GC_IRIX_THREADS ! #endif ! #if defined(HPUX_THREADS) ! # define GC_HPUX_THREADS ! #endif ! #if defined(OSF1_THREADS) ! # define GC_OSF1_THREADS ! #endif ! #if defined(LINUX_THREADS) ! # define GC_LINUX_THREADS ! #endif ! #if defined(WIN32_THREADS) ! # define GC_WIN32_THREADS ! #endif ! #if defined(USE_LD_WRAP) ! # define GC_USE_LD_WRAP ! #endif ! ! #if !defined(_REENTRANT) && (defined(GC_SOLARIS_THREADS) \ ! || defined(GC_SOLARIS_PTHREADS) \ ! || defined(GC_HPUX_THREADS) \ ! || defined(GC_LINUX_THREADS)) ! # define _REENTRANT ! /* Better late than never. This fails if system headers that */ ! /* depend on this were previously included. */ ! #endif ! ! #if defined(GC_SOLARIS_PTHREADS) && !defined(GC_SOLARIS_THREADS) ! # define GC_SOLARIS_THREADS ! #endif ! ! # if defined(GC_SOLARIS_PTHREADS) || defined(GC_FREEBSD_THREADS) || \ ! defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) || \ ! defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) ! # define GC_PTHREADS ! # endif ! ! # define __GC ! # include ! # ifdef _WIN32_WCE ! /* Yet more kluges for WinCE */ ! # include /* size_t is defined here */ ! typedef long ptrdiff_t; /* ptrdiff_t is not defined */ ! # endif ! ! #if defined(__MINGW32__) &&defined(_DLL) && !defined(GC_NOT_DLL) ! # ifdef GC_BUILD ! # define GC_API __declspec(dllexport) ! # else ! # define GC_API __declspec(dllimport) ! # endif ! #endif ! ! #if (defined(__DMC__) || defined(_MSC_VER)) \ ! && (defined(_DLL) && !defined(GC_NOT_DLL) \ ! || defined(GC_DLL)) ! # ifdef GC_BUILD ! # define GC_API extern __declspec(dllexport) ! # else ! # define GC_API __declspec(dllimport) ! # endif ! #endif ! ! #if defined(__WATCOMC__) && defined(GC_DLL) ! # ifdef GC_BUILD ! # define GC_API extern __declspec(dllexport) ! # else ! # define GC_API extern __declspec(dllimport) ! # endif ! #endif ! ! #ifndef GC_API ! #define GC_API extern ! #endif # if defined(__STDC__) || defined(__cplusplus) # define GC_PROTO(args) args --- 30,36 ---- # define _GC_H ! # include "gc_config_macros.h" # if defined(__STDC__) || defined(__cplusplus) # define GC_PROTO(args) args *************** GC_API int GC_parallel; /* GC is paralle *** 154,160 **** /* Env variable GC_NPROC is set to > 1, or */ /* GC_NPROC is not set and this is an MP. */ /* If GC_parallel is set, incremental */ ! /* collection is aonly partially functional, */ /* and may not be desirable. */ --- 70,76 ---- /* Env variable GC_NPROC is set to > 1, or */ /* GC_NPROC is not set and this is an MP. */ /* If GC_parallel is set, incremental */ ! /* collection is only partially functional, */ /* and may not be desirable. */ *************** GC_API void (* GC_finalizer_notifier)(); *** 215,222 **** /* thread, which will call GC_invoke_finalizers */ /* in response. */ ! GC_API int GC_dont_gc; /* Dont collect unless explicitly requested, e.g. */ ! /* because it's not safe. */ GC_API int GC_dont_expand; /* Dont expand heap unless explicitly requested */ --- 131,144 ---- /* thread, which will call GC_invoke_finalizers */ /* in response. */ ! GC_API int GC_dont_gc; /* != 0 ==> Dont collect. In versions 6.2a1+, */ ! /* this overrides explicit GC_gcollect() calls. */ ! /* Used as a counter, so that nested enabling */ ! /* and disabling work correctly. Should */ ! /* normally be updated with GC_enable() and */ ! /* GC_disable() calls. */ ! /* Direct assignment to GC_dont_gc is */ ! /* deprecated. */ GC_API int GC_dont_expand; /* Dont expand heap unless explicitly requested */ *************** GC_API unsigned long GC_time_limit; *** 316,324 **** /* enabled. */ # define GC_TIME_UNLIMITED 999999 /* Setting GC_time_limit to this value */ ! /* will disable the "pause time exceeded */ /* tests. */ /* * general purpose allocation routines, with roughly malloc calling conv. * The atomic versions promise that no relevant pointers are contained --- 238,255 ---- /* enabled. */ # define GC_TIME_UNLIMITED 999999 /* Setting GC_time_limit to this value */ ! /* will disable the "pause time exceeded"*/ /* tests. */ + /* Public procedures */ + + /* Initialize the collector. This is only required when using thread-local + * allocation, since unlike the regular allocation routines, GC_local_malloc + * is not self-initializing. If you use GC_local_malloc you should arrange + * to call this somehow (e.g. from a constructor) before doing any allocation. + */ + GC_API void GC_init GC_PROTO((void)); + /* * general purpose allocation routines, with roughly malloc calling conv. * The atomic versions promise that no relevant pointers are contained *************** GC_API void GC_clear_roots GC_PROTO((voi *** 419,435 **** GC_API void GC_add_roots GC_PROTO((char * low_address, char * high_address_plus_1)); /* Add a displacement to the set of those considered valid by the */ /* collector. GC_register_displacement(n) means that if p was returned */ /* by GC_malloc, then (char *)p + n will be considered to be a valid */ ! /* pointer to n. N must be small and less than the size of p. */ /* (All pointers to the interior of objects from the stack are */ /* considered valid in any case. This applies to heap objects and */ /* static data.) */ /* Preferably, this should be called before any other GC procedures. */ /* Calling it later adds to the probability of excess memory */ /* retention. */ ! /* This is a no-op if the collector was compiled with recognition of */ /* arbitrary interior pointers enabled, which is now the default. */ GC_API void GC_register_displacement GC_PROTO((GC_word n)); --- 350,370 ---- GC_API void GC_add_roots GC_PROTO((char * low_address, char * high_address_plus_1)); + /* Remove a root segment. Wizards only. */ + GC_API void GC_remove_roots GC_PROTO((char * low_address, + char * high_address_plus_1)); + /* Add a displacement to the set of those considered valid by the */ /* collector. GC_register_displacement(n) means that if p was returned */ /* by GC_malloc, then (char *)p + n will be considered to be a valid */ ! /* pointer to p. N must be small and less than the size of p. */ /* (All pointers to the interior of objects from the stack are */ /* considered valid in any case. This applies to heap objects and */ /* static data.) */ /* Preferably, this should be called before any other GC procedures. */ /* Calling it later adds to the probability of excess memory */ /* retention. */ ! /* This is a no-op if the collector has recognition of */ /* arbitrary interior pointers enabled, which is now the default. */ GC_API void GC_register_displacement GC_PROTO((GC_word n)); *************** GC_API size_t GC_get_free_bytes GC_PROTO *** 464,472 **** GC_API size_t GC_get_bytes_since_gc GC_PROTO((void)); /* Return the total number of bytes allocated in this process. */ ! /* Never decreases. */ GC_API size_t GC_get_total_bytes GC_PROTO((void)); /* Enable incremental/generational collection. */ /* Not advisable unless dirty bits are */ /* available or most heap objects are */ --- 399,416 ---- GC_API size_t GC_get_bytes_since_gc GC_PROTO((void)); /* Return the total number of bytes allocated in this process. */ ! /* Never decreases, except due to wrapping. */ GC_API size_t GC_get_total_bytes GC_PROTO((void)); + /* Disable garbage collection. Even GC_gcollect calls will be */ + /* ineffective. */ + GC_API void GC_disable GC_PROTO((void)); + + /* Reenable garbage collection. GC_disable() and GC_enable() calls */ + /* nest. Garbage collection is enabled if the number of calls to both */ + /* both functions is equal. */ + GC_API void GC_enable GC_PROTO((void)); + /* Enable incremental/generational collection. */ /* Not advisable unless dirty bits are */ /* available or most heap objects are */ *************** GC_API size_t GC_get_total_bytes GC_PROT *** 474,480 **** /* Don't use in leak finding mode. */ /* Ignored if GC_dont_gc is true. */ /* Only the generational piece of this is */ ! /* functional if GC_parallel is TRUE. */ GC_API void GC_enable_incremental GC_PROTO((void)); /* Does incremental mode write-protect pages? Returns zero or */ --- 418,428 ---- /* Don't use in leak finding mode. */ /* Ignored if GC_dont_gc is true. */ /* Only the generational piece of this is */ ! /* functional if GC_parallel is TRUE */ ! /* or if GC_time_limit is GC_TIME_UNLIMITED. */ ! /* Causes GC_local_gcj_malloc() to revert to */ ! /* locked allocation. Must be called */ ! /* before any GC_local_gcj_malloc() calls. */ GC_API void GC_enable_incremental GC_PROTO((void)); /* Does incremental mode write-protect pages? Returns zero or */ *************** GC_API GC_PTR GC_malloc_atomic_ignore_of *** 518,523 **** --- 466,507 ---- # define GC_RETURN_ADDR (GC_word)__return_address #endif + #ifdef __linux__ + # include + # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \ + && !defined(__ia64__) + # define GC_HAVE_BUILTIN_BACKTRACE + # define GC_CAN_SAVE_CALL_STACKS + # endif + # if defined(__i386__) || defined(__x86_64__) + # define GC_CAN_SAVE_CALL_STACKS + # endif + #endif + + #if defined(__sparc__) + # define GC_CAN_SAVE_CALL_STACKS + #endif + + /* If we're on an a platform on which we can't save call stacks, but */ + /* gcc is normally used, we go ahead and define GC_ADD_CALLER. */ + /* We make this decision independent of whether gcc is actually being */ + /* used, in order to keep the interface consistent, and allow mixing */ + /* of compilers. */ + /* 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(GC_CAN_SAVE_CALL_STACKS) + # define GC_ADD_CALLER + # if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) + /* gcc knows how to retrieve return address, but we don't know */ + /* how to generate call stacks. */ + # define GC_RETURN_ADDR (GC_word)__builtin_return_address(0) + # else + /* Just pass 0 for gcc compatibility. */ + # define GC_RETURN_ADDR 0 + # endif + #endif + #ifdef GC_ADD_CALLER # define GC_EXTRAS GC_RETURN_ADDR, __FILE__, __LINE__ # define GC_EXTRA_PARAMS GC_word ra, GC_CONST char * s, int i *************** GC_API GC_PTR GC_debug_malloc_uncollecta *** 536,553 **** GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS)); GC_API GC_PTR GC_debug_malloc_stubborn GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS)); GC_API void GC_debug_free GC_PROTO((GC_PTR object_addr)); GC_API GC_PTR GC_debug_realloc GC_PROTO((GC_PTR old_object, size_t new_size_in_bytes, GC_EXTRA_PARAMS)); - GC_API void GC_debug_change_stubborn GC_PROTO((GC_PTR)); GC_API void GC_debug_end_stubborn_change GC_PROTO((GC_PTR)); # ifdef GC_DEBUG # define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS) # define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS) ! # define GC_MALLOC_UNCOLLECTABLE(sz) GC_debug_malloc_uncollectable(sz, \ ! GC_EXTRAS) # define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS) # define GC_FREE(p) GC_debug_free(p) # define GC_REGISTER_FINALIZER(p, f, d, of, od) \ --- 520,561 ---- GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS)); GC_API GC_PTR GC_debug_malloc_stubborn GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS)); + GC_API GC_PTR GC_debug_malloc_ignore_off_page + GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS)); + GC_API GC_PTR GC_debug_malloc_atomic_ignore_off_page + GC_PROTO((size_t size_in_bytes, GC_EXTRA_PARAMS)); GC_API void GC_debug_free GC_PROTO((GC_PTR object_addr)); GC_API GC_PTR GC_debug_realloc GC_PROTO((GC_PTR old_object, size_t new_size_in_bytes, GC_EXTRA_PARAMS)); GC_API void GC_debug_change_stubborn GC_PROTO((GC_PTR)); GC_API void GC_debug_end_stubborn_change GC_PROTO((GC_PTR)); + + /* Routines that allocate objects with debug information (like the */ + /* above), but just fill in dummy file and line number information. */ + /* Thus they can serve as drop-in malloc/realloc replacements. This */ + /* can be useful for two reasons: */ + /* 1) It allows the collector to be built with DBG_HDRS_ALL defined */ + /* even if some allocation calls come from 3rd party libraries */ + /* that can't be recompiled. */ + /* 2) On some platforms, the file and line information is redundant, */ + /* since it can be reconstructed from a stack trace. On such */ + /* platforms it may be more convenient not to recompile, e.g. for */ + /* leak detection. This can be accomplished by instructing the */ + /* linker to replace malloc/realloc with these. */ + GC_API GC_PTR GC_debug_malloc_replacement GC_PROTO((size_t size_in_bytes)); + GC_API GC_PTR GC_debug_realloc_replacement + GC_PROTO((GC_PTR object_addr, size_t size_in_bytes)); + # ifdef GC_DEBUG # define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS) # define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS) ! # define GC_MALLOC_UNCOLLECTABLE(sz) \ ! GC_debug_malloc_uncollectable(sz, GC_EXTRAS) ! # define GC_MALLOC_IGNORE_OFF_PAGE(sz) \ ! GC_debug_malloc_ignore_off_page(sz, GC_EXTRAS) ! # define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \ ! GC_debug_malloc_atomic_ignore_off_page(sz, GC_EXTRAS) # define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS) # define GC_FREE(p) GC_debug_free(p) # define GC_REGISTER_FINALIZER(p, f, d, of, od) \ *************** GC_API void GC_debug_end_stubborn_change *** 566,571 **** --- 574,583 ---- # define GC_MALLOC(sz) GC_malloc(sz) # define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz) # define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz) + # define GC_MALLOC_IGNORE_OFF_PAGE(sz) \ + GC_malloc_ignore_off_page(sz) + # define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \ + GC_malloc_atomic_ignore_off_page(sz) # define GC_REALLOC(old, sz) GC_realloc(old, sz) # define GC_FREE(p) GC_free(p) # define GC_REGISTER_FINALIZER(p, f, d, of, od) \ *************** GC_API void GC_debug_register_finalizer *** 644,650 **** /* itself. There is a stylistic argument that this is wrong, */ /* but it's unavoidable for C++, since the compiler may */ /* silently introduce these. It's also benign in that specific */ ! /* case. */ /* Note that cd will still be viewed as accessible, even if it */ /* refers to the object itself. */ GC_API void GC_register_finalizer_ignore_self --- 656,663 ---- /* itself. There is a stylistic argument that this is wrong, */ /* but it's unavoidable for C++, since the compiler may */ /* silently introduce these. It's also benign in that specific */ ! /* case. And it helps if finalizable objects are split to */ ! /* avoid cycles. */ /* Note that cd will still be viewed as accessible, even if it */ /* refers to the object itself. */ GC_API void GC_register_finalizer_ignore_self *************** GC_API int GC_unregister_disappearing_li *** 717,727 **** /* Undoes a registration by either of the above two */ /* routines. */ - /* Auxiliary fns to make finalization work correctly with displaced */ - /* pointers introduced by the debugging allocators. */ - GC_API GC_PTR GC_make_closure GC_PROTO((GC_finalization_proc fn, GC_PTR data)); - GC_API void GC_debug_invoke_finalizer GC_PROTO((GC_PTR obj, GC_PTR data)); - /* Returns !=0 if GC_invoke_finalizers has something to do. */ GC_API int GC_should_invoke_finalizers GC_PROTO((void)); --- 730,735 ---- *************** GC_API int GC_invoke_finalizers GC_PROTO *** 738,743 **** --- 746,755 ---- typedef void (*GC_warn_proc) GC_PROTO((char *msg, GC_word arg)); GC_API GC_warn_proc GC_set_warn_proc GC_PROTO((GC_warn_proc p)); /* Returns old warning procedure. */ + + GC_API GC_word GC_set_free_space_divisor GC_PROTO((GC_word value)); + /* Set free_space_divisor. See above for definition. */ + /* Returns old value. */ /* The following is intended to be used by a higher level */ /* (e.g. Java-like) finalization facility. It is expected */ *************** extern void GC_thr_init(); /* Needed for *** 873,886 **** #endif /* THREADS && !SRC_M3 */ ! #if defined(GC_WIN32_THREADS) # include /* * All threads must be created using GC_CreateThread, so that they will be ! * recorded in the thread table. */ ! HANDLE WINAPI GC_CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); --- 885,901 ---- #endif /* THREADS && !SRC_M3 */ ! #if defined(GC_WIN32_THREADS) && !defined(__CYGWIN32__) && !defined(__CYGWIN__) # include /* * All threads must be created using GC_CreateThread, so that they will be ! * recorded in the thread table. For backwards compatibility, this is not ! * technically true if the GC is built as a dynamic library, since it can ! * and does then use DllMain to keep track of thread creations. But new code ! * should be built to call GC_CreateThread. */ ! GC_API HANDLE WINAPI GC_CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); *************** extern void GC_thr_init(); /* Needed for *** 902,908 **** # endif # endif /* defined(_WIN32_WCE) */ ! #endif /* defined(GC_WIN32_THREADS) */ /* * If you are planning on putting --- 917,923 ---- # endif # endif /* defined(_WIN32_WCE) */ ! #endif /* defined(GC_WIN32_THREADS) && !cygwin */ /* * If you are planning on putting *************** extern void GC_thr_init(); /* Needed for *** 914,926 **** # define GC_INIT() { extern end, etext; \ GC_noop(&end, &etext); } #else ! # if (defined(__CYGWIN32__) && defined(GC_USE_DLL)) || defined (_AIX) /* ! * Similarly gnu-win32 DLLs need explicit initialization */ # define GC_INIT() { GC_add_roots(DATASTART, DATAEND); } # else # define GC_INIT() # endif #endif --- 929,946 ---- # define GC_INIT() { extern end, etext; \ GC_noop(&end, &etext); } #else ! # if defined(__CYGWIN32__) && defined(GC_DLL) || defined (_AIX) /* ! * Similarly gnu-win32 DLLs need explicit initialization from ! * the main program, as does AIX. */ # define GC_INIT() { GC_add_roots(DATASTART, DATAEND); } # else + # if defined(__APPLE__) && defined(__MACH__) + # define GC_INIT() { GC_init(); } + # else # define GC_INIT() + # endif # endif #endif diff -Nrc3pad gcc-3.3.3/boehm-gc/include/gc_local_alloc.h gcc-3.4.0/boehm-gc/include/gc_local_alloc.h *** gcc-3.3.3/boehm-gc/include/gc_local_alloc.h 2001-08-17 18:30:50.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/gc_local_alloc.h 2003-07-28 04:18:23.000000000 +0000 *************** *** 33,38 **** --- 33,41 ---- * -DTHREAD_LOCAL_ALLOC, which is currently supported only on Linux. * * The debugging allocators use standard, not thread-local allocation. + * + * These routines normally require an explicit call to GC_init(), though + * that may be done from a constructor function. */ #ifndef GC_LOCAL_ALLOC_H diff -Nrc3pad gcc-3.3.3/boehm-gc/include/gc_mark.h gcc-3.4.0/boehm-gc/include/gc_mark.h *** gcc-3.3.3/boehm-gc/include/gc_mark.h 2001-08-17 18:30:50.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/gc_mark.h 2003-07-28 04:18:23.000000000 +0000 *************** extern GC_PTR GC_greatest_plausible_heap *** 129,135 **** /* be reserved for exceptional cases. That will ensure that */ /* performance of this call is not extremely performance critical. */ /* (Otherwise we would need to inline GC_mark_and_push completely, */ ! /* which would tie the client code to a fixed colllector version.) */ struct GC_ms_entry *GC_mark_and_push GC_PROTO((GC_PTR obj, struct GC_ms_entry * mark_stack_ptr, --- 129,137 ---- /* be reserved for exceptional cases. That will ensure that */ /* performance of this call is not extremely performance critical. */ /* (Otherwise we would need to inline GC_mark_and_push completely, */ ! /* which would tie the client code to a fixed collector version.) */ ! /* Note that mark procedures should explicitly call FIXUP_POINTER() */ ! /* if required. */ struct GC_ms_entry *GC_mark_and_push GC_PROTO((GC_PTR obj, struct GC_ms_entry * mark_stack_ptr, diff -Nrc3pad gcc-3.3.3/boehm-gc/include/gc_pthread_redirects.h gcc-3.4.0/boehm-gc/include/gc_pthread_redirects.h *** gcc-3.3.3/boehm-gc/include/gc_pthread_redirects.h 2001-10-17 04:55:28.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/gc_pthread_redirects.h 2003-07-28 04:18:23.000000000 +0000 *************** *** 52,66 **** int GC_pthread_create(pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset); int GC_pthread_join(pthread_t thread, void **retval); int GC_pthread_detach(pthread_t thread); # define pthread_create GC_pthread_create - # define pthread_sigmask GC_pthread_sigmask # define pthread_join GC_pthread_join # define pthread_detach GC_pthread_detach # define dlopen GC_dlopen #endif /* GC_xxxxx_THREADS */ --- 52,81 ---- int GC_pthread_create(pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); + #ifndef GC_DARWIN_THREADS int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset); + #endif int GC_pthread_join(pthread_t thread, void **retval); int GC_pthread_detach(pthread_t thread); + #if defined(GC_OSF1_THREADS) \ + && defined(_PTHREAD_USE_MANGLED_NAMES_) && !defined(_PTHREAD_USE_PTDNAM_) + /* Unless the compiler supports #pragma extern_prefix, the Tru64 UNIX + redefines some POSIX thread functions to use mangled names. + If so, undef them before redefining. */ + # undef pthread_create + # undef pthread_join + # undef pthread_detach + #endif + # define pthread_create GC_pthread_create # define pthread_join GC_pthread_join # define pthread_detach GC_pthread_detach + + #ifndef GC_DARWIN_THREADS + # define pthread_sigmask GC_pthread_sigmask # define dlopen GC_dlopen + #endif #endif /* GC_xxxxx_THREADS */ diff -Nrc3pad gcc-3.3.3/boehm-gc/include/gc_typed.h gcc-3.4.0/boehm-gc/include/gc_typed.h *** gcc-3.3.3/boehm-gc/include/gc_typed.h 2001-08-17 18:30:50.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/gc_typed.h 2003-07-28 04:18:23.000000000 +0000 *************** *** 29,42 **** # include "gc.h" # endif typedef GC_word * GC_bitmap; /* The least significant bit of the first word is one if */ /* the first word in the object may be a pointer. */ # define GC_get_bit(bm, index) \ ! (((bm)[divWORDSZ(index)] >> modWORDSZ(index)) & 1) # define GC_set_bit(bm, index) \ ! (bm)[divWORDSZ(index)] |= (word)1 << modWORDSZ(index) typedef GC_word GC_descr; --- 29,49 ---- # include "gc.h" # endif + #ifdef __cplusplus + extern "C" { + #endif typedef GC_word * GC_bitmap; /* The least significant bit of the first word is one if */ /* the first word in the object may be a pointer. */ + # define GC_WORDSZ (8*sizeof(GC_word)) # define GC_get_bit(bm, index) \ ! (((bm)[index/GC_WORDSZ] >> (index%GC_WORDSZ)) & 1) # define GC_set_bit(bm, index) \ ! (bm)[index/GC_WORDSZ] |= ((GC_word)1 << (index%GC_WORDSZ)) ! # define GC_WORD_OFFSET(t, f) (offsetof(t,f)/sizeof(GC_word)) ! # define GC_WORD_LEN(t) (sizeof(t)/ sizeof(GC_word)) ! # define GC_BITMAP_SIZE(t) ((GC_WORD_LEN(t) + GC_WORDSZ-1)/GC_WORDSZ) typedef GC_word GC_descr; *************** GC_API GC_descr GC_make_descriptor GC_PR *** 57,62 **** --- 64,79 ---- /* is intended to be called once per type, not once */ /* per allocation. */ + /* It is possible to generate a descriptor for a C type T with */ + /* word aligned pointer fields f1, f2, ... as follows: */ + /* */ + /* GC_descr T_descr; */ + /* GC_word T_bitmap[GC_BITMAP_SIZE(T)] = {0}; */ + /* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f1)); */ + /* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f2)); */ + /* ... */ + /* T_descr = GC_make_descriptor(T_bitmap, GC_WORD_LEN(T)); */ + GC_API GC_PTR GC_malloc_explicitly_typed GC_PROTO((size_t size_in_bytes, GC_descr d)); /* Allocate an object whose layout is described by d. */ *************** GC_API GC_PTR GC_calloc_explicitly_typed *** 79,93 **** /* Returned object is cleared. */ #ifdef GC_DEBUG ! # define GC_MALLOC_EXPLICTLY_TYPED(bytes, d) GC_MALLOC(bytes) ! # define GC_CALLOC_EXPLICTLY_TYPED(n, bytes, d) GC_MALLOC(n*bytes) #else ! # define GC_MALLOC_EXPLICTLY_TYPED(bytes, d) \ GC_malloc_explicitly_typed(bytes, d) ! # define GC_CALLOC_EXPLICTLY_TYPED(n, bytes, d) \ GC_calloc_explicitly_typed(n, bytes, d) #endif /* !GC_DEBUG */ #endif /* _GC_TYPED_H */ --- 96,113 ---- /* Returned object is cleared. */ #ifdef GC_DEBUG ! # define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) GC_MALLOC(bytes) ! # define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) GC_MALLOC(n*bytes) #else ! # define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \ GC_malloc_explicitly_typed(bytes, d) ! # define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \ GC_calloc_explicitly_typed(n, bytes, d) #endif /* !GC_DEBUG */ + #ifdef __cplusplus + } /* matches extern "C" */ + #endif #endif /* _GC_TYPED_H */ diff -Nrc3pad gcc-3.3.3/boehm-gc/include/Makefile.in gcc-3.4.0/boehm-gc/include/Makefile.in *** gcc-3.3.3/boehm-gc/include/Makefile.in 2002-12-31 17:52:45.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/Makefile.in 2003-07-28 04:18:22.000000000 +0000 *************** *** 1,6 **** ! # Makefile.in generated automatically by automake 1.4 from Makefile.am ! # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in 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. --- 1,6 ---- ! # Makefile.in generated automatically by automake 1.4-p5 from Makefile.am ! # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in 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. *************** target_triplet = @target@ *** 66,74 **** --- 66,76 ---- AR = @AR@ AS = @AS@ CC = @CC@ + CFLAGS = @CFLAGS@ CPP = @CPP@ CXX = @CXX@ CXXCPP = @CXXCPP@ + CXXFLAGS = @CXXFLAGS@ CXXINCLUDES = @CXXINCLUDES@ DLLTOOL = @DLLTOOL@ EXEEXT = @EXEEXT@ *************** RANLIB = @RANLIB@ *** 89,98 **** --- 91,105 ---- STRIP = @STRIP@ THREADLIBS = @THREADLIBS@ VERSION = @VERSION@ + addincludes = @addincludes@ + addlibs = @addlibs@ addobjs = @addobjs@ + addtests = @addtests@ gc_basedir = @gc_basedir@ mkinstalldirs = @mkinstalldirs@ target_all = @target_all@ + toolexecdir = @toolexecdir@ + toolexeclibdir = @toolexeclibdir@ AUTOMAKE_OPTIONS = foreign diff -Nrc3pad gcc-3.3.3/boehm-gc/include/new_gc_alloc.h gcc-3.4.0/boehm-gc/include/new_gc_alloc.h *** gcc-3.3.3/boehm-gc/include/new_gc_alloc.h 2001-10-16 09:01:38.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/new_gc_alloc.h 2003-07-28 04:18:23.000000000 +0000 *************** *** 64,69 **** --- 64,77 ---- #endif #endif + /* A hack to deal with gcc 3.1. If you are using gcc3.1 and later, */ + /* you should probably really use gc_allocator.h instead. */ + #if defined (__GNUC__) && \ + (__GNUC > 3 || (__GNUC__ == 3 && (__GNUC_MINOR__ >= 1))) + # define simple_alloc __simple_alloc + #endif + + #define GC_ALLOC_H diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/darwin_semaphore.h gcc-3.4.0/boehm-gc/include/private/darwin_semaphore.h *** gcc-3.3.3/boehm-gc/include/private/darwin_semaphore.h 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/darwin_semaphore.h 2003-07-28 03:46:18.000000000 +0000 *************** *** 0 **** --- 1,68 ---- + #ifndef GC_DARWIN_SEMAPHORE_H + #define GC_DARWIN_SEMAPHORE_H + + #if !defined(GC_DARWIN_THREADS) + #error darwin_semaphore.h included with GC_DARWIN_THREADS not defined + #endif + + /* + This is a very simple semaphore implementation for darwin. It + is implemented in terms of pthreads calls so it isn't async signal + safe. This isn't a problem because signals aren't used to + suspend threads on darwin. + */ + + typedef struct { + pthread_mutex_t mutex; + pthread_cond_t cond; + int value; + } sem_t; + + static int sem_init(sem_t *sem, int pshared, int value) { + int ret; + if(pshared) + GC_abort("sem_init with pshared set"); + sem->value = value; + + ret = pthread_mutex_init(&sem->mutex,NULL); + if(ret < 0) return -1; + ret = pthread_cond_init(&sem->cond,NULL); + if(ret < 0) return -1; + return 0; + } + + static int sem_post(sem_t *sem) { + if(pthread_mutex_lock(&sem->mutex) < 0) + return -1; + sem->value++; + if(pthread_cond_signal(&sem->cond) < 0) { + pthread_mutex_unlock(&sem->mutex); + return -1; + } + if(pthread_mutex_unlock(&sem->mutex) < 0) + return -1; + return 0; + } + + static int sem_wait(sem_t *sem) { + if(pthread_mutex_lock(&sem->mutex) < 0) + return -1; + while(sem->value == 0) { + pthread_cond_wait(&sem->cond,&sem->mutex); + } + sem->value--; + if(pthread_mutex_unlock(&sem->mutex) < 0) + return -1; + return 0; + } + + static int sem_destroy(sem_t *sem) { + int ret; + ret = pthread_cond_destroy(&sem->cond); + if(ret < 0) return -1; + ret = pthread_mutex_destroy(&sem->mutex); + if(ret < 0) return -1; + return 0; + } + + #endif diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/darwin_stop_world.h gcc-3.4.0/boehm-gc/include/private/darwin_stop_world.h *** gcc-3.3.3/boehm-gc/include/private/darwin_stop_world.h 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/darwin_stop_world.h 2003-07-28 03:46:18.000000000 +0000 *************** *** 0 **** --- 1,15 ---- + #ifndef GC_DARWIN_STOP_WORLD_H + #define GC_DARWIN_STOP_WORLD_H + + #if !defined(GC_DARWIN_THREADS) + #error darwin_stop_world.h included without GC_DARWIN_THREADS defined + #endif + + #include + #include + + struct thread_stop_info { + mach_port_t mach_thread; + }; + + #endif diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/dbg_mlc.h gcc-3.4.0/boehm-gc/include/private/dbg_mlc.h *** gcc-3.3.3/boehm-gc/include/private/dbg_mlc.h 2002-02-12 04:37:57.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/dbg_mlc.h 2003-07-28 04:18:23.000000000 +0000 *************** typedef struct { *** 115,130 **** #ifdef SHORT_DBG_HDRS # define DEBUG_BYTES (sizeof (oh)) #else /* Add space for END_FLAG, but use any extra space that was already */ /* added to catch off-the-end pointers. */ ! # define DEBUG_BYTES (sizeof (oh) + sizeof (word) - EXTRA_BYTES) #endif #define USR_PTR_FROM_BASE(p) ((ptr_t)(p) + sizeof(oh)) /* Round bytes to words without adding extra byte at end. */ #define SIMPLE_ROUNDED_UP_WORDS(n) BYTES_TO_WORDS((n) + WORDS_TO_BYTES(1) - 1) #ifdef SAVE_CALL_CHAIN # define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci) # define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci) --- 115,138 ---- #ifdef SHORT_DBG_HDRS # define DEBUG_BYTES (sizeof (oh)) + # define UNCOLLECTABLE_DEBUG_BYTES DEBUG_BYTES #else /* Add space for END_FLAG, but use any extra space that was already */ /* added to catch off-the-end pointers. */ ! /* For uncollectable objects, the extra byte is not added. */ ! # define UNCOLLECTABLE_DEBUG_BYTES (sizeof (oh) + sizeof (word)) ! # define DEBUG_BYTES (UNCOLLECTABLE_DEBUG_BYTES - EXTRA_BYTES) #endif #define USR_PTR_FROM_BASE(p) ((ptr_t)(p) + sizeof(oh)) /* Round bytes to words without adding extra byte at end. */ #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. */ + /* PRINT_CALL_CHAIN prints the call chain stored in an object */ + /* to stderr. It requires that we do not hold the lock. */ #ifdef SAVE_CALL_CHAIN # define ADD_CALL_CHAIN(base, ra) GC_save_callers(((oh *)(base)) -> oh_ci) # define PRINT_CALL_CHAIN(base) GC_print_callers(((oh *)(base)) -> oh_ci) diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/gcconfig.h gcc-3.4.0/boehm-gc/include/private/gcconfig.h *** gcc-3.3.3/boehm-gc/include/private/gcconfig.h 2003-04-10 00:08:01.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/gcconfig.h 2004-01-20 15:15:49.000000000 +0000 *************** *** 13,23 **** --- 13,37 ---- * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. */ + + /* + * This header is private to the gc. It is almost always included from + * gc_priv.h. However it is possible to include it by itself if just the + * configuration macros are needed. In that + * case, a few declarations relying on types declared in gc_priv.h will be + * omitted. + */ #ifndef GCCONFIG_H # define GCCONFIG_H + # ifndef GC_PRIVATE_H + /* Fake ptr_t declaration, just to avoid compilation errors. */ + /* This avoids many instances if "ifndef GC_PRIVATE_H" below. */ + typedef struct GC_undefined_struct * ptr_t; + # endif + /* Machine dependent parameters. Some tuning parameters can be found */ /* near the top of gc_private.h. */ *************** *** 25,31 **** --- 39,47 ---- /* First a unified test for Linux: */ # if defined(linux) || defined(__linux__) + # ifndef LINUX # define LINUX + # endif # endif /* And one for NetBSD: */ *************** *** 46,52 **** /* Determine the machine type: */ # if defined(__arm__) || defined(__thumb__) # define ARM32 ! # if !defined(LINUX) # define NOSYS # define mach_type_known # endif --- 62,68 ---- /* Determine the machine type: */ # if defined(__arm__) || defined(__thumb__) # define ARM32 ! # if !defined(LINUX) && !defined(NETBSD) # define NOSYS # define mach_type_known # endif *************** *** 69,75 **** # define SPARC # define mach_type_known # endif ! # if defined(NETBSD) && defined(m68k) # define M68K # define mach_type_known # endif --- 85,91 ---- # define SPARC # define mach_type_known # endif ! # if defined(NETBSD) && (defined(m68k) || defined(__m68k__)) # define M68K # define mach_type_known # endif *************** *** 77,83 **** # define POWERPC # define mach_type_known # endif ! # if defined(NETBSD) && defined(__arm32__) # define ARM32 # define mach_type_known # endif --- 93,99 ---- # define POWERPC # define mach_type_known # endif ! # if defined(NETBSD) && (defined(__arm32__) || defined(__arm__)) # define ARM32 # define mach_type_known # endif *************** *** 90,95 **** --- 106,115 ---- # endif # define mach_type_known # endif + # if defined(__NetBSD__) && defined(__vax__) + # define VAX + # define mach_type_known + # endif # if defined(mips) || defined(__mips) || defined(_mips) # define MIPS # if defined(nec_ews) || defined(_nec_ews) *************** *** 109,114 **** --- 129,141 ---- # endif /* !LINUX */ # define mach_type_known # endif + # if defined(DGUX) && (defined(i386) || defined(__i386__)) + # define I386 + # ifndef _USING_DGUX + # define _USING_DGUX + # endif + # define mach_type_known + # endif # if defined(sequent) && (defined(i386) || defined(__i386__)) # define I386 # define SEQUENT *************** *** 198,204 **** # define IA64 # define mach_type_known # endif ! # if defined(LINUX) && (defined(powerpc) || defined(__powerpc__)) # define POWERPC # define mach_type_known # endif --- 225,235 ---- # define IA64 # define mach_type_known # endif ! # if defined(LINUX) && defined(__arm__) ! # define ARM32 ! # define mach_type_known ! # endif ! # if defined(LINUX) && (defined(powerpc) || defined(__powerpc__) || defined(powerpc64) || defined(__powerpc64__)) # define POWERPC # define mach_type_known # endif *************** *** 237,255 **** # define MACOS # define mach_type_known # endif ! # if defined(__MWERKS__) && defined(__powerc) # define POWERPC # define MACOS # define mach_type_known # endif # if defined(macosx) || \ defined(__APPLE__) && defined(__MACH__) && defined(__ppc__) ! # define MACOSX # define POWERPC # define mach_type_known # endif # if defined(__APPLE__) && defined(__MACH__) && defined(__i386__) ! # define MACOSX # define I386 --> Not really supported, but at least we recognize it. # endif --- 268,286 ---- # define MACOS # define mach_type_known # endif ! # if defined(__MWERKS__) && defined(__powerc) && !defined(__MACH__) # define POWERPC # define MACOS # define mach_type_known # endif # if defined(macosx) || \ defined(__APPLE__) && defined(__MACH__) && defined(__ppc__) ! # define DARWIN # define POWERPC # define mach_type_known # endif # if defined(__APPLE__) && defined(__MACH__) && defined(__i386__) ! # define DARWIN # define I386 --> Not really supported, but at least we recognize it. # endif *************** *** 291,297 **** # define CX_UX # define mach_type_known # endif ! # if defined(DGUX) # define M88K /* DGUX defined */ # define mach_type_known --- 322,328 ---- # define CX_UX # define mach_type_known # endif ! # if defined(DGUX) && defined(m88k) # define M88K /* DGUX defined */ # define mach_type_known *************** *** 419,435 **** /* (CX_UX and DGUX) */ /* S370 ==> 370-like machine */ /* running Amdahl UTS4 */ ! /* S390 ==> 390-like machine */ ! /* running LINUX */ /* ARM32 ==> Intel StrongARM */ /* IA64 ==> Intel IPF */ /* (e.g. Itanium) */ /* (LINUX and HPUX) */ - /* IA64_32 ==> IA64 w/32 bit ABI */ - /* (HPUX) */ /* SH ==> Hitachi SuperH */ /* (LINUX & MSWINCE) */ /* X86_64 ==> AMD x86-64 */ /* --- 450,467 ---- /* (CX_UX and DGUX) */ /* S370 ==> 370-like machine */ /* running Amdahl UTS4 */ ! /* S390 ==> 390-like machine */ ! /* running LINUX */ /* ARM32 ==> Intel StrongARM */ /* IA64 ==> Intel IPF */ /* (e.g. Itanium) */ /* (LINUX and HPUX) */ /* SH ==> Hitachi SuperH */ /* (LINUX & MSWINCE) */ /* X86_64 ==> AMD x86-64 */ + /* POWERPC ==> IBM/Apple PowerPC */ + /* (MACOS(<=9),DARWIN(incl.MACOSX),*/ + /* LINUX, NETBSD, NOSYS variants) */ /* *************** *** 450,456 **** * defining it to be 1 will always work, but perform poorly. * * DATASTART is the beginning of the data segment. ! * On UNIX systems, the collector will scan the area between DATASTART * and DATAEND for root pointers. * * DATAEND, if not `end' where `end' is defined as ``extern int end[];''. --- 482,493 ---- * defining it to be 1 will always work, but perform poorly. * * DATASTART is the beginning of the data segment. ! * On some platforms SEARCH_FOR_DATA_START is defined. ! * SEARCH_FOR_DATASTART will cause GC_data_start to ! * be set to an address determined by accessing data backwards from _end ! * until an unmapped page is found. DATASTART will be defined to be ! * GC_data_start. ! * On UNIX-like systems, the collector will scan the area between DATASTART * and DATAEND for root pointers. * * DATAEND, if not `end' where `end' is defined as ``extern int end[];''. *************** *** 470,477 **** --- 507,519 ---- * 1) define STACK_GROWS_UP if the stack grows toward higher addresses, and * 2) define exactly one of * STACKBOTTOM (should be defined to be an expression) + * LINUX_STACKBOTTOM * HEURISTIC1 * HEURISTIC2 + * If STACKBOTTOM is defined, then it's 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, and if that fails read it from /proc. * If either of the last two macros are defined, then STACKBOTTOM is computed * during collector startup using one of the following two heuristics: * HEURISTIC1: Take an address inside GC_init's frame, and round it up to *************** *** 536,541 **** --- 578,586 ---- * 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, * word stores of 0 are used instead. + * + * HEAP_START may be defined as the initial address hint for mmap-based + * allocation. */ /* If we are using a recent version of gcc, we can use __builtin_unwind_init() *************** *** 560,577 **** # ifdef NETBSD # define OS_TYPE "NETBSD" # define HEURISTIC2 ! extern char etext[]; ! # define DATASTART ((ptr_t)(etext)) # endif # ifdef LINUX # define OS_TYPE "LINUX" # define STACKBOTTOM ((ptr_t)0xf0000000) /* # define MPROTECT_VDB - Reported to not work 9/17/01 */ # ifdef __ELF__ # define DYNAMIC_LOADING # include # if defined(__GLIBC__)&& __GLIBC__>=2 ! # define LINUX_DATA_START # else /* !GLIBC2 */ extern char **__environ; # define DATASTART ((ptr_t)(&__environ)) --- 605,630 ---- # ifdef NETBSD # define OS_TYPE "NETBSD" # define HEURISTIC2 ! # ifdef __ELF__ ! # define DATASTART GC_data_start ! # define DYNAMIC_LOADING ! # else ! extern char etext[]; ! # define DATASTART ((ptr_t)(etext)) ! # endif # endif # ifdef LINUX # define OS_TYPE "LINUX" # define STACKBOTTOM ((ptr_t)0xf0000000) + # define USE_MMAP + # define USE_GENERIC_PUSH_REGS + /* We never got around to the assembly version. */ /* # define MPROTECT_VDB - Reported to not work 9/17/01 */ # ifdef __ELF__ # define DYNAMIC_LOADING # include # if defined(__GLIBC__)&& __GLIBC__>=2 ! # define SEARCH_FOR_DATA_START # else /* !GLIBC2 */ extern char **__environ; # define DATASTART ((ptr_t)(&__environ)) *************** *** 666,691 **** # define DATAEND /* not needed */ # endif # ifdef LINUX ! # define ALIGNMENT 4 /* Guess. Can someone verify? */ ! /* This was 2, but that didn't sound right. */ # define OS_TYPE "LINUX" ! # define DYNAMIC_LOADING # define LINUX_STACKBOTTOM ! /* Stack usually starts at 0x80000000 */ ! # define LINUX_DATA_START extern int _end[]; # define DATAEND (_end) # endif ! # ifdef MACOSX ! /* There are reasons to suspect this may not be reliable. */ # define ALIGNMENT 4 ! # define OS_TYPE "MACOSX" # define DATASTART ((ptr_t) get_etext()) # define STACKBOTTOM ((ptr_t) 0xc0000000) ! # define DATAEND /* not needed */ ! # undef MPROTECT_VDB # include # define GETPAGESIZE() getpagesize() # endif # ifdef NETBSD # define ALIGNMENT 4 --- 719,766 ---- # define DATAEND /* not needed */ # endif # ifdef LINUX ! # if (defined (powerpc64) || defined(__powerpc64__)) ! # define ALIGNMENT 8 ! # define CPP_WORDSZ 64 ! # else ! # define ALIGNMENT 4 ! # endif # define OS_TYPE "LINUX" ! /* HEURISTIC1 has been reliably reported to fail for a 32-bit */ ! /* executable on a 64 bit kernel. */ # define LINUX_STACKBOTTOM ! # define DYNAMIC_LOADING ! # define SEARCH_FOR_DATA_START extern int _end[]; # define DATAEND (_end) # endif ! # ifdef DARWIN # define ALIGNMENT 4 ! # define OS_TYPE "DARWIN" ! # define DYNAMIC_LOADING ! /* 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 USE_MMAP ! # define USE_MMAP_ANON ! # define USE_ASM_PUSH_REGS ! /* This is potentially buggy. It needs more testing. See the comments in ! os_dep.c */ ! # define MPROTECT_VDB # include # define GETPAGESIZE() 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) \ + __asm__ __volatile__ ("dcbtst 0,%0" : : "r" ((const void *) (x))) + # endif + /* There seems to be some issues with trylock hanging on darwin. This + should be looked into some more */ + # define NO_PTHREAD_TRYLOCK # endif # ifdef NETBSD # define ALIGNMENT 4 *************** *** 746,753 **** # define OS_TYPE "SUNOS5" extern int _etext[]; extern int _end[]; ! extern char * GC_SysVGetDataStart(); ! # define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, _etext) # define DATAEND (_end) # if !defined(USE_MMAP) && defined(REDIRECT_MALLOC) # define USE_MMAP --- 821,828 ---- # define OS_TYPE "SUNOS5" extern int _etext[]; extern int _end[]; ! extern ptr_t GC_SysVGetDataStart(); ! # define DATASTART GC_SysVGetDataStart(0x10000, _etext) # define DATAEND (_end) # if !defined(USE_MMAP) && defined(REDIRECT_MALLOC) # define USE_MMAP *************** *** 801,809 **** # endif # ifdef DRSNX # define OS_TYPE "DRSNX" ! extern char * GC_SysVGetDataStart(); extern int etext[]; ! # define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, etext) # define MPROTECT_VDB # define STACKBOTTOM ((ptr_t) 0xdfff0000) # define DYNAMIC_LOADING --- 876,884 ---- # endif # ifdef DRSNX # define OS_TYPE "DRSNX" ! extern ptr_t GC_SysVGetDataStart(); extern int etext[]; ! # define DATASTART GC_SysVGetDataStart(0x10000, etext) # define MPROTECT_VDB # define STACKBOTTOM ((ptr_t) 0xdfff0000) # define DYNAMIC_LOADING *************** *** 819,831 **** extern int _etext[]; # define DATAEND (_end) # define SVR4 # ifdef __arch64__ /* libc_stack_end is not set reliably for sparc64 */ ! # define STACKBOTTOM ((ptr_t) 0x80000000000) ! # define DATASTART (ptr_t)GC_SysVGetDataStart(0x100000, _etext) # else ! # define LINUX_STACKBOTTOM ! # define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, _etext) # endif # endif # ifdef OPENBSD --- 894,907 ---- extern int _etext[]; # define DATAEND (_end) # define SVR4 + extern ptr_t GC_SysVGetDataStart(); # ifdef __arch64__ + # define DATASTART GC_SysVGetDataStart(0x100000, _etext) /* libc_stack_end is not set reliably for sparc64 */ ! # define STACKBOTTOM ((ptr_t) 0x80000000000ULL) # else ! # define DATASTART GC_SysVGetDataStart(0x10000, _etext) ! # define LINUX_STACKBOTTOM # endif # endif # ifdef OPENBSD *************** *** 876,882 **** # ifdef SUNOS5 # define OS_TYPE "SUNOS5" extern int _etext[], _end[]; ! extern char * GC_SysVGetDataStart(); # define DATASTART GC_SysVGetDataStart(0x1000, _etext) # define DATAEND (_end) /* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */ --- 952,958 ---- # ifdef SUNOS5 # define OS_TYPE "SUNOS5" extern int _etext[], _end[]; ! extern ptr_t GC_SysVGetDataStart(); # define DATASTART GC_SysVGetDataStart(0x1000, _etext) # define DATAEND (_end) /* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */ *************** *** 921,926 **** --- 997,1024 ---- # define DYNAMIC_LOADING # define ELF_CLASS ELFCLASS32 # endif + # ifdef DGUX + # define OS_TYPE "DGUX" + extern int _etext, _end; + extern ptr_t GC_SysVGetDataStart(); + # define DATASTART GC_SysVGetDataStart(0x1000, &_etext) + # define DATAEND (&_end) + # define STACK_GROWS_DOWN + # define HEURISTIC2 + # include + # define GETPAGESIZE() sysconf(_SC_PAGESIZE) + # define DYNAMIC_LOADING + # ifndef USE_MMAP + # define USE_MMAP + # endif /* USE_MMAP */ + # define MAP_FAILED (void *) -1 + # ifdef USE_MMAP + # define HEAP_START (ptr_t)0x40000000 + # else /* USE_MMAP */ + # define HEAP_START DATAEND + # endif /* USE_MMAP */ + # endif /* DGUX */ + # ifdef LINUX # ifndef __GNUC__ /* The Intel compiler doesn't like inline assembly */ *************** *** 944,949 **** --- 1042,1050 ---- /* possibly because Linux threads is itself a malloc client */ /* and can't deal with the signals. */ # endif + # define HEAP_START 0x1000 + /* This encourages mmap to give us low addresses, */ + /* thus allowing the heap to grow to ~3GB */ # ifdef __ELF__ # define DYNAMIC_LOADING # ifdef UNDEFINED /* includes ro data */ *************** *** 952,958 **** # endif # include # if defined(__GLIBC__) && __GLIBC__ >= 2 ! # define LINUX_DATA_START # else extern char **__environ; # define DATASTART ((ptr_t)(&__environ)) --- 1053,1059 ---- # endif # include # if defined(__GLIBC__) && __GLIBC__ >= 2 ! # define SEARCH_FOR_DATA_START # else extern char **__environ; # define DATASTART ((ptr_t)(&__environ)) *************** *** 1006,1013 **** --- 1107,1118 ---- /* DATAEND = _data_end__ */ /* To get it right for both, we take the */ /* minumum/maximum of the two. */ + # ifndef MAX # define MAX(x,y) ((x) > (y) ? (x) : (y)) + # endif + # ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) + # endif # define DATASTART ((ptr_t) MIN(_data_start__, _bss_start__)) # define DATAEND ((ptr_t) MAX(_data_end__, _bss_end__)) # undef STACK_GRAN *************** *** 1061,1076 **** # ifdef __ELF__ # define DYNAMIC_LOADING # endif - /* Handle unmapped hole i386*-*-freebsd[45]* may put between etext and edata. */ extern char etext[]; ! extern char edata[]; ! extern char end[]; ! # define NEED_FIND_LIMIT ! # define DATASTART ((ptr_t)(etext)) ! # define MIN(x,y) ((x) < (y) ? (x) : (y)) ! # define DATAEND (MIN (GC_find_limit (DATASTART, TRUE), DATASTART2)) ! # define DATASTART2 ((ptr_t)(edata)) ! # define DATAEND2 ((ptr_t)(end)) # endif # ifdef NETBSD # define OS_TYPE "NETBSD" --- 1166,1174 ---- # ifdef __ELF__ # define DYNAMIC_LOADING # endif extern char etext[]; ! extern char * GC_FreeBSDGetDataStart(); ! # define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext) # endif # ifdef NETBSD # define OS_TYPE "NETBSD" *************** *** 1149,1155 **** # define DATASTART ((ptr_t)(__data_start)) # define ALIGNMENT 4 # define USE_GENERIC_PUSH_REGS ! # define LINUX_STACKBOTTOM # endif /* Linux */ # ifdef EWS4800 # define HEURISTIC2 --- 1247,1257 ---- # define DATASTART ((ptr_t)(__data_start)) # define ALIGNMENT 4 # define USE_GENERIC_PUSH_REGS ! # if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 2 || __GLIBC__ > 2 ! # define LINUX_STACKBOTTOM ! # else ! # define STACKBOTTOM 0x80000000 ! # endif # endif /* Linux */ # ifdef EWS4800 # define HEURISTIC2 *************** *** 1203,1209 **** /* heap sections so they're not */ /* considered as roots. */ # define OS_TYPE "IRIX5" ! # define MPROTECT_VDB # ifdef _MIPS_SZPTR # define CPP_WORDSZ _MIPS_SZPTR # define ALIGNMENT (_MIPS_SZPTR/8) --- 1305,1312 ---- /* heap sections so they're not */ /* considered as roots. */ # define OS_TYPE "IRIX5" ! /*# define MPROTECT_VDB DOB: this should work, but there is evidence */ ! /* of recent breakage. */ # ifdef _MIPS_SZPTR # define CPP_WORDSZ _MIPS_SZPTR # define ALIGNMENT (_MIPS_SZPTR/8) *************** *** 1226,1253 **** # define ALIGNMENT 4 # define HEURISTIC2 # define USE_GENERIC_PUSH_REGS ! extern int _fdata[]; ! # define DATASTART ((ptr_t)(_fdata)) ! extern int _end[]; ! # define DATAEND ((ptr_t)(_end)) ! # define DYNAMIC_LOADING # endif # endif # ifdef RS6000 # define MACH_TYPE "RS6000" # ifdef __64BIT__ # define ALIGNMENT 8 # define CPP_WORDSZ 64 # else # define ALIGNMENT 4 # define CPP_WORDSZ 32 # endif extern int _data[], _end[]; # define DATASTART ((ptr_t)((ulong)_data)) # define DATAEND ((ptr_t)((ulong)_end)) extern int errno; - # define STACKBOTTOM ((ptr_t)((ulong)&errno)) # define USE_GENERIC_PUSH_REGS # define DYNAMIC_LOADING /* For really old versions of AIX, this may have to be removed. */ --- 1329,1374 ---- # define ALIGNMENT 4 # define HEURISTIC2 # define USE_GENERIC_PUSH_REGS ! # ifdef __ELF__ ! extern int etext[]; ! # define DATASTART GC_data_start ! # define NEED_FIND_LIMIT ! # define DYNAMIC_LOADING ! # else ! # define DATASTART ((ptr_t) 0x10000000) ! # define STACKBOTTOM ((ptr_t) 0x7ffff000) ! # endif /* _ELF_ */ # endif # endif # ifdef RS6000 # define MACH_TYPE "RS6000" + # ifdef ALIGNMENT + # undef ALIGNMENT + # endif + # ifdef IA64 + # undef IA64 /* DOB: some AIX installs stupidly define IA64 in /usr/include/sys/systemcfg.h */ + # endif # ifdef __64BIT__ # define ALIGNMENT 8 # define CPP_WORDSZ 64 + # define STACKBOTTOM ((ptr_t)0x1000000000000000) # else # define ALIGNMENT 4 # define CPP_WORDSZ 32 + # define STACKBOTTOM ((ptr_t)((ulong)&errno)) # endif + /* From AIX linker man page: + _text Specifies the first location of the program. + _etext Specifies the first location after the program. + _data Specifies the first location of the data. + _edata Specifies the first location after the initialized data + _end or end Specifies the first location after all data. + */ extern int _data[], _end[]; # define DATASTART ((ptr_t)((ulong)_data)) # define DATAEND ((ptr_t)((ulong)_end)) extern int errno; # define USE_GENERIC_PUSH_REGS # define DYNAMIC_LOADING /* For really old versions of AIX, this may have to be removed. */ *************** *** 1311,1325 **** # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM # define DYNAMIC_LOADING ! # define LINUX_DATA_START extern int _end[]; ! # define DATAEND (_end) # endif /* LINUX */ # endif /* HP_PA */ # ifdef ALPHA # define MACH_TYPE "ALPHA" # define ALIGNMENT 8 # ifdef NETBSD # define OS_TYPE "NETBSD" # define HEURISTIC2 --- 1432,1454 ---- # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM # define DYNAMIC_LOADING ! # define SEARCH_FOR_DATA_START extern int _end[]; ! # define DATAEND (&_end) # endif /* LINUX */ # endif /* HP_PA */ # ifdef ALPHA # define MACH_TYPE "ALPHA" # define ALIGNMENT 8 + # define CPP_WORDSZ 64 + # ifndef LINUX + # define USE_GENERIC_PUSH_REGS + /* Gcc and probably the DEC/Compaq compiler spill pointers to preserved */ + /* fp registers in some cases when the target is a 21264. The assembly */ + /* code doesn't handle that yet, and version dependencies make that a */ + /* bit tricky. Do the easy thing for now. */ + # endif # ifdef NETBSD # define OS_TYPE "NETBSD" # define HEURISTIC2 *************** *** 1327,1339 **** # define ELFCLASS32 32 # define ELFCLASS64 64 # define ELF_CLASS ELFCLASS64 - # define CPP_WORDSZ 64 # define DYNAMIC_LOADING # endif # ifdef OPENBSD # define OS_TYPE "OPENBSD" # define HEURISTIC2 - # define CPP_WORDSZ 64 # ifdef __ELF__ /* since OpenBSD/Alpha 2.9 */ # define DATASTART GC_data_start # define ELFCLASS32 32 --- 1456,1466 ---- *************** *** 1357,1373 **** extern char edata[]; extern char end[]; # define NEED_FIND_LIMIT ! # define DATASTART ((ptr_t)(etext)) # define DATAEND (GC_find_limit (DATASTART, TRUE)) ! # define DATASTART2 ((ptr_t)(edata)) ! # define DATAEND2 ((ptr_t)(end)) ! # define CPP_WORDSZ 64 # endif # ifdef OSF1 # define OS_TYPE "OSF1" # define DATASTART ((ptr_t) 0x140000000) extern int _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 */ --- 1484,1499 ---- extern char edata[]; extern char end[]; # define NEED_FIND_LIMIT ! # define DATASTART ((ptr_t)(&etext)) # define DATAEND (GC_find_limit (DATASTART, TRUE)) ! # define DATASTART2 ((ptr_t)(&edata)) ! # define DATAEND2 ((ptr_t)(&end)) # endif # ifdef OSF1 # define OS_TYPE "OSF1" # define DATASTART ((ptr_t) 0x140000000) extern int _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 */ *************** *** 1378,1396 **** /* the text segment immediately follows the stack. */ /* Hence we give an upper pound. */ /* This is currently unused, since we disabled HEURISTIC2 */ ! extern int __start[]; # define HEURISTIC2_LIMIT ((ptr_t)((word)(__start) & ~(getpagesize()-1))) ! # define CPP_WORDSZ 64 ! # define MPROTECT_VDB # define DYNAMIC_LOADING # endif # ifdef LINUX # define OS_TYPE "LINUX" - # define CPP_WORDSZ 64 # define STACKBOTTOM ((ptr_t) 0x120000000) # ifdef __ELF__ # define SEARCH_FOR_DATA_START - # define DATASTART GC_data_start # define DYNAMIC_LOADING # else # define DATASTART ((ptr_t) 0x140000000) --- 1504,1522 ---- /* the text segment immediately follows the stack. */ /* Hence we give an upper pound. */ /* This is currently unused, since we disabled HEURISTIC2 */ ! extern int __start[]; # define HEURISTIC2_LIMIT ((ptr_t)((word)(__start) & ~(getpagesize()-1))) ! # ifndef GC_OSF1_THREADS ! /* Unresolved signal issues with threads. */ ! # define MPROTECT_VDB ! # endif # define DYNAMIC_LOADING # endif # ifdef LINUX # define OS_TYPE "LINUX" # define STACKBOTTOM ((ptr_t) 0x120000000) # ifdef __ELF__ # define SEARCH_FOR_DATA_START # define DYNAMIC_LOADING # else # define DATASTART ((ptr_t) 0x140000000) *************** *** 1468,1474 **** extern char * GC_register_stackbottom; # define BACKING_STORE_BASE ((ptr_t)GC_register_stackbottom) # define SEARCH_FOR_DATA_START - # define DATASTART GC_data_start # ifdef __GNUC__ # define DYNAMIC_LOADING # else --- 1594,1599 ---- *************** *** 1502,1524 **** # endif # ifdef DGUX # define OS_TYPE "DGUX" ! extern char * GC_SysVGetDataStart(); ! # define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, etext) # endif # define STACKBOTTOM ((char*)0xf0000000) /* determined empirically */ # endif # ifdef S370 # define MACH_TYPE "S370" # define ALIGNMENT 4 /* Required by hardware */ # define USE_GENERIC_PUSH_REGS # ifdef UTS4 # define OS_TYPE "UTS4" ! extern int etext[]; extern int _etext[]; extern int _end[]; ! extern char * GC_SysVGetDataStart(); ! # define DATASTART (ptr_t)GC_SysVGetDataStart(0x10000, _etext) # define DATAEND (_end) # define HEURISTIC2 # endif --- 1627,1651 ---- # endif # ifdef DGUX # define OS_TYPE "DGUX" ! extern ptr_t GC_SysVGetDataStart(); ! # define DATASTART GC_SysVGetDataStart(0x10000, etext) # endif # define STACKBOTTOM ((char*)0xf0000000) /* determined empirically */ # endif # ifdef S370 + /* If this still works, and if anyone cares, this should probably */ + /* be moved to the S390 category. */ # define MACH_TYPE "S370" # define ALIGNMENT 4 /* Required by hardware */ # define USE_GENERIC_PUSH_REGS # ifdef UTS4 # define OS_TYPE "UTS4" ! extern int etext[]; extern int _etext[]; extern int _end[]; ! extern ptr_t GC_SysVGetDataStart(); ! # define DATASTART GC_SysVGetDataStart(0x10000, _etext) # define DATAEND (_end) # define HEURISTIC2 # endif *************** *** 1528,1550 **** # define MACH_TYPE "S390" # define USE_GENERIC_PUSH_REGS # ifndef __s390x__ ! # define ALIGNMENT 4 ! # define CPP_WORDSZ 32 # else ! # define ALIGNMENT 8 ! # define CPP_WORDSZ 64 ! # define HBLKSIZE 4096 # endif # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM # define DYNAMIC_LOADING ! extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) ! extern int _end[]; ! # define DATAEND (_end) ! # define CACHE_LINE_SIZE 256 ! # define GETPAGESIZE() 4096 # endif # endif --- 1655,1677 ---- # define MACH_TYPE "S390" # define USE_GENERIC_PUSH_REGS # ifndef __s390x__ ! # define ALIGNMENT 4 ! # define CPP_WORDSZ 32 # else ! # define ALIGNMENT 8 ! # define CPP_WORDSZ 64 ! # define HBLKSIZE 4096 # endif # ifdef LINUX # define OS_TYPE "LINUX" # define LINUX_STACKBOTTOM # define DYNAMIC_LOADING ! extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) ! extern int _end[]; ! # define DATAEND (_end) ! # define CACHE_LINE_SIZE 256 ! # define GETPAGESIZE() 4096 # endif # endif *************** *** 1562,1569 **** # ifdef NETBSD # define OS_TYPE "NETBSD" # define HEURISTIC2 ! extern char etext[]; ! # define DATASTART ((ptr_t)(etext)) # define USE_GENERIC_PUSH_REGS # endif # ifdef LINUX --- 1689,1701 ---- # ifdef NETBSD # define OS_TYPE "NETBSD" # define HEURISTIC2 ! # ifdef __ELF__ ! # define DATASTART GC_data_start ! # define DYNAMIC_LOADING ! # else ! extern char etext[]; ! # define DATASTART ((ptr_t)(etext)) ! # endif # define USE_GENERIC_PUSH_REGS # endif # ifdef LINUX *************** *** 1576,1582 **** # define DYNAMIC_LOADING # include # if defined(__GLIBC__) && __GLIBC__ >= 2 ! # define LINUX_DATA_START # else extern char **__environ; # define DATASTART ((ptr_t)(&__environ)) --- 1708,1714 ---- # define DYNAMIC_LOADING # include # if defined(__GLIBC__) && __GLIBC__ >= 2 ! # define SEARCH_FOR_DATA_START # else extern char **__environ; # define DATASTART ((ptr_t)(&__environ)) *************** *** 1623,1629 **** # define STACKBOTTOM ((ptr_t) 0x7c000000) # define USE_GENERIC_PUSH_REGS # define DYNAMIC_LOADING ! # define LINUX_DATA_START extern int _end[]; # define DATAEND (_end) # endif --- 1755,1761 ---- # define STACKBOTTOM ((ptr_t) 0x7c000000) # define USE_GENERIC_PUSH_REGS # define DYNAMIC_LOADING ! # define SEARCH_FOR_DATA_START extern int _end[]; # define DATAEND (_end) # endif *************** *** 1640,1646 **** # define MACH_TYPE "X86_64" # define ALIGNMENT 8 # define CPP_WORDSZ 64 ! # define HBLKSIZE 4096 # define CACHE_LINE_SIZE 64 # define USE_GENERIC_PUSH_REGS # ifdef LINUX --- 1772,1780 ---- # define MACH_TYPE "X86_64" # define ALIGNMENT 8 # define CPP_WORDSZ 64 ! # ifndef HBLKSIZE ! # define HBLKSIZE 4096 ! # endif # define CACHE_LINE_SIZE 64 # define USE_GENERIC_PUSH_REGS # ifdef LINUX *************** *** 1660,1666 **** # define DATASTART ((ptr_t)((((word) (_etext)) + 0xfff) & ~0xfff)) # endif # include ! # define LINUX_DATA_START extern int _end[]; # define DATAEND (_end) # else --- 1794,1800 ---- # define DATASTART ((ptr_t)((((word) (_etext)) + 0xfff) & ~0xfff)) # endif # include ! # define SEARCH_FOR_DATA_START extern int _end[]; # define DATAEND (_end) # else *************** *** 1674,1692 **** # endif # endif - #ifdef LINUX_DATA_START - /* Some Linux distributions arrange to define __data_start. Some */ - /* define data_start as a weak symbol. The latter is technically */ - /* broken, since the user program may define data_start, in which */ - /* case we lose. Nonetheless, we try both, prefering __data_start. */ - /* We assume gcc. */ - # pragma weak __data_start - extern int __data_start[]; - # pragma weak data_start - extern int data_start[]; - # define DATASTART ((ptr_t)(__data_start != 0? __data_start : data_start)) - #endif - #if defined(LINUX) && defined(REDIRECT_MALLOC) /* Rld appears to allocate some memory with its own allocator, and */ /* some through malloc, which might be redirected. To make this */ --- 1808,1813 ---- *************** *** 1725,1739 **** # endif # if defined(SUNOS5) || defined(DRSNX) || defined(UTS4) ! /* OS has SVR4 generic features. Probably others also qualify. */ # define SVR4 # endif # if defined(SUNOS5) || defined(DRSNX) ! /* OS has SUNOS5 style semi-undocumented interface to dynamic */ ! /* loader. */ # define SUNOS5DL ! /* OS has SUNOS5 style signal handlers. */ # define SUNOS5SIGS # endif --- 1846,1860 ---- # endif # if defined(SUNOS5) || defined(DRSNX) || defined(UTS4) ! /* OS has SVR4 generic features. Probably others also qualify. */ # define SVR4 # endif # if defined(SUNOS5) || defined(DRSNX) ! /* OS has SUNOS5 style semi-undocumented interface to dynamic */ ! /* loader. */ # define SUNOS5DL ! /* OS has SUNOS5 style signal handlers. */ # define SUNOS5SIGS # endif *************** *** 1742,1754 **** # endif # if defined(SVR4) || defined(LINUX) || defined(IRIX) || defined(HPUX) \ ! || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \ ! || defined(BSD) || defined(_AIX) || defined(MACOSX) || defined(OSF1) # define UNIX_LIKE /* Basic Unix-like system calls work. */ # endif # if CPP_WORDSZ != 32 && CPP_WORDSZ != 64 ! -> bad word size # endif # ifdef PCR --- 1863,1876 ---- # endif # if defined(SVR4) || defined(LINUX) || defined(IRIX) || defined(HPUX) \ ! || defined(OPENBSD) || defined(NETBSD) || defined(FREEBSD) \ ! || defined(DGUX) || defined(BSD) \ ! || defined(_AIX) || defined(DARWIN) || defined(OSF1) # define UNIX_LIKE /* Basic Unix-like system calls work. */ # endif # if CPP_WORDSZ != 32 && CPP_WORDSZ != 64 ! -> bad word size # endif # ifdef PCR *************** *** 1762,1774 **** # endif # ifdef SRC_M3 ! /* Postponed for now. */ # undef PROC_VDB # undef MPROTECT_VDB # endif # ifdef SMALL_CONFIG ! /* Presumably not worth the space it takes. */ # undef PROC_VDB # undef MPROTECT_VDB # endif --- 1884,1896 ---- # endif # ifdef SRC_M3 ! /* Postponed for now. */ # undef PROC_VDB # undef MPROTECT_VDB # endif # ifdef SMALL_CONFIG ! /* Presumably not worth the space it takes. */ # undef PROC_VDB # undef MPROTECT_VDB # endif *************** *** 1808,1856 **** /* platforms as well, though it should be avoided in win32. */ # endif /* LINUX */ ! # if defined(SEARCH_FOR_DATA_START) && defined(GC_PRIVATE_H) extern ptr_t GC_data_start; # endif # ifndef CLEAR_DOUBLE # define CLEAR_DOUBLE(x) \ ! ((word*)x)[0] = 0; \ ! ((word*)x)[1] = 0; # endif /* CLEAR_DOUBLE */ ! /* Internally we use GC_SOLARIS_THREADS to test for either old or pthreads. */ # if defined(GC_SOLARIS_PTHREADS) && !defined(GC_SOLARIS_THREADS) # define GC_SOLARIS_THREADS # endif # if defined(GC_IRIX_THREADS) && !defined(IRIX5) ! --> inconsistent configuration # endif # if defined(GC_LINUX_THREADS) && !defined(LINUX) ! --> inconsistent configuration # endif # if defined(GC_SOLARIS_THREADS) && !defined(SUNOS5) ! --> inconsistent configuration # endif # if defined(GC_HPUX_THREADS) && !defined(HPUX) ! --> inconsistent configuration # endif ! # if defined(GC_WIN32_THREADS) && !defined(MSWIN32) ! /* Ideally CYGWIN32 should work, in addition to MSWIN32. I suspect */ ! /* the necessary code is mostly there, but nobody has actually made */ ! /* sure the right combination of pieces is compiled in, etc. */ ! --> inconsistent configuration # endif # if defined(PCR) || defined(SRC_M3) || \ ! defined(GC_SOLARIS_THREADS) || defined(GC_WIN32_THREADS) || \ ! defined(GC_PTHREADS) # define THREADS # endif ! # if defined(HP_PA) || defined(M88K) || defined(POWERPC) && !defined(MACOSX) \ ! || defined(LINT) || defined(MSWINCE) \ ! || (defined(I386) && defined(__LCC__)) /* Use setjmp based hack to mark from callee-save registers. */ /* The define should move to the individual platform */ /* descriptions. */ --- 1930,1979 ---- /* platforms as well, though it should be avoided in win32. */ # endif /* LINUX */ ! # if defined(SEARCH_FOR_DATA_START) extern ptr_t GC_data_start; + # define DATASTART GC_data_start # endif # ifndef CLEAR_DOUBLE # define CLEAR_DOUBLE(x) \ ! ((word*)x)[0] = 0; \ ! ((word*)x)[1] = 0; # endif /* CLEAR_DOUBLE */ ! /* Internally we use GC_SOLARIS_THREADS to test for either old or pthreads. */ # if defined(GC_SOLARIS_PTHREADS) && !defined(GC_SOLARIS_THREADS) # define GC_SOLARIS_THREADS # endif # if defined(GC_IRIX_THREADS) && !defined(IRIX5) ! --> inconsistent configuration # endif # if defined(GC_LINUX_THREADS) && !defined(LINUX) ! --> inconsistent configuration # endif # if defined(GC_SOLARIS_THREADS) && !defined(SUNOS5) ! --> inconsistent configuration # endif # if defined(GC_HPUX_THREADS) && !defined(HPUX) ! --> inconsistent configuration # endif ! # if defined(GC_AIX_THREADS) && !defined(_AIX) ! --> inconsistent configuration ! # endif ! # if defined(GC_WIN32_THREADS) && !defined(MSWIN32) && !defined(CYGWIN32) ! --> inconsistent configuration # endif # if defined(PCR) || defined(SRC_M3) || \ ! defined(GC_SOLARIS_THREADS) || defined(GC_WIN32_THREADS) || \ ! defined(GC_PTHREADS) # define THREADS # endif ! # if defined(HP_PA) || defined(M88K) || defined(POWERPC) && !defined(DARWIN) \ ! || defined(LINT) || defined(MSWINCE) || defined(ARM32) \ ! || (defined(I386) && defined(__LCC__)) /* Use setjmp based hack to mark from callee-save registers. */ /* The define should move to the individual platform */ /* descriptions. */ *************** *** 1862,1897 **** /* include assembly code to do it well. */ # endif ! /* Can we save call chain in objects for debugging? */ ! /* SET NFRAMES (# of saved frames) and NARGS (#of args for each frame) */ ! /* to reasonable values for the platform. */ ! /* Set SAVE_CALL_CHAIN if we can. SAVE_CALL_COUNT can be specified at */ ! /* build time, though we feel free to adjust it slightly. */ ! /* Define NEED_CALLINFO if we either save the call stack or */ ! /* GC_ADD_CALLER is defined. */ ! #ifdef LINUX ! # include ! # if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2 ! # define HAVE_BUILTIN_BACKTRACE ! # endif ! #endif #if defined(SPARC) - # define CAN_SAVE_CALL_STACKS # define CAN_SAVE_CALL_ARGS #endif #if (defined(I386) || defined(X86_64)) && defined(LINUX) ! /* SAVE_CALL_CHAIN is supported if the code is compiled to save */ ! /* frame pointers by default, i.e. no -fomit-frame-pointer flag. */ ! # define CAN_SAVE_CALL_STACKS # define CAN_SAVE_CALL_ARGS #endif - #if defined(HAVE_BUILTIN_BACKTRACE) && !defined(CAN_SAVE_CALL_STACKS) - # define CAN_SAVE_CALL_STACKS - #endif # if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \ ! && defined(CAN_SAVE_CALL_STACKS) # define SAVE_CALL_CHAIN # endif # ifdef SAVE_CALL_CHAIN --- 1985,2010 ---- /* include assembly code to do it well. */ # endif ! /* Can we save call chain in objects for debugging? */ ! /* SET NFRAMES (# of saved frames) and NARGS (#of args for each */ ! /* frame) to reasonable values for the platform. */ ! /* Set SAVE_CALL_CHAIN if we can. SAVE_CALL_COUNT can be specified */ ! /* at build time, though we feel free to adjust it slightly. */ ! /* Define NEED_CALLINFO if we either save the call stack or */ ! /* GC_ADD_CALLER is defined. */ ! /* GC_CAN_SAVE_CALL_STACKS is set in gc.h. */ #if defined(SPARC) # define CAN_SAVE_CALL_ARGS #endif #if (defined(I386) || defined(X86_64)) && defined(LINUX) ! /* SAVE_CALL_CHAIN is supported if the code is compiled to save */ ! /* frame pointers by default, i.e. no -fomit-frame-pointer flag. */ # define CAN_SAVE_CALL_ARGS #endif # if defined(SAVE_CALL_COUNT) && !defined(GC_ADD_CALLER) \ ! && defined(GC_CAN_SAVE_CALL_STACKS) # define SAVE_CALL_CHAIN # endif # ifdef SAVE_CALL_CHAIN *************** *** 1904,1910 **** # ifdef SAVE_CALL_CHAIN # ifndef SAVE_CALL_COUNT # define NFRAMES 6 /* Number of frames to save. Even for */ ! /* alignment reasons. */ # else # define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1) # endif --- 2017,2023 ---- # ifdef SAVE_CALL_CHAIN # ifndef SAVE_CALL_COUNT # define NFRAMES 6 /* Number of frames to save. Even for */ ! /* alignment reasons. */ # else # define NFRAMES ((SAVE_CALL_COUNT + 1) & ~1) # endif *************** *** 1920,1923 **** --- 2033,2128 ---- # define DBG_HDRS_ALL # endif + # if defined(POINTER_MASK) && !defined(POINTER_SHIFT) + # define POINTER_SHIFT 0 + # endif + + # if defined(POINTER_SHIFT) && !defined(POINTER_MASK) + # define POINTER_MASK ((GC_word)(-1)) + # endif + + # if !defined(FIXUP_POINTER) && defined(POINTER_MASK) + # define FIXUP_POINTER(p) (p) = ((p) & (POINTER_MASK) << POINTER_SHIFT) + # endif + + # if defined(FIXUP_POINTER) + # define NEED_FIXUP_POINTER 1 + # else + # define NEED_FIXUP_POINTER 0 + # define FIXUP_POINTER(p) + # endif + + #ifdef GC_PRIVATE_H + /* This relies on some type definitions from gc_priv.h, from */ + /* where it's normally included. */ + /* */ + /* How to get heap memory from the OS: */ + /* Note that sbrk()-like allocation is preferred, since it */ + /* usually makes it possible to merge consecutively allocated */ + /* chunks. It also avoids unintented recursion with */ + /* -DREDIRECT_MALLOC. */ + /* GET_MEM() returns a HLKSIZE aligned chunk. */ + /* 0 is taken to mean failure. */ + /* In the case os USE_MMAP, the argument must also be a */ + /* physical page size. */ + /* GET_MEM is currently not assumed to retrieve 0 filled space, */ + /* though we should perhaps take advantage of the case in which */ + /* does. */ + struct hblk; /* See gc_priv.h. */ + # ifdef PCR + char * real_malloc(); + # define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \ + + GC_page_size-1) + # else + # ifdef 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) + # else + # if defined(NEXT) || defined(DOS4GW) || \ + (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \ + (defined(SUNOS5) && !defined(USE_MMAP)) + # define GET_MEM(bytes) HBLKPTR((size_t) \ + calloc(1, (size_t)bytes + GC_page_size) \ + + GC_page_size-1) + # else + # ifdef MSWIN32 + extern ptr_t GC_win32_get_mem(); + # define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes) + # else + # ifdef MACOS + # if defined(USE_TEMPORARY_MEMORY) + extern Ptr GC_MacTemporaryNewPtr(size_t size, + Boolean clearMemory); + # define GET_MEM(bytes) HBLKPTR( \ + GC_MacTemporaryNewPtr(bytes + GC_page_size, true) \ + + GC_page_size-1) + # else + # define GET_MEM(bytes) HBLKPTR( \ + NewPtrClear(bytes + GC_page_size) + GC_page_size-1) + # endif + # else + # ifdef MSWINCE + extern ptr_t GC_wince_get_mem(); + # define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes) + # else + # if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC) + extern 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) \ + + GC_page_size-1) + # else + extern ptr_t GC_unix_get_mem(); + # define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes) + # endif + # endif + # endif + # endif + # endif + # endif + # endif + + #endif /* GC_PRIVATE_H */ + # endif /* GCCONFIG_H */ diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/gc_hdrs.h gcc-3.4.0/boehm-gc/include/private/gc_hdrs.h *** gcc-3.3.3/boehm-gc/include/private/gc_hdrs.h 2001-08-18 01:04:43.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/gc_hdrs.h 2003-07-28 04:18:23.000000000 +0000 *************** extern hdr * GC_invalid_header; /* heade *** 70,76 **** #define ADVANCE(p, hhdr, source) \ { \ hdr * new_hdr = GC_invalid_header; \ ! p = GC_FIND_START(p, hhdr, &new_hdr, (word)source); \ hhdr = new_hdr; \ } --- 70,76 ---- #define ADVANCE(p, hhdr, source) \ { \ hdr * new_hdr = GC_invalid_header; \ ! p = GC_find_start(p, hhdr, &new_hdr); \ hhdr = new_hdr; \ } diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/gc_locks.h gcc-3.4.0/boehm-gc/include/private/gc_locks.h *** gcc-3.3.3/boehm-gc/include/private/gc_locks.h 2002-09-27 20:40:06.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/gc_locks.h 2003-07-28 04:18:23.000000000 +0000 *************** *** 100,116 **** # define GC_TEST_AND_SET_DEFINED # endif # if defined(IA64) inline static int GC_test_and_set(volatile unsigned int *addr) { ! long oldval, n = 1; ! __asm__ __volatile__("xchg4 %0=%1,%2" ! : "=r"(oldval), "=m"(*addr) ! : "r"(n), "1"(*addr) : "memory"); ! return oldval; } # define GC_TEST_AND_SET_DEFINED - /* Should this handle post-increment addressing?? */ inline static void GC_clear(volatile unsigned int *addr) { ! __asm__ __volatile__("st4.rel %0=r0" : "=m" (*addr) : : "memory"); } # define GC_CLEAR_DEFINED # endif --- 100,112 ---- # define GC_TEST_AND_SET_DEFINED # endif # if defined(IA64) + # include inline static int GC_test_and_set(volatile unsigned int *addr) { ! return __sync_lock_test_and_set(addr, 1); } # define GC_TEST_AND_SET_DEFINED inline static void GC_clear(volatile unsigned int *addr) { ! *addr = 0; } # define GC_CLEAR_DEFINED # endif *************** *** 145,167 **** # if defined(POWERPC) inline static int GC_test_and_set(volatile unsigned int *addr) { int oldval; ! int temp = 1; // locked value __asm__ __volatile__( ! "1:\tlwarx %0,0,%3\n" // load and reserve ! "\tcmpwi %0, 0\n" // if load is ! "\tbne 2f\n" // non-zero, return already set ! "\tstwcx. %2,0,%1\n" // else store conditional ! "\tbne- 1b\n" // retry if lost reservation ! "2:\t\n" // oldval is zero if we set : "=&r"(oldval), "=p"(addr) : "r"(temp), "1"(addr) ! : "memory"); ! return (int)oldval; } # define GC_TEST_AND_SET_DEFINED inline static void GC_clear(volatile unsigned int *addr) { ! __asm__ __volatile__("eieio" ::: "memory"); *(addr) = 0; } # define GC_CLEAR_DEFINED --- 141,164 ---- # if defined(POWERPC) inline static int GC_test_and_set(volatile unsigned int *addr) { int oldval; ! int temp = 1; /* locked value */ __asm__ __volatile__( ! "1:\tlwarx %0,0,%3\n" /* load and reserve */ ! "\tcmpwi %0, 0\n" /* if load is */ ! "\tbne 2f\n" /* non-zero, return already set */ ! "\tstwcx. %2,0,%1\n" /* else store conditional */ ! "\tbne- 1b\n" /* retry if lost reservation */ ! "\tsync\n" /* import barrier */ ! "2:\t\n" /* oldval is zero if we set */ : "=&r"(oldval), "=p"(addr) : "r"(temp), "1"(addr) ! : "cr0","memory"); ! return oldval; } # define GC_TEST_AND_SET_DEFINED inline static void GC_clear(volatile unsigned int *addr) { ! __asm__ __volatile__("eieio" : : : "memory"); *(addr) = 0; } # define GC_CLEAR_DEFINED *************** *** 178,189 **** --- 175,192 ---- " bne %2,2f\n" " xor %0,%3,%0\n" " stl_c %0,%1\n" + # ifdef __ELF__ " beq %0,3f\n" + # else + " beq %0,1b\n" + # endif " mb\n" "2:\n" + # ifdef __ELF__ ".section .text2,\"ax\"\n" "3: br 1b\n" ".previous" + # endif :"=&r" (temp), "=m" (*addr), "=&r" (oldvalue) :"Ir" (1), "m" (*addr) :"memory"); *************** *** 191,198 **** return oldvalue; } # define GC_TEST_AND_SET_DEFINED ! /* Should probably also define GC_clear, since it needs */ ! /* a memory barrier ?? */ # endif /* ALPHA */ # ifdef ARM32 inline static int GC_test_and_set(volatile unsigned int *addr) { --- 194,204 ---- return oldvalue; } # define GC_TEST_AND_SET_DEFINED ! inline static void GC_clear(volatile unsigned int *addr) { ! __asm__ __volatile__("mb" : : : "memory"); ! *(addr) = 0; ! } ! # define GC_CLEAR_DEFINED # endif /* ALPHA */ # ifdef ARM32 inline static int GC_test_and_set(volatile unsigned int *addr) { *************** *** 210,231 **** # define GC_TEST_AND_SET_DEFINED # endif /* ARM32 */ # ifdef S390 ! inline static int GC_test_and_set(volatile unsigned int *addr) { ! int ret; ! __asm__ __volatile__ ( ! " l %0,0(%2)\n" ! "0: cs %0,%1,0(%2)\n" ! " jl 0b" ! : "=&d" (ret) ! : "d" (1), "a" (addr) ! : "cc", "memory"); ! return ret; ! } # endif # endif /* __GNUC__ */ # if (defined(ALPHA) && !defined(__GNUC__)) ! # define GC_test_and_set(addr) __cxx_test_and_set_atomic(addr, 1) # define GC_TEST_AND_SET_DEFINED # endif # if defined(MSWIN32) # define GC_test_and_set(addr) InterlockedExchange((LPLONG)addr,1) --- 216,245 ---- # define GC_TEST_AND_SET_DEFINED # endif /* ARM32 */ # ifdef S390 ! inline static int GC_test_and_set(volatile unsigned int *addr) { ! int ret; ! __asm__ __volatile__ ( ! " l %0,0(%2)\n" ! "0: cs %0,%1,0(%2)\n" ! " jl 0b" ! : "=&d" (ret) ! : "d" (1), "a" (addr) ! : "cc", "memory"); ! return ret; ! } # endif # endif /* __GNUC__ */ # if (defined(ALPHA) && !defined(__GNUC__)) ! # ifndef OSF1 ! --> We currently assume that if gcc is not used, we are ! --> running under Tru64. ! # endif ! # include ! # include ! # define GC_test_and_set(addr) __ATOMIC_EXCH_LONG(addr, 1) # define GC_TEST_AND_SET_DEFINED + # define GC_clear(addr) { asm("mb"); *(volatile unsigned *)addr = 0; } + # define GC_CLEAR_DEFINED # endif # if defined(MSWIN32) # define GC_test_and_set(addr) InterlockedExchange((LPLONG)addr,1) *************** *** 238,251 **** # define GC_TEST_AND_SET_DEFINED # elif __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \ || !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700 ! # define GC_test_and_set(addr) test_and_set(addr, 1) # else ! # define GC_test_and_set(addr) __test_and_set(addr,1) # define GC_clear(addr) __lock_release(addr); # define GC_CLEAR_DEFINED # endif # define GC_TEST_AND_SET_DEFINED # endif /* MIPS */ # if 0 /* defined(HP_PA) */ /* The official recommendation seems to be to not use ldcw from */ /* user mode. Since multithreaded incremental collection doesn't */ --- 252,302 ---- # define GC_TEST_AND_SET_DEFINED # elif __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) \ || !defined(_COMPILER_VERSION) || _COMPILER_VERSION < 700 ! # ifdef __GNUC__ ! # define GC_test_and_set(addr) _test_and_set((void *)addr,1) ! # else ! # define GC_test_and_set(addr) test_and_set((void *)addr,1) ! # endif # else ! # define GC_test_and_set(addr) __test_and_set32((void *)addr,1) # define GC_clear(addr) __lock_release(addr); # define GC_CLEAR_DEFINED # endif # define GC_TEST_AND_SET_DEFINED # endif /* MIPS */ + # if defined(_AIX) + # include + # if (defined(_POWER) || defined(_POWERPC)) + # if defined(__GNUC__) + inline static void GC_memsync() { + __asm__ __volatile__ ("sync" : : : "memory"); + } + # else + # ifndef inline + # define inline __inline + # endif + # pragma mc_func GC_memsync { \ + "7c0004ac" /* sync (same opcode used for dcs)*/ \ + } + # endif + # else + # error dont know how to memsync + # endif + inline static int GC_test_and_set(volatile unsigned int * addr) { + int oldvalue = 0; + if (compare_and_swap((void *)addr, &oldvalue, 1)) { + GC_memsync(); + return 0; + } else return 1; + } + # define GC_TEST_AND_SET_DEFINED + inline static void GC_clear(volatile unsigned int *addr) { + GC_memsync(); + *(addr) = 0; + } + # define GC_CLEAR_DEFINED + + # endif # if 0 /* defined(HP_PA) */ /* The official recommendation seems to be to not use ldcw from */ /* user mode. Since multithreaded incremental collection doesn't */ *************** *** 279,285 **** # endif # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ ! && !defined(GC_IRIX_THREADS) # define NO_THREAD (pthread_t)(-1) # include # if defined(PARALLEL_MARK) --- 330,336 ---- # endif # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ ! && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) # define NO_THREAD (pthread_t)(-1) # include # if defined(PARALLEL_MARK) *************** *** 310,321 **** { char result; __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1" ! : "=m"(*(addr)), "=r"(result) ! : "r" (new_val), "0"(*(addr)), "a"(old) : "memory"); return (GC_bool) result; } # endif /* !GENERIC_COMPARE_AND_SWAP */ ! inline static void GC_memory_write_barrier() { /* We believe the processor ensures at least processor */ /* consistent ordering. Thus a compiler barrier */ --- 361,372 ---- { char result; __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1" ! : "+m"(*(addr)), "=r"(result) ! : "r" (new_val), "a"(old) : "memory"); return (GC_bool) result; } # endif /* !GENERIC_COMPARE_AND_SWAP */ ! inline static void GC_memory_barrier() { /* We believe the processor ensures at least processor */ /* consistent ordering. Thus a compiler barrier */ *************** *** 323,367 **** __asm__ __volatile__("" : : : "memory"); } # endif /* I386 */ # if defined(IA64) # if !defined(GENERIC_COMPARE_AND_SWAP) inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, ! GC_word old, GC_word new_val) { ! unsigned long oldval; ! __asm__ __volatile__("mov ar.ccv=%4 ;; cmpxchg8.rel %0=%1,%2,ar.ccv" ! : "=r"(oldval), "=m"(*addr) ! : "r"(new_val), "1"(*addr), "r"(old) : "memory"); ! return (oldval == old); } # endif /* !GENERIC_COMPARE_AND_SWAP */ # if 0 /* Shouldn't be needed; we use volatile stores instead. */ ! inline static void GC_memory_write_barrier() { ! __asm__ __volatile__("mf" : : : "memory"); } # endif /* 0 */ # endif /* IA64 */ # if defined(S390) # if !defined(GENERIC_COMPARE_AND_SWAP) ! inline static GC_bool GC_compare_and_exchange(volatile C_word *addr, ! GC_word old, GC_word new_val) ! { ! int retval; ! __asm__ __volatile__ ( ! # ifndef __s390x__ ! " cs %1,%2,0(%3)\n" ! # else ! " csg %1,%2,0(%3)\n" ! # endif ! " ipm %0\n" ! " srl %0,28\n" ! : "=&d" (retval), "+d" (old) ! : "d" (new_val), "a" (addr) ! : "cc", "memory"); ! return retval == 0; ! } # endif # endif # if !defined(GENERIC_COMPARE_AND_SWAP) --- 374,486 ---- __asm__ __volatile__("" : : : "memory"); } # endif /* I386 */ + + # if defined(POWERPC) + # if !defined(GENERIC_COMPARE_AND_SWAP) + /* Returns TRUE if the comparison succeeded. */ + inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, + GC_word old, GC_word new_val) + { + int result, dummy; + __asm__ __volatile__( + "1:\tlwarx %0,0,%5\n" + "\tcmpw %0,%4\n" + "\tbne 2f\n" + "\tstwcx. %3,0,%2\n" + "\tbne- 1b\n" + "\tsync\n" + "\tli %1, 1\n" + "\tb 3f\n" + "2:\tli %1, 0\n" + "3:\t\n" + : "=&r" (dummy), "=r" (result), "=p" (addr) + : "r" (new_val), "r" (old), "2"(addr) + : "cr0","memory"); + return (GC_bool) result; + } + # endif /* !GENERIC_COMPARE_AND_SWAP */ + inline static void GC_memory_barrier() + { + __asm__ __volatile__("sync" : : : "memory"); + } + # endif /* POWERPC */ + # if defined(IA64) # if !defined(GENERIC_COMPARE_AND_SWAP) inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, ! GC_word old, ! GC_word new_val) { ! return __sync_bool_compare_and_swap (addr, old, new_val); } # endif /* !GENERIC_COMPARE_AND_SWAP */ # if 0 /* Shouldn't be needed; we use volatile stores instead. */ ! inline static void GC_memory_barrier() { ! __sync_synchronize (); } # endif /* 0 */ # endif /* IA64 */ + # if defined(ALPHA) + # if !defined(GENERIC_COMPARE_AND_SWAP) + # if defined(__GNUC__) + inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, + GC_word old, GC_word new_val) + { + unsigned long was_equal; + unsigned long temp; + + __asm__ __volatile__( + "1: ldq_l %0,%1\n" + " cmpeq %0,%4,%2\n" + " mov %3,%0\n" + " beq %2,2f\n" + " stq_c %0,%1\n" + " beq %0,1b\n" + "2:\n" + " mb\n" + :"=&r" (temp), "=m" (*addr), "=&r" (was_equal) + : "r" (new_val), "Ir" (old) + :"memory"); + return was_equal; + } + # else /* !__GNUC__ */ + inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr, + GC_word old, GC_word new_val) + { + return __CMP_STORE_QUAD(addr, old, new_val, addr); + } + # endif /* !__GNUC__ */ + # endif /* !GENERIC_COMPARE_AND_SWAP */ + # ifdef __GNUC__ + inline static void GC_memory_barrier() + { + __asm__ __volatile__("mb" : : : "memory"); + } + # else + # define GC_memory_barrier() asm("mb") + # endif /* !__GNUC__ */ + # endif /* ALPHA */ # if defined(S390) # if !defined(GENERIC_COMPARE_AND_SWAP) ! inline static GC_bool GC_compare_and_exchange(volatile C_word *addr, ! GC_word old, GC_word new_val) ! { ! int retval; ! __asm__ __volatile__ ( ! # ifndef __s390x__ ! " cs %1,%2,0(%3)\n" ! # else ! " csg %1,%2,0(%3)\n" ! # endif ! " ipm %0\n" ! " srl %0,28\n" ! : "=&d" (retval), "+d" (old) ! : "d" (new_val), "a" (addr) ! : "cc", "memory"); ! return retval == 0; ! } # endif # endif # if !defined(GENERIC_COMPARE_AND_SWAP) *************** *** 434,441 **** --- 553,564 ---- { GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \ pthread_mutex_unlock(&GC_allocate_ml); } # else /* !GC_ASSERTIONS */ + # if defined(NO_PTHREAD_TRYLOCK) + # define LOCK() GC_lock(); + # else /* !defined(NO_PTHREAD_TRYLOCK) */ # define LOCK() \ { if (0 != pthread_mutex_trylock(&GC_allocate_ml)) GC_lock(); } + # endif # define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) # endif /* !GC_ASSERTIONS */ # endif /* USE_PTHREAD_LOCKS */ *************** *** 457,463 **** /* on Irix anymore. */ # include ! extern unsigned long GC_allocate_lock; /* This is not a mutex because mutexes that obey the (optional) */ /* POSIX scheduling rules are subject to convoys in high contention */ /* applications. This is basically a spin lock. */ --- 580,586 ---- /* on Irix anymore. */ # include ! extern volatile unsigned int GC_allocate_lock; /* This is not a mutex because mutexes that obey the (optional) */ /* POSIX scheduling rules are subject to convoys in high contention */ /* applications. This is basically a spin lock. */ *************** *** 478,488 **** } # define EXIT_GC() GC_collecting = 0; # endif /* GC_IRIX_THREADS */ ! # ifdef GC_WIN32_THREADS ! # include ! GC_API CRITICAL_SECTION GC_allocate_ml; ! # define LOCK() EnterCriticalSection(&GC_allocate_ml); ! # define UNLOCK() LeaveCriticalSection(&GC_allocate_ml); # endif # ifndef SET_LOCK_HOLDER # define SET_LOCK_HOLDER() --- 601,618 ---- } # define EXIT_GC() GC_collecting = 0; # endif /* GC_IRIX_THREADS */ ! # if defined(GC_WIN32_THREADS) ! # if defined(GC_PTHREADS) ! # include ! extern pthread_mutex_t GC_allocate_ml; ! # define LOCK() pthread_mutex_lock(&GC_allocate_ml) ! # define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml) ! # else ! # include ! GC_API CRITICAL_SECTION GC_allocate_ml; ! # define LOCK() EnterCriticalSection(&GC_allocate_ml); ! # define UNLOCK() LeaveCriticalSection(&GC_allocate_ml); ! # endif # endif # ifndef SET_LOCK_HOLDER # define SET_LOCK_HOLDER() diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/gc_pmark.h gcc-3.4.0/boehm-gc/include/private/gc_pmark.h *** gcc-3.3.3/boehm-gc/include/private/gc_pmark.h 2002-02-12 04:37:57.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/gc_pmark.h 2003-07-28 04:18:23.000000000 +0000 *************** extern mse * GC_mark_stack; *** 137,143 **** #ifdef __STDC__ # ifdef PRINT_BLACK_LIST ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p, ! ptr_t source); # else ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p); # endif --- 137,143 ---- #ifdef __STDC__ # ifdef PRINT_BLACK_LIST ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p, ! word source); # else ptr_t GC_find_start(ptr_t current, hdr *hhdr, hdr **new_hdr_p); # endif *************** extern mse * GC_mark_stack; *** 145,151 **** ptr_t GC_find_start(); #endif ! mse *GC_signal_mark_stack_overflow(mse *msp); # ifdef GATHERSTATS # define ADD_TO_ATOMIC(sz) GC_atomic_in_use += (sz) --- 145,151 ---- ptr_t GC_find_start(); #endif ! mse * GC_signal_mark_stack_overflow GC_PROTO((mse *msp)); # ifdef GATHERSTATS # define ADD_TO_ATOMIC(sz) GC_atomic_in_use += (sz) *************** mse *GC_signal_mark_stack_overflow(mse * *** 174,187 **** } \ } - #ifdef PRINT_BLACK_LIST - # define GC_FIND_START(current, hhdr, new_hdr_p, source) \ - GC_find_start(current, hhdr, new_hdr_p, source) - #else - # define GC_FIND_START(current, hhdr, new_hdr_p, source) \ - GC_find_start(current, hhdr, new_hdr_p) - #endif - /* 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 */ --- 174,179 ---- *************** mse *GC_signal_mark_stack_overflow(mse * *** 195,202 **** GET_HDR(my_current, my_hhdr); \ if (IS_FORWARDING_ADDR_OR_NIL(my_hhdr)) { \ hdr * new_hdr = GC_invalid_header; \ ! my_current = GC_FIND_START(my_current, my_hhdr, \ ! &new_hdr, (word)source); \ my_hhdr = new_hdr; \ } \ PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \ --- 187,193 ---- GET_HDR(my_current, my_hhdr); \ if (IS_FORWARDING_ADDR_OR_NIL(my_hhdr)) { \ hdr * new_hdr = GC_invalid_header; \ ! my_current = GC_find_start(my_current, my_hhdr, &new_hdr); \ my_hhdr = new_hdr; \ } \ PUSH_CONTENTS_HDR(my_current, mark_stack_top, mark_stack_limit, \ *************** exit_label: ; \ *** 290,310 **** /* * Push a single value onto mark stack. Mark from the object pointed to by p. * P is considered valid even if it is an interior pointer. * Previously marked objects are not pushed. Hence we make progress even * if the mark stack overflows. */ ! # define GC_PUSH_ONE_STACK(p, source) \ ! if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ PUSH_ONE_CHECKED_STACK(p, source); \ ! } /* * As above, but interior pointer recognition as for * normal for heap pointers. */ # define GC_PUSH_ONE_HEAP(p,source) \ if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ GC_mark_stack_top = GC_mark_and_push( \ --- 281,319 ---- /* * Push a single value onto mark stack. Mark from the object pointed to by p. + * Invoke FIXUP_POINTER(p) before any further processing. * P is considered valid even if it is an interior pointer. * Previously marked objects are not pushed. Hence we make progress even * if the mark stack overflows. */ ! ! # if NEED_FIXUP_POINTER ! /* Try both the raw version and the fixed up one. */ ! # define GC_PUSH_ONE_STACK(p, source) \ ! if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ PUSH_ONE_CHECKED_STACK(p, source); \ ! } \ ! FIXUP_POINTER(p); \ ! if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ ! && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ ! PUSH_ONE_CHECKED_STACK(p, source); \ ! } ! # else /* !NEED_FIXUP_POINTER */ ! # define GC_PUSH_ONE_STACK(p, source) \ ! if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ ! && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ ! PUSH_ONE_CHECKED_STACK(p, source); \ ! } ! # endif ! /* * As above, but interior pointer recognition as for * normal for heap pointers. */ # define GC_PUSH_ONE_HEAP(p,source) \ + FIXUP_POINTER(p); \ if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \ GC_mark_stack_top = GC_mark_and_push( \ diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/gc_priv.h gcc-3.4.0/boehm-gc/include/private/gc_priv.h *** gcc-3.3.3/boehm-gc/include/private/gc_priv.h 2003-03-04 17:56:49.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/gc_priv.h 2003-10-03 18:43:06.000000000 +0000 *************** *** 30,43 **** # define BSD_TIME #endif #ifdef BSD_TIME # include # include # include #endif /* BSD_TIME */ ! # ifndef GC_H ! # include "gc.h" # endif # ifndef GC_MARK_H --- 30,49 ---- # define BSD_TIME #endif + #ifdef DGUX + # include + # include + # include + #endif /* DGUX */ + #ifdef BSD_TIME # include # include # include #endif /* BSD_TIME */ ! # ifndef _GC_H ! # include "../gc.h" # endif # ifndef GC_MARK_H *************** typedef char * ptr_t; /* A generic point *** 206,216 **** #endif #if defined(GC_GCJ_SUPPORT) && ALIGNMENT < 8 && !defined(ALIGN_DOUBLE) ! /* GCJ's Hashtable synchronization code requires 64-bit alignment. */ # define ALIGN_DOUBLE #endif - /* ALIGN_DOUBLE requires MERGE_SIZES at present. */ # if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES) # define MERGE_SIZES --- 212,221 ---- #endif #if defined(GC_GCJ_SUPPORT) && ALIGNMENT < 8 && !defined(ALIGN_DOUBLE) ! /* GCJ's Hashtable synchronization code requires 64-bit alignment. */ # define ALIGN_DOUBLE #endif /* ALIGN_DOUBLE requires MERGE_SIZES at present. */ # if defined(ALIGN_DOUBLE) && !defined(MERGE_SIZES) # define MERGE_SIZES *************** void GC_print_callers GC_PROTO((struct c *** 347,353 **** # include # define BCOPY_EXISTS # endif ! # if defined(MACOSX) # define BCOPY_EXISTS # endif --- 352,359 ---- # include # define BCOPY_EXISTS # endif ! # if defined(DARWIN) ! # include # define BCOPY_EXISTS # endif *************** void GC_print_callers GC_PROTO((struct c *** 360,427 **** # define BZERO(x,n) bzero((char *)(x),(int)(n)) # endif - /* HBLKSIZE aligned allocation. 0 is taken to mean failure */ - /* space is assumed to be cleared. */ - /* In the case os USE_MMAP, the argument must also be a */ - /* physical page size. */ - /* GET_MEM is currently not assumed to retrieve 0 filled space, */ - /* though we should perhaps take advantage of the case in which */ - /* does. */ - struct hblk; /* See below. */ - # ifdef PCR - char * real_malloc(); - # define GET_MEM(bytes) HBLKPTR(real_malloc((size_t)bytes + GC_page_size) \ - + GC_page_size-1) - # else - # ifdef 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) - # else - # if defined(NEXT) || defined(MACOSX) || defined(DOS4GW) || \ - (defined(AMIGA) && !defined(GC_AMIGA_FASTALLOC)) || \ - (defined(SUNOS5) && !defined(USE_MMAP)) - # define GET_MEM(bytes) HBLKPTR((size_t) \ - calloc(1, (size_t)bytes + GC_page_size) \ - + GC_page_size-1) - # else - # ifdef MSWIN32 - extern ptr_t GC_win32_get_mem(); - # define GET_MEM(bytes) (struct hblk *)GC_win32_get_mem(bytes) - # else - # ifdef MACOS - # if defined(USE_TEMPORARY_MEMORY) - extern Ptr GC_MacTemporaryNewPtr(size_t size, - Boolean clearMemory); - # define GET_MEM(bytes) HBLKPTR( \ - GC_MacTemporaryNewPtr(bytes + GC_page_size, true) \ - + GC_page_size-1) - # else - # define GET_MEM(bytes) HBLKPTR( \ - NewPtrClear(bytes + GC_page_size) + GC_page_size-1) - # endif - # else - # ifdef MSWINCE - extern ptr_t GC_wince_get_mem(); - # define GET_MEM(bytes) (struct hblk *)GC_wince_get_mem(bytes) - # else - # if defined(AMIGA) && defined(GC_AMIGA_FASTALLOC) - extern 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) \ - + GC_page_size-1) - # else - extern ptr_t GC_unix_get_mem(); - # define GET_MEM(bytes) (struct hblk *)GC_unix_get_mem(bytes) - # endif - # endif - # endif - # endif - # endif - # endif - # endif - /* Delay any interrupts or signals that may abort this thread. Data */ /* structures are in a consistent state outside this pair of calls. */ /* ANSI C allows both to be empty (though the standard isn't very */ --- 366,371 ---- *************** struct hblk; /* See below. */ *** 486,492 **** # ifdef SMALL_CONFIG # define ABORT(msg) abort(); # else ! GC_API void GC_abort(); # define ABORT(msg) GC_abort(msg); # endif # endif --- 430,436 ---- # ifdef SMALL_CONFIG # define ABORT(msg) abort(); # else ! GC_API void GC_abort GC_PROTO((GC_CONST char * msg)); # define ABORT(msg) GC_abort(msg); # endif # endif *************** extern GC_warn_proc GC_current_warn_proc *** 504,510 **** /* Get environment entry */ #if !defined(NO_GETENV) ! # define GETENV(name) getenv(name) #else # define GETENV(name) 0 #endif --- 448,466 ---- /* Get environment entry */ #if !defined(NO_GETENV) ! # if defined(EMPTY_GETENV_RESULTS) ! /* Workaround for a reputed Wine bug. */ ! static inline char * fixed_getenv(const char *name) ! { ! char * tmp = getenv(name); ! if (tmp == 0 || strlen(tmp) == 0) ! return 0; ! return tmp; ! } ! # define GETENV(name) fixed_getenv(name) ! # else ! # define GETENV(name) getenv(name) ! # endif #else # define GETENV(name) 0 #endif *************** extern GC_warn_proc GC_current_warn_proc *** 646,654 **** */ # ifdef LARGE_CONFIG ! # define LOG_PHT_ENTRIES 19 /* Collisions likely at 512K blocks, */ ! /* which is >= 2GB. Each table takes */ ! /* 64KB. */ # else # ifdef SMALL_CONFIG # define LOG_PHT_ENTRIES 14 /* Collisions are likely if heap grows */ --- 602,611 ---- */ # ifdef LARGE_CONFIG ! # define LOG_PHT_ENTRIES 20 /* Collisions likely at 1M blocks, */ ! /* which is >= 4GB. Each table takes */ ! /* 128KB, some of which may never be */ ! /* touched. */ # else # ifdef SMALL_CONFIG # define LOG_PHT_ENTRIES 14 /* Collisions are likely if heap grows */ *************** extern GC_warn_proc GC_current_warn_proc *** 656,662 **** /* Each hash table occupies 2K bytes. */ # else /* default "medium" configuration */ # define LOG_PHT_ENTRIES 16 /* Collisions are likely if heap grows */ ! /* to more than 16K hblks >= 256MB. */ /* Each hash table occupies 8K bytes. */ # endif # endif --- 613,619 ---- /* Each hash table occupies 2K bytes. */ # else /* default "medium" configuration */ # define LOG_PHT_ENTRIES 16 /* Collisions are likely if heap grows */ ! /* to more than 64K hblks >= 256MB. */ /* Each hash table occupies 8K bytes. */ # endif # endif *************** struct _GC_arrays { *** 897,902 **** --- 854,863 ---- word _mem_freed; /* Number of explicitly deallocated words of memory */ /* since last collection. */ + word _finalizer_mem_freed; + /* Words of memory explicitly deallocated while */ + /* finalizers were running. Used to approximate mem. */ + /* explicitly deallocated by finalizers. */ ptr_t _scratch_end_ptr; ptr_t _scratch_last_end_ptr; /* Used by headers.c, and can easily appear to point to */ *************** struct _GC_arrays { *** 957,963 **** /* OFFSET_TOO_BIG if the value j would be too */ /* large to fit in the entry. (Note that the */ /* size of these entries matters, both for */ ! /* space consumption and for cache utilization. */ # define OFFSET_TOO_BIG 0xfe # define OBJ_INVALID 0xff # define MAP_ENTRY(map, bytes) (map)[bytes] --- 918,924 ---- /* OFFSET_TOO_BIG if the value j would be too */ /* large to fit in the entry. (Note that the */ /* size of these entries matters, both for */ ! /* space consumption and for cache utilization.) */ # define OFFSET_TOO_BIG 0xfe # define OBJ_INVALID 0xff # define MAP_ENTRY(map, bytes) (map)[bytes] *************** GC_API GC_FAR struct _GC_arrays GC_array *** 1067,1072 **** --- 1028,1034 ---- # define GC_words_finalized GC_arrays._words_finalized # define GC_non_gc_bytes_at_gc GC_arrays._non_gc_bytes_at_gc # define GC_mem_freed GC_arrays._mem_freed + # define GC_finalizer_mem_freed GC_arrays._finalizer_mem_freed # define GC_scratch_end_ptr GC_arrays._scratch_end_ptr # define GC_scratch_last_end_ptr GC_arrays._scratch_last_end_ptr # define GC_mark_procs GC_arrays._mark_procs *************** extern struct hblk * GC_hblkfreelist[]; *** 1201,1217 **** /* header structure associated with */ /* block. */ - extern GC_bool GC_is_initialized; /* GC_init() has been run. */ - extern GC_bool GC_objects_are_marked; /* There are marked objects in */ /* the heap. */ #ifndef SMALL_CONFIG extern GC_bool GC_incremental; /* Using incremental/generational collection. */ #else # define GC_incremental FALSE /* Hopefully allow optimizer to remove some code. */ #endif extern GC_bool GC_dirty_maintained; --- 1163,1181 ---- /* header structure associated with */ /* block. */ extern GC_bool GC_objects_are_marked; /* There are marked objects in */ /* the heap. */ #ifndef SMALL_CONFIG extern GC_bool GC_incremental; /* Using incremental/generational collection. */ + # define TRUE_INCREMENTAL \ + (GC_incremental && GC_time_limit != GC_TIME_UNLIMITED) + /* True incremental, not just generational, mode */ #else # define GC_incremental FALSE /* Hopefully allow optimizer to remove some code. */ + # define TRUE_INCREMENTAL FALSE #endif extern GC_bool GC_dirty_maintained; *************** extern long GC_large_alloc_warn_interval *** 1229,1234 **** --- 1193,1202 ---- extern long GC_large_alloc_warn_suppressed; /* Number of warnings suppressed so far. */ + #ifdef THREADS + extern GC_bool GC_world_stopped; + #endif + /* Operations */ # ifndef abs # define abs(x) ((x) < 0? (-(x)) : (x)) *************** extern void (*GC_start_call_back) GC_PRO *** 1403,1408 **** --- 1371,1381 ---- # else void GC_push_regs GC_PROTO((void)); # endif + # if defined(SPARC) || defined(IA64) + /* Cause all stacked registers to be saved in memory. Return a */ + /* pointer to the top of the corresponding memory stack. */ + word GC_save_regs_in_stack GC_PROTO((void)); + # endif /* Push register contents onto mark stack. */ /* If NURSERY is defined, the default push */ /* action can be overridden with GC_push_proc */ *************** void GC_set_fl_marks GC_PROTO((ptr_t p)) *** 1452,1457 **** --- 1425,1431 ---- /* Set all mark bits associated with */ /* a free list. */ void GC_add_roots_inner GC_PROTO((char * b, char * e, GC_bool tmp)); + void GC_remove_roots_inner GC_PROTO((char * b, char * e)); GC_bool GC_is_static_root GC_PROTO((ptr_t p)); /* Is the address p in one of the registered static */ /* root sections? */ *************** GC_bool GC_is_tmp_root GC_PROTO((ptr_t p *** 1462,1472 **** # endif void GC_register_dynamic_libraries GC_PROTO((void)); /* Add dynamic library data sections to the root set. */ - GC_bool GC_register_main_static_data GC_PROTO((void)); ! /* We need to register the main data segment. Returns */ ! /* TRUE unless this is done implicitly as part of */ ! /* dynamic library registration. */ /* Machine dependent startup routines */ ptr_t GC_get_stack_base GC_PROTO((void)); /* Cold end of stack */ --- 1436,1445 ---- # endif void GC_register_dynamic_libraries GC_PROTO((void)); /* Add dynamic library data sections to the root set. */ GC_bool GC_register_main_static_data GC_PROTO((void)); ! /* We need to register the main data segment. Returns */ ! /* TRUE unless this is done implicitly as part of */ ! /* dynamic library registration. */ /* Machine dependent startup routines */ ptr_t GC_get_stack_base GC_PROTO((void)); /* Cold end of stack */ *************** GC_bool GC_collect_or_expand GC_PROTO(( *** 1624,1629 **** --- 1597,1604 ---- /* until the blocks are available or */ /* until it fails by returning FALSE. */ + extern GC_bool GC_is_initialized; /* GC_init() has been run. */ + #if defined(MSWIN32) || defined(MSWINCE) void GC_deinit GC_PROTO((void)); /* Free any resources allocated by */ *************** ptr_t GC_allocobj GC_PROTO((word sz, int *** 1665,1670 **** --- 1640,1647 ---- /* Make the indicated */ /* free list nonempty, and return its */ /* head. */ + + void GC_free_inner(GC_PTR p); void GC_init_headers GC_PROTO((void)); struct hblkhdr * GC_install_header GC_PROTO((struct hblk *h)); *************** void GC_notify_or_invoke_finalizers GC_P *** 1694,1699 **** --- 1671,1682 ---- /* Call *GC_finalizer_notifier if there are */ /* finalizers to be run, and we haven't called */ /* this procedure yet this GC cycle. */ + + GC_API GC_PTR GC_make_closure GC_PROTO((GC_finalization_proc fn, GC_PTR data)); + GC_API void GC_debug_invoke_finalizer GC_PROTO((GC_PTR obj, GC_PTR data)); + /* Auxiliary fns to make finalization work */ + /* correctly with displaced pointers introduced */ + /* by the debugging allocators. */ void GC_add_to_heap GC_PROTO((struct hblk *p, word bytes)); /* Add a HBLKSIZE aligned chunk to the heap. */ *************** void GC_print_obj GC_PROTO((ptr_t p)); *** 1704,1719 **** /* description of the object to stderr. */ extern void (*GC_check_heap) GC_PROTO((void)); /* Check that all objects in the heap with */ ! /* debugging info are intact. Print */ ! /* descriptions of any that are not. */ extern void (*GC_print_heap_obj) GC_PROTO((ptr_t p)); /* If possible print s followed by a more */ /* detailed description of the object */ /* referred to by p. */ extern GC_bool GC_print_stats; /* Produce at least some logging output */ /* Set from environment variable. */ /* Macros used for collector internal allocation. */ /* These assume the collector lock is held. */ #ifdef DBG_HDRS_ALL --- 1687,1722 ---- /* description of the object to stderr. */ extern void (*GC_check_heap) GC_PROTO((void)); /* Check that all objects in the heap with */ ! /* debugging info are intact. */ ! /* Add any that are not to GC_smashed list. */ ! extern void (*GC_print_all_smashed) GC_PROTO((void)); ! /* Print GC_smashed if it's not empty. */ ! /* Clear GC_smashed list. */ ! extern void GC_print_all_errors GC_PROTO((void)); ! /* Print smashed and leaked objects, if any. */ ! /* Clear the lists of such objects. */ extern void (*GC_print_heap_obj) GC_PROTO((ptr_t p)); /* If possible print s followed by a more */ /* detailed description of the object */ /* referred to by p. */ + #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) + void GC_print_address_map GC_PROTO((void)); + /* Print an address map of the process. */ + #endif + extern GC_bool GC_have_errors; /* We saw a smashed or leaked object. */ + /* Call error printing routine */ + /* occasionally. */ extern GC_bool GC_print_stats; /* Produce at least some logging output */ /* Set from environment variable. */ + #ifndef NO_DEBUGGING + extern GC_bool GC_dump_regularly; /* Generate regular debugging dumps. */ + # define COND_DUMP if (GC_dump_regularly) GC_dump(); + #else + # define COND_DUMP + #endif + /* Macros used for collector internal allocation. */ /* These assume the collector lock is held. */ #ifdef DBG_HDRS_ALL *************** void GC_print_block_list GC_PROTO((void) *** 1785,1790 **** --- 1788,1794 ---- void GC_print_hblkfreelist GC_PROTO((void)); void GC_print_heap_sects GC_PROTO((void)); void GC_print_static_roots GC_PROTO((void)); + void GC_print_finalization_stats GC_PROTO((void)); void GC_dump GC_PROTO((void)); #ifdef KEEP_BACK_PTRS *************** void GC_err_puts GC_PROTO((GC_CONST char *** 1866,1871 **** --- 1870,1885 ---- # define GC_ASSERT(expr) # endif + /* Check a compile time assertion at compile time. The error */ + /* message for failure is a bit baroque, but ... */ + #if defined(mips) && !defined(__GNUC__) + /* DOB: MIPSPro C gets an internal error taking the sizeof an array type. + This code works correctly (ugliness is to avoid "unused var" warnings) */ + # define GC_STATIC_ASSERT(expr) do { if (0) { char j[(expr)? 1 : -1]; j[0]='\0'; j[0]=j[0]; } } while(0) + #else + # define GC_STATIC_ASSERT(expr) sizeof(char[(expr)? 1 : -1]) + #endif + # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) /* We need additional synchronization facilities from the thread */ /* support. We believe these are less performance critical */ *************** void GC_err_puts GC_PROTO((GC_CONST char *** 1911,1917 **** /* in Linux glibc, but it's not exported.) Thus we continue to use */ /* the same hard-coded signals we've always used. */ # if !defined(SIG_SUSPEND) ! # if defined(GC_LINUX_THREADS) # if defined(SPARC) && !defined(SIGPWR) /* SPARC/Linux doesn't properly define SIGPWR in . * It is aliased to SIGLOST in asm/signal.h, though. */ --- 1925,1931 ---- /* in Linux glibc, but it's not exported.) Thus we continue to use */ /* the same hard-coded signals we've always used. */ # if !defined(SIG_SUSPEND) ! # if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS) # if defined(SPARC) && !defined(SIGPWR) /* SPARC/Linux doesn't properly define SIGPWR in . * It is aliased to SIGLOST in asm/signal.h, though. */ diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/pthread_stop_world.h gcc-3.4.0/boehm-gc/include/private/pthread_stop_world.h *** gcc-3.3.3/boehm-gc/include/private/pthread_stop_world.h 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/pthread_stop_world.h 2003-07-28 03:46:18.000000000 +0000 *************** *** 0 **** --- 1,12 ---- + #ifndef GC_PTHREAD_STOP_WORLD_H + #define GC_PTHREAD_STOP_WORLD_H + + struct thread_stop_info { + int signal; + word last_stop_count; /* GC_last_stop_count value when thread */ + /* last successfully handled a suspend */ + /* signal. */ + ptr_t stack_ptr; /* Valid only when stopped. */ + }; + + #endif diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/pthread_support.h gcc-3.4.0/boehm-gc/include/private/pthread_support.h *** gcc-3.3.3/boehm-gc/include/private/pthread_support.h 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/pthread_support.h 2003-07-28 03:46:18.000000000 +0000 *************** *** 0 **** --- 1,97 ---- + #ifndef GC_PTHREAD_SUPPORT_H + #define GC_PTHREAD_SUPPORT_H + + # include "private/gc_priv.h" + + # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ + && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) + + #if defined(GC_DARWIN_THREADS) + # include "private/darwin_stop_world.h" + #else + # include "private/pthread_stop_world.h" + #endif + + /* We use the allocation lock to protect thread-related data structures. */ + + /* The set of all known threads. We intercept thread creation and */ + /* joins. */ + /* Protected by allocation/GC lock. */ + /* Some of this should be declared volatile, but that's inconsistent */ + /* with some library routine declarations. */ + typedef struct GC_Thread_Rep { + struct GC_Thread_Rep * next; /* More recently allocated threads */ + /* with a given pthread id come */ + /* first. (All but the first are */ + /* guaranteed to be dead, but we may */ + /* not yet have registered the join.) */ + pthread_t id; + /* Extra bookkeeping information the stopping code uses */ + struct thread_stop_info stop_info; + + short flags; + # define FINISHED 1 /* Thread has exited. */ + # define DETACHED 2 /* Thread is intended to be detached. */ + # define MAIN_THREAD 4 /* True for the original thread only. */ + short thread_blocked; /* Protected by GC lock. */ + /* Treated as a boolean value. If set, */ + /* thread will acquire GC lock before */ + /* doing any pointer manipulations, and */ + /* has set its sp value. Thus it does */ + /* not need to be sent a signal to stop */ + /* it. */ + ptr_t stack_end; /* Cold end of the stack. */ + # ifdef IA64 + ptr_t backing_store_end; + ptr_t backing_store_ptr; + # endif + void * status; /* The value returned from the thread. */ + /* Used only to avoid premature */ + /* reclamation of any data it might */ + /* reference. */ + # ifdef THREAD_LOCAL_ALLOC + # if CPP_WORDSZ == 64 && defined(ALIGN_DOUBLE) + # define GRANULARITY 16 + # define NFREELISTS 49 + # else + # define GRANULARITY 8 + # define NFREELISTS 65 + # endif + /* The ith free list corresponds to size i*GRANULARITY */ + # define INDEX_FROM_BYTES(n) ((ADD_SLOP(n) + GRANULARITY - 1)/GRANULARITY) + # define BYTES_FROM_INDEX(i) ((i) * GRANULARITY - EXTRA_BYTES) + # define SMALL_ENOUGH(bytes) (ADD_SLOP(bytes) <= \ + (NFREELISTS-1)*GRANULARITY) + ptr_t ptrfree_freelists[NFREELISTS]; + ptr_t normal_freelists[NFREELISTS]; + # ifdef GC_GCJ_SUPPORT + ptr_t gcj_freelists[NFREELISTS]; + # endif + /* Free lists contain either a pointer or a small count */ + /* reflecting the number of granules allocated at that */ + /* size. */ + /* 0 ==> thread-local allocation in use, free list */ + /* empty. */ + /* > 0, <= DIRECT_GRANULES ==> Using global allocation, */ + /* too few objects of this size have been */ + /* allocated by this thread. */ + /* >= HBLKSIZE => pointer to nonempty free list. */ + /* > DIRECT_GRANULES, < HBLKSIZE ==> transition to */ + /* local alloc, equivalent to 0. */ + # define DIRECT_GRANULES (HBLKSIZE/GRANULARITY) + /* Don't use local free lists for up to this much */ + /* allocation. */ + # endif + } * GC_thread; + + # define THREAD_TABLE_SZ 128 /* Must be power of 2 */ + extern volatile GC_thread GC_threads[THREAD_TABLE_SZ]; + + extern GC_bool GC_thr_initialized; + + GC_thread GC_lookup_thread(pthread_t id); + + void GC_stop_init(); + + #endif /* GC_PTHREADS && !GC_SOLARIS_THREADS.... etc */ + #endif /* GC_PTHREAD_SUPPORT_H */ diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/solaris_threads.h gcc-3.4.0/boehm-gc/include/private/solaris_threads.h *** gcc-3.3.3/boehm-gc/include/private/solaris_threads.h 2001-10-23 23:21:39.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/solaris_threads.h 2003-07-28 04:18:23.000000000 +0000 *************** *** 16,22 **** # define DETACHED 2 /* Thread is intended to be detached. */ # define CLIENT_OWNS_STACK 4 /* Stack was supplied by client. */ ! # define SUSPENDED 8 /* Currently suspended. */ ptr_t stack; size_t stack_size; cond_t join_cv; --- 16,23 ---- # define DETACHED 2 /* Thread is intended to be detached. */ # define CLIENT_OWNS_STACK 4 /* Stack was supplied by client. */ ! # define SUSPNDED 8 /* Currently suspended. */ ! /* SUSPENDED is used insystem header. */ ptr_t stack; size_t stack_size; cond_t join_cv; diff -Nrc3pad gcc-3.3.3/boehm-gc/include/private/specific.h gcc-3.4.0/boehm-gc/include/private/specific.h *** gcc-3.3.3/boehm-gc/include/private/specific.h 2002-03-29 22:52:13.000000000 +0000 --- gcc-3.4.0/boehm-gc/include/private/specific.h 2003-07-28 04:18:23.000000000 +0000 *************** static __inline__ void * PREFIXED(getspe *** 85,91 **** unsigned hash_val = CACHE_HASH(qtid); tse * volatile * entry_ptr = key -> cache + hash_val; tse * entry = *entry_ptr; /* Must be loaded only once. */ ! if (entry -> qtid == qtid) { GC_ASSERT(entry -> thread == pthread_self()); return entry -> value; } --- 85,91 ---- unsigned hash_val = CACHE_HASH(qtid); tse * volatile * entry_ptr = key -> cache + hash_val; tse * entry = *entry_ptr; /* Must be loaded only once. */ ! if (EXPECT(entry -> qtid == qtid, 1)) { GC_ASSERT(entry -> thread == pthread_self()); return entry -> value; } diff -Nrc3pad gcc-3.3.3/boehm-gc/irix_threads.c gcc-3.4.0/boehm-gc/irix_threads.c *** gcc-3.3.3/boehm-gc/irix_threads.c 2002-05-19 17:36:14.000000000 +0000 --- gcc-3.4.0/boehm-gc/irix_threads.c 1970-01-01 00:00:00.000000000 +0000 *************** *** 1,726 **** - /* - * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. - * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. - * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved. - * - * 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. - */ - /* - * Support code for Irix (>=6.2) Pthreads. This relies on properties - * not guaranteed by the Pthread standard. It may or may not be portable - * to other implementations. - * - * This now also includes an initial attempt at thread support for - * HP/UX 11. - * - * Note that there is a lot of code duplication between linux_threads.c - * and irix_threads.c; any changes made here may need to be reflected - * there too. - */ - - # if defined(GC_IRIX_THREADS) - - # include "private/gc_priv.h" - # include - # include - # include - # include - # include - # include - # include - - #undef pthread_create - #undef pthread_sigmask - #undef pthread_join - #undef pthread_detach - - void GC_thr_init(); - - #if 0 - void GC_print_sig_mask() - { - sigset_t blocked; - int i; - - if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0) - ABORT("pthread_sigmask"); - GC_printf0("Blocked: "); - for (i = 1; i <= MAXSIG; i++) { - if (sigismember(&blocked, i)) { GC_printf1("%ld ",(long) i); } - } - GC_printf0("\n"); - } - #endif - - /* We use the allocation lock to protect thread-related data structures. */ - - /* The set of all known threads. We intercept thread creation and */ - /* joins. We never actually create detached threads. We allocate all */ - /* new thread stacks ourselves. These allow us to maintain this */ - /* data structure. */ - /* Protected by GC_thr_lock. */ - /* Some of this should be declared volatile, but that's incosnsistent */ - /* with some library routine declarations. */ - typedef struct GC_Thread_Rep { - struct GC_Thread_Rep * next; /* More recently allocated threads */ - /* with a given pthread id come */ - /* first. (All but the first are */ - /* guaranteed to be dead, but we may */ - /* not yet have registered the join.) */ - pthread_t id; - word stop; - # define NOT_STOPPED 0 - # define PLEASE_STOP 1 - # define STOPPED 2 - word flags; - # define FINISHED 1 /* Thread has exited. */ - # define DETACHED 2 /* Thread is intended to be detached. */ - # define CLIENT_OWNS_STACK 4 - /* Stack was supplied by client. */ - ptr_t stack; - ptr_t stack_ptr; /* Valid only when stopped. */ - /* But must be within stack region at */ - /* all times. */ - size_t stack_size; /* 0 for original thread. */ - void * status; /* Used only to avoid premature */ - /* reclamation of any data it might */ - /* reference. */ - } * GC_thread; - - GC_thread GC_lookup_thread(pthread_t id); - - /* - * The only way to suspend threads given the pthread interface is to send - * signals. Unfortunately, this means we have to reserve - * a signal, and intercept client calls to change the signal mask. - * We use SIG_SUSPEND, defined in gc_priv.h. - */ - - pthread_mutex_t GC_suspend_lock = PTHREAD_MUTEX_INITIALIZER; - /* Number of threads stopped so far */ - pthread_cond_t GC_suspend_ack_cv = PTHREAD_COND_INITIALIZER; - pthread_cond_t GC_continue_cv = PTHREAD_COND_INITIALIZER; - - void GC_suspend_handler(int sig) - { - int dummy; - GC_thread me; - sigset_t all_sigs; - sigset_t old_sigs; - int i; - - if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler"); - me = GC_lookup_thread(pthread_self()); - /* The lookup here is safe, since I'm doing this on behalf */ - /* of a thread which holds the allocation lock in order */ - /* to stop the world. Thus concurrent modification of the */ - /* data structure is impossible. */ - if (PLEASE_STOP != me -> stop) { - /* Misdirected signal. */ - pthread_mutex_unlock(&GC_suspend_lock); - return; - } - pthread_mutex_lock(&GC_suspend_lock); - me -> stack_ptr = (ptr_t)(&dummy); - me -> stop = STOPPED; - pthread_cond_signal(&GC_suspend_ack_cv); - pthread_cond_wait(&GC_continue_cv, &GC_suspend_lock); - pthread_mutex_unlock(&GC_suspend_lock); - /* GC_printf1("Continuing 0x%x\n", pthread_self()); */ - } - - - GC_bool GC_thr_initialized = FALSE; - - size_t GC_min_stack_sz; - - # define N_FREE_LISTS 25 - ptr_t GC_stack_free_lists[N_FREE_LISTS] = { 0 }; - /* GC_stack_free_lists[i] is free list for stacks of */ - /* size GC_min_stack_sz*2**i. */ - /* Free lists are linked through first word. */ - - /* Return a stack of size at least *stack_size. *stack_size is */ - /* replaced by the actual stack size. */ - /* Caller holds allocation lock. */ - ptr_t GC_stack_alloc(size_t * stack_size) - { - register size_t requested_sz = *stack_size; - register size_t search_sz = GC_min_stack_sz; - register int index = 0; /* = log2(search_sz/GC_min_stack_sz) */ - register ptr_t result; - - while (search_sz < requested_sz) { - search_sz *= 2; - index++; - } - if ((result = GC_stack_free_lists[index]) == 0 - && (result = GC_stack_free_lists[index+1]) != 0) { - /* Try next size up. */ - search_sz *= 2; index++; - } - if (result != 0) { - GC_stack_free_lists[index] = *(ptr_t *)result; - } else { - result = (ptr_t) GC_scratch_alloc(search_sz + 2*GC_page_size); - result = (ptr_t)(((word)result + GC_page_size) & ~(GC_page_size - 1)); - /* Protect hottest page to detect overflow. */ - # ifdef STACK_GROWS_UP - /* mprotect(result + search_sz, GC_page_size, PROT_NONE); */ - # else - /* mprotect(result, GC_page_size, PROT_NONE); */ - result += GC_page_size; - # endif - } - *stack_size = search_sz; - return(result); - } - - /* Caller holds allocation lock. */ - void GC_stack_free(ptr_t stack, size_t size) - { - register int index = 0; - register size_t search_sz = GC_min_stack_sz; - - while (search_sz < size) { - search_sz *= 2; - index++; - } - if (search_sz != size) ABORT("Bad stack size"); - *(ptr_t *)stack = GC_stack_free_lists[index]; - GC_stack_free_lists[index] = stack; - } - - - - # define THREAD_TABLE_SZ 128 /* Must be power of 2 */ - volatile GC_thread GC_threads[THREAD_TABLE_SZ]; - - void GC_push_thread_structures GC_PROTO((void)) - { - GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads)); - } - - /* Add a thread to GC_threads. We assume it wasn't already there. */ - /* Caller holds allocation lock. */ - GC_thread GC_new_thread(pthread_t id) - { - int hv = ((word)id) % THREAD_TABLE_SZ; - GC_thread result; - static struct GC_Thread_Rep first_thread; - static GC_bool first_thread_used = FALSE; - - if (!first_thread_used) { - result = &first_thread; - first_thread_used = TRUE; - /* Dont acquire allocation lock, since we may already hold it. */ - } else { - result = (struct GC_Thread_Rep *) - GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL); - } - if (result == 0) return(0); - result -> id = id; - result -> next = GC_threads[hv]; - GC_threads[hv] = result; - /* result -> flags = 0; */ - /* result -> stop = 0; */ - return(result); - } - - /* Delete a thread from GC_threads. We assume it is there. */ - /* (The code intentionally traps if it wasn't.) */ - /* Caller holds allocation lock. */ - void GC_delete_thread(pthread_t id) - { - int hv = ((word)id) % THREAD_TABLE_SZ; - register GC_thread p = GC_threads[hv]; - register GC_thread prev = 0; - - while (!pthread_equal(p -> id, id)) { - prev = p; - p = p -> next; - } - if (prev == 0) { - GC_threads[hv] = p -> next; - } else { - prev -> next = p -> next; - } - } - - /* If a thread has been joined, but we have not yet */ - /* been notified, then there may be more than one thread */ - /* in the table with the same pthread id. */ - /* This is OK, but we need a way to delete a specific one. */ - void GC_delete_gc_thread(pthread_t id, GC_thread gc_id) - { - int hv = ((word)id) % THREAD_TABLE_SZ; - register GC_thread p = GC_threads[hv]; - register GC_thread prev = 0; - - while (p != gc_id) { - prev = p; - p = p -> next; - } - if (prev == 0) { - GC_threads[hv] = p -> next; - } else { - prev -> next = p -> next; - } - } - - /* Return a GC_thread corresponding to a given thread_t. */ - /* Returns 0 if it's not there. */ - /* Caller holds allocation lock or otherwise inhibits */ - /* updates. */ - /* If there is more than one thread with the given id we */ - /* return the most recent one. */ - GC_thread GC_lookup_thread(pthread_t id) - { - int hv = ((word)id) % THREAD_TABLE_SZ; - register GC_thread p = GC_threads[hv]; - - while (p != 0 && !pthread_equal(p -> id, id)) p = p -> next; - return(p); - } - - - /* Caller holds allocation lock. */ - void GC_stop_world() - { - pthread_t my_thread = pthread_self(); - register int i; - register GC_thread p; - register int result; - struct timespec timeout; - - for (i = 0; i < THREAD_TABLE_SZ; i++) { - for (p = GC_threads[i]; p != 0; p = p -> next) { - if (p -> id != my_thread) { - if (p -> flags & FINISHED) { - p -> stop = STOPPED; - continue; - } - p -> stop = PLEASE_STOP; - result = pthread_kill(p -> id, SIG_SUSPEND); - /* GC_printf1("Sent signal to 0x%x\n", p -> id); */ - switch(result) { - case ESRCH: - /* Not really there anymore. Possible? */ - p -> stop = STOPPED; - break; - case 0: - break; - default: - ABORT("pthread_kill failed"); - } - } - } - } - pthread_mutex_lock(&GC_suspend_lock); - for (i = 0; i < THREAD_TABLE_SZ; i++) { - for (p = GC_threads[i]; p != 0; p = p -> next) { - while (p -> id != my_thread && p -> stop != STOPPED) { - clock_gettime(CLOCK_REALTIME, &timeout); - timeout.tv_nsec += 50000000; /* 50 msecs */ - if (timeout.tv_nsec >= 1000000000) { - timeout.tv_nsec -= 1000000000; - ++timeout.tv_sec; - } - result = pthread_cond_timedwait(&GC_suspend_ack_cv, - &GC_suspend_lock, - &timeout); - if (result == ETIMEDOUT) { - /* Signal was lost or misdirected. Try again. */ - /* Duplicate signals should be benign. */ - result = pthread_kill(p -> id, SIG_SUSPEND); - } - } - } - } - pthread_mutex_unlock(&GC_suspend_lock); - /* GC_printf1("World stopped 0x%x\n", pthread_self()); */ - } - - /* Caller holds allocation lock. */ - void GC_start_world() - { - GC_thread p; - unsigned i; - - /* GC_printf0("World starting\n"); */ - for (i = 0; i < THREAD_TABLE_SZ; i++) { - for (p = GC_threads[i]; p != 0; p = p -> next) { - p -> stop = NOT_STOPPED; - } - } - pthread_mutex_lock(&GC_suspend_lock); - /* All other threads are at pthread_cond_wait in signal handler. */ - /* Otherwise we couldn't have acquired the lock. */ - pthread_mutex_unlock(&GC_suspend_lock); - pthread_cond_broadcast(&GC_continue_cv); - } - - # ifdef MMAP_STACKS - --> not really supported yet. - int GC_is_thread_stack(ptr_t addr) - { - register int i; - register GC_thread p; - - for (i = 0; i < THREAD_TABLE_SZ; i++) { - for (p = GC_threads[i]; p != 0; p = p -> next) { - if (p -> stack_size != 0) { - if (p -> stack <= addr && - addr < p -> stack + p -> stack_size) - return 1; - } - } - } - return 0; - } - # endif - - /* We hold allocation lock. Should do exactly the right thing if the */ - /* world is stopped. Should not fail if it isn't. */ - void GC_push_all_stacks() - { - register int i; - register GC_thread p; - register ptr_t sp = GC_approx_sp(); - register ptr_t hot, cold; - pthread_t me = pthread_self(); - - if (!GC_thr_initialized) GC_thr_init(); - /* GC_printf1("Pushing stacks from thread 0x%x\n", me); */ - for (i = 0; i < THREAD_TABLE_SZ; i++) { - for (p = GC_threads[i]; p != 0; p = p -> next) { - if (p -> flags & FINISHED) continue; - if (pthread_equal(p -> id, me)) { - hot = GC_approx_sp(); - } else { - hot = p -> stack_ptr; - } - if (p -> stack_size != 0) { - # ifdef STACK_GROWS_UP - cold = p -> stack; - # else - cold = p -> stack + p -> stack_size; - # endif - } else { - /* The original stack. */ - cold = GC_stackbottom; - } - # ifdef STACK_GROWS_UP - GC_push_all_stack(cold, hot); - # else - GC_push_all_stack(hot, cold); - # endif - } - } - } - - - /* We hold the allocation lock. */ - void GC_thr_init() - { - GC_thread t; - struct sigaction act; - - if (GC_thr_initialized) return; - GC_thr_initialized = TRUE; - GC_min_stack_sz = HBLKSIZE; - (void) sigaction(SIG_SUSPEND, 0, &act); - if (act.sa_handler != SIG_DFL) - ABORT("Previously installed SIG_SUSPEND handler"); - /* Install handler. */ - act.sa_handler = GC_suspend_handler; - act.sa_flags = SA_RESTART; - (void) sigemptyset(&act.sa_mask); - if (0 != sigaction(SIG_SUSPEND, &act, 0)) - ABORT("Failed to install SIG_SUSPEND handler"); - /* Add the initial thread, so we can stop it. */ - t = GC_new_thread(pthread_self()); - t -> stack_size = 0; - t -> stack_ptr = (ptr_t)(&t); - t -> flags = DETACHED; - } - - int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) - { - sigset_t fudged_set; - - if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) { - fudged_set = *set; - sigdelset(&fudged_set, SIG_SUSPEND); - set = &fudged_set; - } - return(pthread_sigmask(how, set, oset)); - } - - struct start_info { - void *(*start_routine)(void *); - void *arg; - word flags; - ptr_t stack; - size_t stack_size; - sem_t registered; /* 1 ==> in our thread table, but */ - /* parent hasn't yet noticed. */ - }; - - void GC_thread_exit_proc(void *arg) - { - GC_thread me; - - LOCK(); - me = GC_lookup_thread(pthread_self()); - if (me -> flags & DETACHED) { - GC_delete_thread(pthread_self()); - } else { - me -> flags |= FINISHED; - } - UNLOCK(); - } - - int GC_pthread_join(pthread_t thread, void **retval) - { - int result; - GC_thread thread_gc_id; - - LOCK(); - thread_gc_id = GC_lookup_thread(thread); - /* This is guaranteed to be the intended one, since the thread id */ - /* cant have been recycled by pthreads. */ - UNLOCK(); - result = pthread_join(thread, retval); - /* Some versions of the Irix pthreads library can erroneously */ - /* return EINTR when the call succeeds. */ - if (EINTR == result) result = 0; - if (result == 0) { - LOCK(); - /* Here the pthread thread id may have been recycled. */ - GC_delete_gc_thread(thread, thread_gc_id); - UNLOCK(); - } - return result; - } - - int GC_pthread_detach(pthread_t thread) - { - int result; - GC_thread thread_gc_id; - - LOCK(); - thread_gc_id = GC_lookup_thread(thread); - UNLOCK(); - result = pthread_detach(thread); - if (result == 0) { - LOCK(); - thread_gc_id -> flags |= DETACHED; - /* Here the pthread thread id may have been recycled. */ - if (thread_gc_id -> flags & FINISHED) { - GC_delete_gc_thread(thread, thread_gc_id); - } - UNLOCK(); - } - return result; - } - - void * GC_start_routine(void * arg) - { - struct start_info * si = arg; - void * result; - GC_thread me; - pthread_t my_pthread; - void *(*start)(void *); - void *start_arg; - - my_pthread = pthread_self(); - /* If a GC occurs before the thread is registered, that GC will */ - /* ignore this thread. That's fine, since it will block trying to */ - /* acquire the allocation lock, and won't yet hold interesting */ - /* pointers. */ - LOCK(); - /* We register the thread here instead of in the parent, so that */ - /* we don't need to hold the allocation lock during pthread_create. */ - /* Holding the allocation lock there would make REDIRECT_MALLOC */ - /* impossible. It probably still doesn't work, but we're a little */ - /* closer ... */ - /* This unfortunately means that we have to be careful the parent */ - /* doesn't try to do a pthread_join before we're registered. */ - me = GC_new_thread(my_pthread); - me -> flags = si -> flags; - me -> stack = si -> stack; - me -> stack_size = si -> stack_size; - me -> stack_ptr = (ptr_t)si -> stack + si -> stack_size - sizeof(word); - UNLOCK(); - start = si -> start_routine; - start_arg = si -> arg; - sem_post(&(si -> registered)); - pthread_cleanup_push(GC_thread_exit_proc, 0); - result = (*start)(start_arg); - me -> status = result; - me -> flags |= FINISHED; - pthread_cleanup_pop(1); - /* This involves acquiring the lock, ensuring that we can't exit */ - /* while a collection that thinks we're alive is trying to stop */ - /* us. */ - return(result); - } - - # define copy_attr(pa_ptr, source) *(pa_ptr) = *(source) - - int - GC_pthread_create(pthread_t *new_thread, - const pthread_attr_t *attr, - void *(*start_routine)(void *), void *arg) - { - int result; - GC_thread t; - void * stack; - size_t stacksize; - pthread_attr_t new_attr; - int detachstate; - word my_flags = 0; - struct start_info * si = GC_malloc(sizeof(struct start_info)); - /* This is otherwise saved only in an area mmapped by the thread */ - /* library, which isn't visible to the collector. */ - - if (0 == si) return(ENOMEM); - if (0 != sem_init(&(si -> registered), 0, 0)) { - ABORT("sem_init failed"); - } - si -> start_routine = start_routine; - si -> arg = arg; - LOCK(); - if (!GC_is_initialized) GC_init(); - if (NULL == attr) { - stack = 0; - (void) pthread_attr_init(&new_attr); - } else { - copy_attr(&new_attr, attr); - pthread_attr_getstackaddr(&new_attr, &stack); - } - pthread_attr_getstacksize(&new_attr, &stacksize); - pthread_attr_getdetachstate(&new_attr, &detachstate); - if (stacksize < GC_min_stack_sz) ABORT("Stack too small"); - if (0 == stack) { - stack = (void *)GC_stack_alloc(&stacksize); - if (0 == stack) { - UNLOCK(); - return(ENOMEM); - } - pthread_attr_setstackaddr(&new_attr, stack); - } else { - my_flags |= CLIENT_OWNS_STACK; - } - if (PTHREAD_CREATE_DETACHED == detachstate) my_flags |= DETACHED; - si -> flags = my_flags; - si -> stack = stack; - si -> stack_size = stacksize; - result = pthread_create(new_thread, &new_attr, GC_start_routine, si); - if (0 == new_thread && !(my_flags & CLIENT_OWNS_STACK)) { - GC_stack_free(stack, stacksize); - } - UNLOCK(); - /* Wait until child has been added to the thread table. */ - /* This also ensures that we hold onto si until the child is done */ - /* with it. Thus it doesn't matter whether it is otherwise */ - /* visible to the collector. */ - while (0 != sem_wait(&(si -> registered))) { - if (errno != EINTR) { - GC_printf1("Sem_wait: errno = %ld\n", (unsigned long) errno); - ABORT("sem_wait failed"); - } - } - sem_destroy(&(si -> registered)); - pthread_attr_destroy(&new_attr); /* Probably unnecessary under Irix */ - return(result); - } - - VOLATILE GC_bool GC_collecting = 0; - /* A hint that we're in the collector and */ - /* holding the allocation lock for an */ - /* extended period. */ - - /* Reasonably fast spin locks. Basically the same implementation */ - /* as STL alloc.h. */ - - #define SLEEP_THRESHOLD 3 - - unsigned long GC_allocate_lock = 0; - # define GC_TRY_LOCK() !GC_test_and_set(&GC_allocate_lock) - # define GC_LOCK_TAKEN GC_allocate_lock - - void GC_lock() - { - # define low_spin_max 30 /* spin cycles if we suspect uniprocessor */ - # define high_spin_max 1000 /* spin cycles for multiprocessor */ - static unsigned spin_max = low_spin_max; - unsigned my_spin_max; - static unsigned last_spins = 0; - unsigned my_last_spins; - volatile unsigned junk; - # define PAUSE junk *= junk; junk *= junk; junk *= junk; junk *= junk - int i; - - if (GC_TRY_LOCK()) { - return; - } - junk = 0; - my_spin_max = spin_max; - my_last_spins = last_spins; - for (i = 0; i < my_spin_max; i++) { - if (GC_collecting) goto yield; - if (i < my_last_spins/2 || GC_LOCK_TAKEN) { - PAUSE; - continue; - } - if (GC_TRY_LOCK()) { - /* - * got it! - * Spinning worked. Thus we're probably not being scheduled - * against the other process with which we were contending. - * Thus it makes sense to spin longer the next time. - */ - last_spins = i; - spin_max = high_spin_max; - return; - } - } - /* We are probably being scheduled against the other process. Sleep. */ - spin_max = low_spin_max; - yield: - for (i = 0;; ++i) { - if (GC_TRY_LOCK()) { - return; - } - if (i < SLEEP_THRESHOLD) { - sched_yield(); - } else { - struct timespec ts; - - if (i > 26) i = 26; - /* Don't wait for more than about 60msecs, even */ - /* under extreme contention. */ - ts.tv_sec = 0; - ts.tv_nsec = 1 << i; - nanosleep(&ts, 0); - } - } - } - - # else - - #ifndef LINT - int GC_no_Irix_threads; - #endif - - # endif /* GC_IRIX_THREADS */ - --- 0 ---- diff -Nrc3pad gcc-3.3.3/boehm-gc/linux_threads.c gcc-3.4.0/boehm-gc/linux_threads.c *** gcc-3.3.3/boehm-gc/linux_threads.c 2002-03-29 22:52:12.000000000 +0000 --- gcc-3.4.0/boehm-gc/linux_threads.c 1970-01-01 00:00:00.000000000 +0000 *************** *** 1,1735 **** - /* - * Copyright (c) 1994 by Xerox Corporation. All rights reserved. - * Copyright (c) 1996 by Silicon Graphics. All rights reserved. - * Copyright (c) 1998 by Fergus Henderson. All rights reserved. - * Copyright (c) 2000-2001 by Hewlett-Packard Company. All rights reserved. - * - * 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. - */ - /* - * Support code for LinuxThreads, the clone()-based kernel - * thread package for Linux which is included in libc6. - * - * This code relies on implementation details of LinuxThreads, - * (i.e. properties not guaranteed by the Pthread standard), - * though this version now does less of that than the other Pthreads - * support code. - * - * Note that there is a lot of code duplication between linux_threads.c - * and thread support for some of the other Posix platforms; any changes - * made here may need to be reflected there too. - */ - /* - * Linux_threads.c now also includes some code to support HPUX and - * OSF1 (Compaq Tru64 Unix, really). The OSF1 support is not yet - * functional. The OSF1 code is based on Eric Benson's - * patch, though that was originally against hpux_irix_threads. The code - * here is completely untested. With 0.0000001% probability, it might - * actually work. - * - * 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 - */ - - /* #define DEBUG_THREADS 1 */ - - /* ANSI C requires that a compilation unit contains something */ - - # include "gc.h" - - # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ - && !defined(GC_IRIX_THREADS) - - # include "private/gc_priv.h" - - # if defined(GC_HPUX_THREADS) && !defined(USE_PTHREAD_SPECIFIC) \ - && !defined(USE_HPUX_TLS) - # define USE_HPUX_TLS - # endif - - # ifdef THREAD_LOCAL_ALLOC - # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_HPUX_TLS) - # include "private/specific.h" - # endif - # if defined(USE_PTHREAD_SPECIFIC) - # define GC_getspecific pthread_getspecific - # define GC_setspecific pthread_setspecific - # define GC_key_create pthread_key_create - typedef pthread_key_t GC_key_t; - # endif - # if defined(USE_HPUX_TLS) - # define GC_getspecific(x) (x) - # define GC_setspecific(key, v) ((key) = (v), 0) - # define GC_key_create(key, d) 0 - typedef void * GC_key_t; - # endif - # endif - # include - # include - # include - # include - # include - # include - # include - # include - # include - # include - # include - # include - # include - - #ifndef __GNUC__ - # define __inline__ - #endif - - #ifdef GC_USE_LD_WRAP - # define WRAP_FUNC(f) __wrap_##f - # define REAL_FUNC(f) __real_##f - #else - # define WRAP_FUNC(f) GC_##f - # define REAL_FUNC(f) f - # undef pthread_create - # undef pthread_sigmask - # undef pthread_join - # undef pthread_detach - #endif - - - void GC_thr_init(); - - #if 0 - void GC_print_sig_mask() - { - sigset_t blocked; - int i; - - if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0) - ABORT("pthread_sigmask"); - GC_printf0("Blocked: "); - for (i = 1; i <= MAXSIG; i++) { - if (sigismember(&blocked, i)) { GC_printf1("%ld ",(long) i); } - } - GC_printf0("\n"); - } - #endif - - - /* We use the allocation lock to protect thread-related data structures. */ - - /* The set of all known threads. We intercept thread creation and */ - /* joins. */ - /* Protected by allocation/GC lock. */ - /* Some of this should be declared volatile, but that's inconsistent */ - /* with some library routine declarations. */ - typedef struct GC_Thread_Rep { - struct GC_Thread_Rep * next; /* More recently allocated threads */ - /* with a given pthread id come */ - /* first. (All but the first are */ - /* guaranteed to be dead, but we may */ - /* not yet have registered the join.) */ - pthread_t id; - short flags; - # define FINISHED 1 /* Thread has exited. */ - # define DETACHED 2 /* Thread is intended to be detached. */ - # define MAIN_THREAD 4 /* True for the original thread only. */ - short thread_blocked; /* Protected by GC lock. */ - /* Treated as a boolean value. If set, */ - /* thread will acquire GC lock before */ - /* doing any pointer manipulations, and */ - /* has set its sp value. Thus it does */ - /* not need to be sent a signal to stop */ - /* it. */ - ptr_t stack_end; /* Cold end of the stack. */ - ptr_t stack_ptr; /* Valid only when stopped. */ - # ifdef IA64 - ptr_t backing_store_end; - ptr_t backing_store_ptr; - # endif - int signal; - void * status; /* The value returned from the thread. */ - /* Used only to avoid premature */ - /* reclamation of any data it might */ - /* reference. */ - # ifdef THREAD_LOCAL_ALLOC - # if CPP_WORDSZ == 64 && defined(ALIGN_DOUBLE) - # define GRANULARITY 16 - # define NFREELISTS 49 - # else - # define GRANULARITY 8 - # define NFREELISTS 65 - # endif - /* The ith free list corresponds to size i*GRANULARITY */ - # define INDEX_FROM_BYTES(n) ((ADD_SLOP(n) + GRANULARITY - 1)/GRANULARITY) - # define BYTES_FROM_INDEX(i) ((i) * GRANULARITY - EXTRA_BYTES) - # define SMALL_ENOUGH(bytes) (ADD_SLOP(bytes) <= \ - (NFREELISTS-1)*GRANULARITY) - ptr_t ptrfree_freelists[NFREELISTS]; - ptr_t normal_freelists[NFREELISTS]; - # ifdef GC_GCJ_SUPPORT - ptr_t gcj_freelists[NFREELISTS]; - # endif - /* Free lists contain either a pointer or a small count */ - /* reflecting the number of granules allocated at that */ - /* size. */ - /* 0 ==> thread-local allocation in use, free list */ - /* empty. */ - /* > 0, <= DIRECT_GRANULES ==> Using global allocation, */ - /* too few objects of this size have been */ - /* allocated by this thread. */ - /* >= HBLKSIZE => pointer to nonempty free list. */ - /* > DIRECT_GRANULES, < HBLKSIZE ==> transition to */ - /* local alloc, equivalent to 0. */ - # define DIRECT_GRANULES (HBLKSIZE/GRANULARITY) - /* Don't use local free lists for up to this much */ - /* allocation. */ - # endif - } * GC_thread; - - GC_thread GC_lookup_thread(pthread_t id); - - static GC_bool parallel_initialized = FALSE; - - void GC_init_parallel(); - - # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) - - /* We don't really support thread-local allocation with DBG_HDRS_ALL */ - - #ifdef USE_HPUX_TLS - __thread - #endif - GC_key_t GC_thread_key; - - static GC_bool keys_initialized; - - /* Recover the contents of the freelist array fl into the global one gfl.*/ - /* Note that the indexing scheme differs, in that gfl has finer size */ - /* resolution, even if not all entries are used. */ - /* We hold the allocator lock. */ - static void return_freelists(ptr_t *fl, ptr_t *gfl) - { - int i; - ptr_t q, *qptr; - size_t nwords; - - for (i = 1; i < NFREELISTS; ++i) { - nwords = i * (GRANULARITY/sizeof(word)); - qptr = fl + i; - q = *qptr; - if ((word)q >= HBLKSIZE) { - if (gfl[nwords] == 0) { - gfl[nwords] = q; - } else { - /* Concatenate: */ - for (; (word)q >= HBLKSIZE; qptr = &(obj_link(q)), q = *qptr); - GC_ASSERT(0 == q); - *qptr = gfl[nwords]; - gfl[nwords] = fl[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. */ - fl[i] = (ptr_t)HBLKSIZE; - } - } - - /* We statically allocate a single "size 0" object. It is linked to */ - /* itself, and is thus repeatedly reused for all size 0 allocation */ - /* requests. (Size 0 gcj allocation requests are incorrect, and */ - /* we arrange for those to fault asap.) */ - static ptr_t size_zero_object = (ptr_t)(&size_zero_object); - - /* Each thread structure must be initialized. */ - /* This call must be made from the new thread. */ - /* Caller holds allocation lock. */ - void GC_init_thread_local(GC_thread p) - { - int i; - - if (!keys_initialized) { - if (0 != GC_key_create(&GC_thread_key, 0)) { - ABORT("Failed to create key for local allocator"); - } - keys_initialized = TRUE; - } - if (0 != GC_setspecific(GC_thread_key, p)) { - ABORT("Failed to set thread specific allocation pointers"); - } - for (i = 1; i < NFREELISTS; ++i) { - p -> ptrfree_freelists[i] = (ptr_t)1; - p -> normal_freelists[i] = (ptr_t)1; - # ifdef GC_GCJ_SUPPORT - p -> gcj_freelists[i] = (ptr_t)1; - # endif - } - /* Set up the size 0 free lists. */ - p -> ptrfree_freelists[0] = (ptr_t)(&size_zero_object); - p -> normal_freelists[0] = (ptr_t)(&size_zero_object); - # ifdef GC_GCJ_SUPPORT - p -> gcj_freelists[0] = (ptr_t)(-1); - # endif - } - - #ifdef GC_GCJ_SUPPORT - extern ptr_t * GC_gcjobjfreelist; - #endif - - /* We hold the allocator lock. */ - void GC_destroy_thread_local(GC_thread p) - { - /* We currently only do this from the thread itself. */ - GC_ASSERT(GC_getspecific(GC_thread_key) == (void *)p); - return_freelists(p -> ptrfree_freelists, GC_aobjfreelist); - return_freelists(p -> normal_freelists, GC_objfreelist); - # ifdef GC_GCJ_SUPPORT - return_freelists(p -> gcj_freelists, GC_gcjobjfreelist); - # endif - } - - extern GC_PTR GC_generic_malloc_many(); - - GC_PTR GC_local_malloc(size_t bytes) - { - if (EXPECT(!SMALL_ENOUGH(bytes),0)) { - return(GC_malloc(bytes)); - } else { - int index = INDEX_FROM_BYTES(bytes); - ptr_t * my_fl; - ptr_t my_entry; - GC_key_t k = GC_thread_key; - void * tsd; - - # if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC) \ - || !defined(__GNUC__) - if (EXPECT(0 == k, 0)) { - /* This can happen if we get called when the world is */ - /* being initialized. Whether we can actually complete */ - /* the initialization then is unclear. */ - GC_init_parallel(); - k = GC_thread_key; - } - # endif - tsd = GC_getspecific(GC_thread_key); - # ifdef GC_ASSERTIONS - LOCK(); - GC_ASSERT(tsd == (void *)GC_lookup_thread(pthread_self())); - UNLOCK(); - # endif - my_fl = ((GC_thread)tsd) -> normal_freelists + index; - my_entry = *my_fl; - if (EXPECT((word)my_entry >= HBLKSIZE, 1)) { - ptr_t next = obj_link(my_entry); - GC_PTR result = (GC_PTR)my_entry; - *my_fl = next; - obj_link(my_entry) = 0; - PREFETCH_FOR_WRITE(next); - return result; - } else if ((word)my_entry - 1 < DIRECT_GRANULES) { - *my_fl = my_entry + index + 1; - return GC_malloc(bytes); - } else { - GC_generic_malloc_many(BYTES_FROM_INDEX(index), NORMAL, my_fl); - if (*my_fl == 0) return GC_oom_fn(bytes); - return GC_local_malloc(bytes); - } - } - } - - GC_PTR GC_local_malloc_atomic(size_t bytes) - { - if (EXPECT(!SMALL_ENOUGH(bytes), 0)) { - return(GC_malloc_atomic(bytes)); - } else { - int index = INDEX_FROM_BYTES(bytes); - ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key)) - -> ptrfree_freelists + index; - ptr_t my_entry = *my_fl; - if (EXPECT((word)my_entry >= HBLKSIZE, 1)) { - GC_PTR result = (GC_PTR)my_entry; - *my_fl = obj_link(my_entry); - return result; - } else if ((word)my_entry - 1 < DIRECT_GRANULES) { - *my_fl = my_entry + index + 1; - return GC_malloc_atomic(bytes); - } else { - GC_generic_malloc_many(BYTES_FROM_INDEX(index), PTRFREE, my_fl); - /* *my_fl is updated while the collector is excluded; */ - /* the free list is always visible to the collector as */ - /* such. */ - if (*my_fl == 0) return GC_oom_fn(bytes); - return GC_local_malloc_atomic(bytes); - } - } - } - - #ifdef GC_GCJ_SUPPORT - - #include "include/gc_gcj.h" - - #ifdef GC_ASSERTIONS - extern GC_bool GC_gcj_malloc_initialized; - #endif - - extern int GC_gcj_kind; - - GC_PTR GC_local_gcj_malloc(size_t bytes, - void * ptr_to_struct_containing_descr) - { - GC_ASSERT(GC_gcj_malloc_initialized); - if (EXPECT(!SMALL_ENOUGH(bytes), 0)) { - return GC_gcj_malloc(bytes, ptr_to_struct_containing_descr); - } else { - int index = INDEX_FROM_BYTES(bytes); - ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key)) - -> gcj_freelists + index; - ptr_t my_entry = *my_fl; - if (EXPECT((word)my_entry >= HBLKSIZE, 1)) { - GC_PTR result = (GC_PTR)my_entry; - GC_ASSERT(!GC_incremental); - /* We assert that any concurrent marker will stop us. */ - /* Thus it is impossible for a mark procedure to see the */ - /* allocation of the next object, but to see this object */ - /* still containing a free list pointer. Otherwise the */ - /* marker might find a random "mark descriptor". */ - *(volatile ptr_t *)my_fl = obj_link(my_entry); - /* We must update the freelist before we store the pointer. */ - /* Otherwise a GC at this point would see a corrupted */ - /* free list. */ - /* A memory barrier is probably never needed, since the */ - /* action of stopping this thread will cause prior writes */ - /* to complete. */ - GC_ASSERT(((void * volatile *)result)[1] == 0); - *(void * volatile *)result = ptr_to_struct_containing_descr; - return result; - } else if ((word)my_entry - 1 < DIRECT_GRANULES) { - *my_fl = my_entry + index + 1; - return GC_gcj_malloc(bytes, ptr_to_struct_containing_descr); - } else { - GC_generic_malloc_many(BYTES_FROM_INDEX(index), GC_gcj_kind, my_fl); - if (*my_fl == 0) return GC_oom_fn(bytes); - return GC_local_gcj_malloc(bytes, ptr_to_struct_containing_descr); - } - } - } - - #endif /* GC_GCJ_SUPPORT */ - - # else /* !THREAD_LOCAL_ALLOC && !DBG_HDRS_ALL */ - - # define GC_destroy_thread_local(t) - - # endif /* !THREAD_LOCAL_ALLOC */ - - /* - * We use signals to stop threads during GC. - * - * Suspended threads wait in signal handler for SIG_THR_RESTART. - * That's more portable than semaphores or condition variables. - * (We do use sem_post from a signal handler, but that should be portable.) - * - * The thread suspension signal SIG_SUSPEND is now defined in gc_priv.h. - * Note that we can't just stop a thread; we need it to save its stack - * pointer(s) and acknowledge. - */ - - #ifndef SIG_THR_RESTART - # if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) - # define SIG_THR_RESTART _SIGRTMIN + 5 - # else - # define SIG_THR_RESTART SIGXCPU - # endif - #endif - - sem_t GC_suspend_ack_sem; - - #if 0 - /* - To make sure that we're using LinuxThreads and not some other thread - package, we generate a dummy reference to `pthread_kill_other_threads_np' - (was `__pthread_initial_thread_bos' but that disappeared), - which is a symbol defined in LinuxThreads, but (hopefully) not in other - thread packages. - - We no longer do this, since this code is now portable enough that it might - actually work for something else. - */ - void (*dummy_var_to_force_linux_threads)() = pthread_kill_other_threads_np; - #endif /* 0 */ - - #if defined(SPARC) || defined(IA64) - extern word GC_save_regs_in_stack(); - #endif - - long GC_nprocs = 1; /* Number of processors. We may not have */ - /* access to all of them, but this is as good */ - /* a guess as any ... */ - - #ifdef PARALLEL_MARK - - # ifndef MAX_MARKERS - # define MAX_MARKERS 16 - # endif - - static ptr_t marker_sp[MAX_MARKERS] = {0}; - - void * GC_mark_thread(void * id) - { - word my_mark_no = 0; - - marker_sp[(word)id] = GC_approx_sp(); - 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 */ - /* handler or from the GC lock acquisition code. Under Linux, it's */ - /* not safe to call it from a signal handler, since it uses mutexes */ - /* and condition variables. Since it is called only here, the */ - /* argument is unnecessary. */ - if (my_mark_no < GC_mark_no || my_mark_no > GC_mark_no + 2) { - /* resynchronize if we get far off, e.g. because GC_mark_no */ - /* wrapped. */ - my_mark_no = GC_mark_no; - } - # ifdef DEBUG_THREADS - GC_printf1("Starting mark helper for mark number %ld\n", my_mark_no); - # endif - GC_help_marker(my_mark_no); - } - } - - extern long GC_markers; /* Number of mark threads we would */ - /* like to have. Includes the */ - /* initiating thread. */ - - pthread_t GC_mark_threads[MAX_MARKERS]; - - #define PTHREAD_CREATE REAL_FUNC(pthread_create) - - static void start_mark_threads() - { - unsigned i; - pthread_attr_t attr; - - if (GC_markers > MAX_MARKERS) { - WARN("Limiting number of mark threads\n", 0); - GC_markers = MAX_MARKERS; - } - 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"); - - # ifdef HPUX - /* 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)) - { - size_t old_size; - int code; - - if (pthread_attr_getstacksize(&attr, &old_size) != 0) - ABORT("pthread_attr_getstacksize failed\n"); - if (old_size < MIN_STACK_SIZE) { - if (pthread_attr_setstacksize(&attr, MIN_STACK_SIZE) != 0) - ABORT("pthread_attr_setstacksize failed\n"); - } - } - # endif /* HPUX */ - # ifdef CONDPRINT - if (GC_print_stats) { - GC_printf1("Starting %ld marker threads\n", GC_markers - 1); - } - # endif - for (i = 0; i < GC_markers - 1; ++i) { - if (0 != PTHREAD_CREATE(GC_mark_threads + i, &attr, - GC_mark_thread, (void *)(word)i)) { - WARN("Marker thread creation failed, errno = %ld.\n", errno); - } - } - } - - #else /* !PARALLEL_MARK */ - - static __inline__ void start_mark_threads() - { - } - - #endif /* !PARALLEL_MARK */ - - void GC_suspend_handler(int sig) - { - int dummy; - pthread_t my_thread = pthread_self(); - GC_thread me; - sigset_t all_sigs; - sigset_t old_sigs; - int i; - sigset_t mask; - # ifdef PARALLEL_MARK - word my_mark_no = GC_mark_no; - /* Marker can't proceed until we acknowledge. Thus this is */ - /* guaranteed to be the mark_no correspending to our */ - /* suspension, i.e. the marker can't have incremented it yet. */ - # endif - - if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler"); - - #if DEBUG_THREADS - GC_printf1("Suspending 0x%x\n", my_thread); - #endif - - me = GC_lookup_thread(my_thread); - /* The lookup here is safe, since I'm doing this on behalf */ - /* of a thread which holds the allocation lock in order */ - /* to stop the world. Thus concurrent modification of the */ - /* data structure is impossible. */ - # ifdef SPARC - me -> stack_ptr = (ptr_t)GC_save_regs_in_stack(); - # else - me -> stack_ptr = (ptr_t)(&dummy); - # endif - # ifdef IA64 - me -> backing_store_ptr = (ptr_t)GC_save_regs_in_stack(); - # endif - - /* Tell the thread that wants to stop the world that this */ - /* thread has been stopped. Note that sem_post() is */ - /* the only async-signal-safe primitive in LinuxThreads. */ - sem_post(&GC_suspend_ack_sem); - - /* Wait until that thread tells us to restart by sending */ - /* this thread a SIG_THR_RESTART signal. */ - /* SIG_THR_RESTART should be masked at this point. Thus there */ - /* is no race. */ - if (sigfillset(&mask) != 0) ABORT("sigfillset() failed"); - if (sigdelset(&mask, SIG_THR_RESTART) != 0) ABORT("sigdelset() failed"); - # ifdef NO_SIGNALS - if (sigdelset(&mask, SIGINT) != 0) ABORT("sigdelset() failed"); - if (sigdelset(&mask, SIGQUIT) != 0) ABORT("sigdelset() failed"); - if (sigdelset(&mask, SIGTERM) != 0) ABORT("sigdelset() failed"); - if (sigdelset(&mask, SIGABRT) != 0) ABORT("sigdelset() failed"); - # endif - do { - me->signal = 0; - sigsuspend(&mask); /* Wait for signal */ - } while (me->signal != SIG_THR_RESTART); - - #if DEBUG_THREADS - GC_printf1("Continuing 0x%x\n", my_thread); - #endif - } - - void GC_restart_handler(int sig) - { - GC_thread me; - - if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler"); - - /* Let the GC_suspend_handler() know that we got a SIG_THR_RESTART. */ - /* The lookup here is safe, since I'm doing this on behalf */ - /* of a thread which holds the allocation lock in order */ - /* to stop the world. Thus concurrent modification of the */ - /* data structure is impossible. */ - me = GC_lookup_thread(pthread_self()); - me->signal = SIG_THR_RESTART; - - /* - ** Note: even if we didn't do anything useful here, - ** it would still be necessary to have a signal handler, - ** rather than ignoring the signals, otherwise - ** the signals will not be delivered at all, and - ** will thus not interrupt the sigsuspend() above. - */ - - #if DEBUG_THREADS - GC_printf1("In GC_restart_handler for 0x%x\n", pthread_self()); - #endif - } - - /* Defining INSTALL_LOOPING_SEGV_HANDLER causes SIGSEGV and SIGBUS to */ - /* result in an infinite loop in a signal handler. This can be very */ - /* useful for debugging, since (as of RH7) gdb still seems to have */ - /* serious problems with threads. */ - #ifdef INSTALL_LOOPING_SEGV_HANDLER - void GC_looping_handler(int sig) - { - GC_printf3("Signal %ld in thread %lx, pid %ld\n", - sig, pthread_self(), getpid()); - for (;;); - } - #endif - - GC_bool GC_thr_initialized = FALSE; - - # define THREAD_TABLE_SZ 128 /* Must be power of 2 */ - volatile GC_thread GC_threads[THREAD_TABLE_SZ]; - - void GC_push_thread_structures GC_PROTO((void)) - { - GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads)); - } - - #ifdef THREAD_LOCAL_ALLOC - /* We must explicitly mark ptrfree and gcj free lists, since the free */ - /* list links wouldn't otherwise be found. We also set them in the */ - /* normal free lists, since that involves touching less memory than if */ - /* we scanned them normally. */ - void GC_mark_thread_local_free_lists(void) - { - int i, j; - GC_thread p; - ptr_t q; - - for (i = 0; i < THREAD_TABLE_SZ; ++i) { - for (p = GC_threads[i]; 0 != p; p = p -> next) { - for (j = 1; j < NFREELISTS; ++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 - q = p -> gcj_freelists[j]; - if ((word)q > HBLKSIZE) GC_set_fl_marks(q); - # endif /* GC_GCJ_SUPPORT */ - } - } - } - } - #endif /* THREAD_LOCAL_ALLOC */ - - /* Add a thread to GC_threads. We assume it wasn't already there. */ - /* Caller holds allocation lock. */ - GC_thread GC_new_thread(pthread_t id) - { - int hv = ((word)id) % THREAD_TABLE_SZ; - GC_thread result; - static struct GC_Thread_Rep first_thread; - static GC_bool first_thread_used = FALSE; - - if (!first_thread_used) { - result = &first_thread; - first_thread_used = TRUE; - } else { - result = (struct GC_Thread_Rep *) - GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL); - } - if (result == 0) return(0); - result -> id = id; - result -> next = GC_threads[hv]; - GC_threads[hv] = result; - GC_ASSERT(result -> flags == 0 && result -> thread_blocked == 0); - return(result); - } - - /* Delete a thread from GC_threads. We assume it is there. */ - /* (The code intentionally traps if it wasn't.) */ - /* Caller holds allocation lock. */ - void GC_delete_thread(pthread_t id) - { - int hv = ((word)id) % THREAD_TABLE_SZ; - register GC_thread p = GC_threads[hv]; - register GC_thread prev = 0; - - while (!pthread_equal(p -> id, id)) { - prev = p; - p = p -> next; - } - if (prev == 0) { - GC_threads[hv] = p -> next; - } else { - prev -> next = p -> next; - } - GC_INTERNAL_FREE(p); - } - - /* If a thread has been joined, but we have not yet */ - /* been notified, then there may be more than one thread */ - /* in the table with the same pthread id. */ - /* This is OK, but we need a way to delete a specific one. */ - void GC_delete_gc_thread(pthread_t id, GC_thread gc_id) - { - int hv = ((word)id) % THREAD_TABLE_SZ; - register GC_thread p = GC_threads[hv]; - register GC_thread prev = 0; - - while (p != gc_id) { - prev = p; - p = p -> next; - } - if (prev == 0) { - GC_threads[hv] = p -> next; - } else { - prev -> next = p -> next; - } - GC_INTERNAL_FREE(p); - } - - /* Return a GC_thread corresponding to a given thread_t. */ - /* Returns 0 if it's not there. */ - /* Caller holds allocation lock or otherwise inhibits */ - /* updates. */ - /* If there is more than one thread with the given id we */ - /* return the most recent one. */ - GC_thread GC_lookup_thread(pthread_t id) - { - int hv = ((word)id) % THREAD_TABLE_SZ; - register GC_thread p = GC_threads[hv]; - - while (p != 0 && !pthread_equal(p -> id, id)) p = p -> next; - return(p); - } - - /* There seems to be a very rare thread stopping problem. To help us */ - /* debug that, we save the ids of the stopping thread. */ - pthread_t GC_stopping_thread; - int GC_stopping_pid; - - /* Caller holds allocation lock. */ - void GC_stop_world() - { - pthread_t my_thread = pthread_self(); - register int i; - register GC_thread p; - register int n_live_threads = 0; - register int result; - - GC_stopping_thread = my_thread; /* debugging only. */ - GC_stopping_pid = getpid(); /* debugging only. */ - /* Make sure all free list construction has stopped before we start. */ - /* No new construction can start, since free list construction is */ - /* required to acquire and release the GC lock before it starts, */ - /* and we have the lock. */ - # ifdef PARALLEL_MARK - GC_acquire_mark_lock(); - GC_ASSERT(GC_fl_builder_count == 0); - /* We should have previously waited for it to become zero. */ - # endif /* PARALLEL_MARK */ - for (i = 0; i < THREAD_TABLE_SZ; i++) { - for (p = GC_threads[i]; p != 0; p = p -> next) { - if (p -> id != my_thread) { - if (p -> flags & FINISHED) continue; - if (p -> thread_blocked) /* Will wait */ continue; - n_live_threads++; - #if DEBUG_THREADS - GC_printf1("Sending suspend signal to 0x%x\n", p -> id); - #endif - result = pthread_kill(p -> id, SIG_SUSPEND); - switch(result) { - case ESRCH: - /* Not really there anymore. Possible? */ - n_live_threads--; - break; - case 0: - break; - default: - ABORT("pthread_kill failed"); - } - } - } - } - for (i = 0; i < n_live_threads; i++) { - if (0 != sem_wait(&GC_suspend_ack_sem)) - ABORT("sem_wait in handler failed"); - } - # ifdef PARALLEL_MARK - GC_release_mark_lock(); - # endif - #if DEBUG_THREADS - GC_printf1("World stopped 0x%x\n", pthread_self()); - #endif - GC_stopping_thread = 0; /* debugging only */ - } - - /* Caller holds allocation lock, and has held it continuously since */ - /* the world stopped. */ - void GC_start_world() - { - pthread_t my_thread = pthread_self(); - register int i; - register GC_thread p; - register int n_live_threads = 0; - register int result; - - # if DEBUG_THREADS - GC_printf0("World starting\n"); - # endif - - for (i = 0; i < THREAD_TABLE_SZ; i++) { - for (p = GC_threads[i]; p != 0; p = p -> next) { - if (p -> id != my_thread) { - if (p -> flags & FINISHED) continue; - if (p -> thread_blocked) continue; - n_live_threads++; - #if DEBUG_THREADS - GC_printf1("Sending restart signal to 0x%x\n", p -> id); - #endif - result = pthread_kill(p -> id, SIG_THR_RESTART); - switch(result) { - case ESRCH: - /* Not really there anymore. Possible? */ - n_live_threads--; - break; - case 0: - break; - default: - ABORT("pthread_kill failed"); - } - } - } - } - #if DEBUG_THREADS - GC_printf0("World started\n"); - #endif - GC_stopping_thread = 0; /* debugging only */ - } - - # ifdef IA64 - # define IF_IA64(x) x - # else - # define IF_IA64(x) - # endif - /* We hold allocation lock. Should do exactly the right thing if the */ - /* world is stopped. Should not fail if it isn't. */ - void GC_push_all_stacks() - { - int i; - GC_thread p; - ptr_t sp = GC_approx_sp(); - ptr_t lo, hi; - /* On IA64, we also need to scan the register backing store. */ - IF_IA64(ptr_t bs_lo; ptr_t bs_hi;) - pthread_t me = pthread_self(); - - if (!GC_thr_initialized) GC_thr_init(); - #if DEBUG_THREADS - GC_printf1("Pushing stacks from thread 0x%lx\n", (unsigned long) me); - #endif - for (i = 0; i < THREAD_TABLE_SZ; i++) { - for (p = GC_threads[i]; p != 0; p = p -> next) { - if (p -> flags & FINISHED) continue; - if (pthread_equal(p -> id, me)) { - # ifdef SPARC - lo = (ptr_t)GC_save_regs_in_stack(); - # else - lo = GC_approx_sp(); - # endif - IF_IA64(bs_hi = (ptr_t)GC_save_regs_in_stack();) - } else { - lo = p -> stack_ptr; - IF_IA64(bs_hi = p -> backing_store_ptr;) - } - if ((p -> flags & MAIN_THREAD) == 0) { - hi = p -> stack_end; - IF_IA64(bs_lo = p -> backing_store_end); - } else { - /* The original stack. */ - hi = GC_stackbottom; - IF_IA64(bs_lo = BACKING_STORE_BASE;) - } - #if DEBUG_THREADS - GC_printf3("Stack for thread 0x%lx = [%lx,%lx)\n", - (unsigned long) p -> id, - (unsigned long) lo, (unsigned long) hi); - #endif - if (0 == lo) ABORT("GC_push_all_stacks: sp not set!\n"); - # ifdef STACK_GROWS_UP - /* We got them backwards! */ - GC_push_all_stack(hi, lo); - # else - GC_push_all_stack(lo, hi); - # endif - # ifdef IA64 - if (pthread_equal(p -> id, me)) { - GC_push_all_eager(bs_lo, bs_hi); - } else { - GC_push_all_stack(bs_lo, bs_hi); - } - # endif - } - } - } - - #ifdef USE_PROC_FOR_LIBRARIES - int GC_segment_is_thread_stack(ptr_t lo, ptr_t hi) - { - int i; - GC_thread p; - - # ifdef PARALLEL_MARK - for (i = 0; i < GC_markers; ++i) { - if (marker_sp[i] > lo & marker_sp[i] < hi) return 1; - } - # endif - for (i = 0; i < THREAD_TABLE_SZ; i++) { - for (p = GC_threads[i]; p != 0; p = p -> next) { - if (0 != p -> stack_end) { - # ifdef STACK_GROWS_UP - if (p -> stack_end >= lo && p -> stack_end < hi) return 1; - # else /* STACK_GROWS_DOWN */ - if (p -> stack_end > lo && p -> stack_end <= hi) return 1; - # endif - } - } - } - return 0; - } - #endif /* USE_PROC_FOR_LIBRARIES */ - - #ifdef GC_LINUX_THREADS - /* Return the number of processors, or i<= 0 if it can't be determined. */ - int GC_get_nprocs() - { - /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that */ - /* appears to be buggy in many cases. */ - /* We look for lines "cpu" in /proc/stat. */ - # define STAT_BUF_SIZE 4096 - # if defined(GC_USE_LD_WRAP) - # define STAT_READ __real_read - # else - # define STAT_READ read - # endif - char stat_buf[STAT_BUF_SIZE]; - int f; - char c; - word result = 1; - /* Some old kernels only have a single "cpu nnnn ..." */ - /* entry in /proc/stat. We identify those as */ - /* uniprocessors. */ - size_t i, len = 0; - - f = open("/proc/stat", O_RDONLY); - if (f < 0 || (len = STAT_READ(f, stat_buf, STAT_BUF_SIZE)) < 100) { - WARN("Couldn't read /proc/stat\n", 0); - return -1; - } - close(f); - for (i = 0; i < len - 100; ++i) { - if (stat_buf[i] == '\n' && stat_buf[i+1] == 'c' - && stat_buf[i+2] == 'p' && stat_buf[i+3] == 'u') { - int cpu_no = atoi(stat_buf + i + 4); - if (cpu_no >= result) result = cpu_no + 1; - } - } - return result; - } - #endif /* GC_LINUX_THREADS */ - - /* We hold the allocation lock. */ - void GC_thr_init() - { - int dummy; - GC_thread t; - struct sigaction act; - - if (GC_thr_initialized) return; - GC_thr_initialized = TRUE; - - if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0) - ABORT("sem_init failed"); - - act.sa_flags = SA_RESTART; - if (sigfillset(&act.sa_mask) != 0) { - ABORT("sigfillset() failed"); - } - # ifdef NO_SIGNALS - if (sigdelset(&act.sa_mask, SIGINT) != 0 - || sigdelset(&act.sa_mask, SIGQUIT != 0) - || sigdelset(&act.sa_mask, SIGABRT != 0) - || sigdelset(&act.sa_mask, SIGTERM != 0)) { - ABORT("sigdelset() failed"); - } - # endif - - /* SIG_THR_RESTART is unmasked by the handler when necessary. */ - act.sa_handler = GC_suspend_handler; - if (sigaction(SIG_SUSPEND, &act, NULL) != 0) { - ABORT("Cannot set SIG_SUSPEND handler"); - } - - act.sa_handler = GC_restart_handler; - if (sigaction(SIG_THR_RESTART, &act, NULL) != 0) { - ABORT("Cannot set SIG_THR_RESTART handler"); - } - # ifdef INSTALL_LOOPING_SEGV_HANDLER - act.sa_handler = GC_looping_handler; - if (sigaction(SIGSEGV, &act, NULL) != 0 - || sigaction(SIGBUS, &act, NULL) != 0) { - ABORT("Cannot set SIGSEGV or SIGBUS looping handler"); - } - # endif /* INSTALL_LOOPING_SEGV_HANDLER */ - - /* Add the initial thread, so we can stop it. */ - t = GC_new_thread(pthread_self()); - t -> stack_ptr = (ptr_t)(&dummy); - t -> flags = DETACHED | MAIN_THREAD; - - /* Set GC_nprocs. */ - { - char * nprocs_string = GETENV("GC_NPROCS"); - GC_nprocs = -1; - if (nprocs_string != NULL) GC_nprocs = atoi(nprocs_string); - } - if (GC_nprocs <= 0) { - # if defined(GC_HPUX_THREADS) - GC_nprocs = pthread_num_processors_np(); - # endif - # if defined(GC_OSF1_THREADS) || defined(GC_FREEBSD_THREADS) - GC_nprocs = 1; - # endif - # if defined(GC_LINUX_THREADS) - GC_nprocs = GC_get_nprocs(); - # endif - } - if (GC_nprocs <= 0) { - WARN("GC_get_nprocs() returned %ld\n", GC_nprocs); - GC_nprocs = 2; - # ifdef PARALLEL_MARK - GC_markers = 1; - # endif - } else { - # ifdef PARALLEL_MARK - GC_markers = GC_nprocs; - # endif - } - # ifdef PARALLEL_MARK - # ifdef CONDPRINT - if (GC_print_stats) { - GC_printf2("Number of processors = %ld, " - "number of marker threads = %ld\n", GC_nprocs, GC_markers); - } - # endif - if (GC_markers == 1) { - GC_parallel = FALSE; - # ifdef CONDPRINT - if (GC_print_stats) { - GC_printf0("Single marker thread, turning off parallel marking\n"); - } - # endif - } else { - GC_parallel = TRUE; - } - # endif - } - - - /* Perform all initializations, including those that */ - /* may require allocation. */ - /* Called as constructor without allocation lock. */ - /* Must be called before a second thread is created. */ - /* Called without allocation lock. */ - void GC_init_parallel() - { - if (parallel_initialized) return; - parallel_initialized = TRUE; - /* GC_init() calls us back, so set flag first. */ - if (!GC_is_initialized) GC_init(); - /* If we are using a parallel marker, start the helper threads. */ - # ifdef PARALLEL_MARK - if (GC_parallel) start_mark_threads(); - # endif - /* Initialize thread local free lists if used. */ - # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) - LOCK(); - GC_init_thread_local(GC_lookup_thread(pthread_self())); - UNLOCK(); - # endif - } - - - int WRAP_FUNC(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset) - { - sigset_t fudged_set; - - if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) { - fudged_set = *set; - sigdelset(&fudged_set, SIG_SUSPEND); - set = &fudged_set; - } - return(REAL_FUNC(pthread_sigmask)(how, set, oset)); - } - - /* Wrappers for functions that are likely to block for an appreciable */ - /* length of time. Must be called in pairs, if at all. */ - /* Nothing much beyond the system call itself should be executed */ - /* between these. */ - - void GC_start_blocking(void) { - # define SP_SLOP 128 - GC_thread me; - LOCK(); - me = GC_lookup_thread(pthread_self()); - GC_ASSERT(!(me -> thread_blocked)); - # ifdef SPARC - me -> stack_ptr = (ptr_t)GC_save_regs_in_stack(); - # else - me -> stack_ptr = (ptr_t)GC_approx_sp(); - # endif - # ifdef IA64 - me -> backing_store_ptr = (ptr_t)GC_save_regs_in_stack() + SP_SLOP; - # endif - /* Add some slop to the stack pointer, since the wrapped call may */ - /* end up pushing more callee-save registers. */ - # ifdef STACK_GROWS_UP - me -> stack_ptr += SP_SLOP; - # else - me -> stack_ptr -= SP_SLOP; - # endif - me -> thread_blocked = TRUE; - UNLOCK(); - } - - GC_end_blocking(void) { - GC_thread me; - LOCK(); /* This will block if the world is stopped. */ - me = GC_lookup_thread(pthread_self()); - GC_ASSERT(me -> thread_blocked); - me -> thread_blocked = FALSE; - UNLOCK(); - } - - /* A wrapper for the standard C sleep function */ - int WRAP_FUNC(sleep) (unsigned int seconds) - { - int result; - - GC_start_blocking(); - result = REAL_FUNC(sleep)(seconds); - GC_end_blocking(); - return result; - } - - struct start_info { - void *(*start_routine)(void *); - void *arg; - word flags; - sem_t registered; /* 1 ==> in our thread table, but */ - /* parent hasn't yet noticed. */ - }; - - /* Called at thread exit. */ - /* Never called for main thread. That's OK, since it */ - /* results in at most a tiny one-time leak. And */ - /* linuxthreads doesn't reclaim the main threads */ - /* resources or id anyway. */ - void GC_thread_exit_proc(void *arg) - { - GC_thread me; - - LOCK(); - me = GC_lookup_thread(pthread_self()); - GC_destroy_thread_local(me); - if (me -> flags & DETACHED) { - GC_delete_thread(pthread_self()); - } else { - me -> flags |= FINISHED; - } - # if defined(THREAD_LOCAL_ALLOC) && !defined(USE_PTHREAD_SPECIFIC) \ - && !defined(USE_HPUX_TLS) && !defined(DBG_HDRS_ALL) - GC_remove_specific(GC_thread_key); - # endif - if (GC_incremental && GC_collection_in_progress()) { - int old_gc_no = GC_gc_no; - - /* Make sure that no part of our stack is still on the mark stack, */ - /* since it's about to be unmapped. */ - while (GC_incremental && GC_collection_in_progress() - && old_gc_no == GC_gc_no) { - ENTER_GC(); - GC_collect_a_little_inner(1); - EXIT_GC(); - UNLOCK(); - sched_yield(); - LOCK(); - } - } - UNLOCK(); - } - - int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) - { - int result; - GC_thread thread_gc_id; - - LOCK(); - thread_gc_id = GC_lookup_thread(thread); - /* This is guaranteed to be the intended one, since the thread id */ - /* cant have been recycled by pthreads. */ - UNLOCK(); - result = REAL_FUNC(pthread_join)(thread, retval); - # if defined (GC_FREEBSD_THREADS) - /* On FreeBSD, the wrapped pthread_join() sometimes returns (what - appears to be) a spurious EINTR which caused the test and real code - to gratuitously fail. Having looked at system pthread library source - code, I see how this return code may be generated. In one path of - code, pthread_join() just returns the errno setting of the thread - being joined. This does not match the POSIX specification or the - local man pages thus I have taken the liberty to catch this one - spurious return value properly conditionalized on GC_FREEBSD_THREADS. */ - if (result == EINTR) result = 0; - # endif - if (result == 0) { - LOCK(); - /* Here the pthread thread id may have been recycled. */ - GC_delete_gc_thread(thread, thread_gc_id); - UNLOCK(); - } - return result; - } - - int - WRAP_FUNC(pthread_detach)(pthread_t thread) - { - int result; - GC_thread thread_gc_id; - - LOCK(); - thread_gc_id = GC_lookup_thread(thread); - UNLOCK(); - result = REAL_FUNC(pthread_detach)(thread); - if (result == 0) { - LOCK(); - thread_gc_id -> flags |= DETACHED; - /* Here the pthread thread id may have been recycled. */ - if (thread_gc_id -> flags & FINISHED) { - GC_delete_gc_thread(thread, thread_gc_id); - } - UNLOCK(); - } - return result; - } - - void * GC_start_routine(void * arg) - { - int dummy; - struct start_info * si = arg; - void * result; - GC_thread me; - pthread_t my_pthread; - void *(*start)(void *); - void *start_arg; - - my_pthread = pthread_self(); - # ifdef DEBUG_THREADS - GC_printf1("Starting thread 0x%lx\n", my_pthread); - GC_printf1("pid = %ld\n", (long) getpid()); - GC_printf1("sp = 0x%lx\n", (long) &arg); - # endif - LOCK(); - me = GC_new_thread(my_pthread); - me -> flags = si -> flags; - me -> stack_ptr = 0; - /* me -> stack_end = GC_linux_stack_base(); -- currently (11/99) */ - /* doesn't work because the stack base in /proc/self/stat is the */ - /* one for the main thread. There is a strong argument that that's */ - /* a kernel bug, but a pervasive one. */ - # ifdef STACK_GROWS_DOWN - me -> stack_end = (ptr_t)(((word)(&dummy) + (GC_page_size - 1)) - & ~(GC_page_size - 1)); - me -> stack_ptr = me -> stack_end - 0x10; - /* Needs to be plausible, since an asynchronous stack mark */ - /* should not crash. */ - # else - me -> stack_end = (ptr_t)((word)(&dummy) & ~(GC_page_size - 1)); - me -> stack_ptr = me -> stack_end + 0x10; - # endif - /* This is dubious, since we may be more than a page into the stack, */ - /* and hence skip some of it, though it's not clear that matters. */ - # ifdef IA64 - me -> backing_store_end = (ptr_t) - (GC_save_regs_in_stack() & ~(GC_page_size - 1)); - /* This is also < 100% convincing. We should also read this */ - /* from /proc, but the hook to do so isn't there yet. */ - # endif /* IA64 */ - UNLOCK(); - start = si -> start_routine; - # ifdef DEBUG_THREADS - GC_printf1("start_routine = 0x%lx\n", start); - # endif - start_arg = si -> arg; - # ifdef DEBUG_THREADS - GC_printf1("sem_post from 0x%lx\n", my_pthread); - # endif - sem_post(&(si -> registered)); /* Last action on si. */ - /* OK to deallocate. */ - pthread_cleanup_push(GC_thread_exit_proc, 0); - # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) - LOCK(); - GC_init_thread_local(me); - UNLOCK(); - # endif - result = (*start)(start_arg); - #if DEBUG_THREADS - GC_printf1("Finishing thread 0x%x\n", pthread_self()); - #endif - me -> status = result; - me -> flags |= FINISHED; - pthread_cleanup_pop(1); - /* Cleanup acquires lock, ensuring that we can't exit */ - /* while a collection that thinks we're alive is trying to stop */ - /* us. */ - return(result); - } - - int - WRAP_FUNC(pthread_create)(pthread_t *new_thread, - const pthread_attr_t *attr, - void *(*start_routine)(void *), void *arg) - { - int result; - GC_thread t; - pthread_t my_new_thread; - int detachstate; - word my_flags = 0; - struct start_info * si; - /* This is otherwise saved only in an area mmapped by the thread */ - /* library, which isn't visible to the collector. */ - - LOCK(); - si = (struct start_info *)GC_INTERNAL_MALLOC(sizeof(struct start_info), NORMAL); - UNLOCK(); - if (!parallel_initialized) GC_init_parallel(); - if (0 == si) return(ENOMEM); - sem_init(&(si -> registered), 0, 0); - si -> start_routine = start_routine; - si -> arg = arg; - LOCK(); - if (!GC_thr_initialized) GC_thr_init(); - if (NULL == attr) { - detachstate = PTHREAD_CREATE_JOINABLE; - } else { - pthread_attr_getdetachstate(attr, &detachstate); - } - if (PTHREAD_CREATE_DETACHED == detachstate) my_flags |= DETACHED; - si -> flags = my_flags; - UNLOCK(); - # ifdef DEBUG_THREADS - GC_printf1("About to start new thread from thread 0x%X\n", - pthread_self()); - # endif - result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, si); - # ifdef DEBUG_THREADS - GC_printf1("Started thread 0x%X\n", *new_thread); - # endif - /* Wait until child has been added to the thread table. */ - /* This also ensures that we hold onto si until the child is done */ - /* with it. Thus it doesn't matter whether it is otherwise */ - /* visible to the collector. */ - while (0 != sem_wait(&(si -> registered))) { - if (EINTR != errno) ABORT("sem_wait failed"); - } - # ifdef DEBUG_THREADS - GC_printf1("sem_wait complete from thread 0x%X\n", - pthread_self()); - # endif - sem_destroy(&(si -> registered)); - LOCK(); - GC_INTERNAL_FREE(si); - UNLOCK(); - return(result); - } - - #ifdef GENERIC_COMPARE_AND_SWAP - pthread_mutex_t GC_compare_and_swap_lock = PTHREAD_MUTEX_INITIALIZER; - - GC_bool GC_compare_and_exchange(volatile GC_word *addr, - GC_word old, GC_word new_val) - { - GC_bool result; - pthread_mutex_lock(&GC_compare_and_swap_lock); - if (*addr == old) { - *addr = new_val; - result = TRUE; - } else { - result = FALSE; - } - pthread_mutex_unlock(&GC_compare_and_swap_lock); - return result; - } - - GC_word GC_atomic_add(volatile GC_word *addr, GC_word how_much) - { - GC_word old; - pthread_mutex_lock(&GC_compare_and_swap_lock); - old = *addr; - *addr = old + how_much; - pthread_mutex_unlock(&GC_compare_and_swap_lock); - return old; - } - - #endif /* GENERIC_COMPARE_AND_SWAP */ - /* Spend a few cycles in a way that can't introduce contention with */ - /* othre threads. */ - void GC_pause() - { - int i; - volatile word dummy = 0; - - for (i = 0; i < 10; ++i) { - # ifdef __GNUC__ - __asm__ __volatile__ (" " : : : "memory"); - # else - /* Something that's unlikely to be optimized away. */ - GC_noop(++dummy); - # endif - } - } - - #define SPIN_MAX 1024 /* Maximum number of calls to GC_pause before */ - /* give up. */ - - VOLATILE GC_bool GC_collecting = 0; - /* A hint that we're in the collector and */ - /* holding the allocation lock for an */ - /* extended period. */ - - #if !defined(USE_SPIN_LOCK) || defined(PARALLEL_MARK) - /* If we don't want to use the below spinlock implementation, either */ - /* because we don't have a GC_test_and_set implementation, or because */ - /* we don't want to risk sleeping, we can still try spinning on */ - /* pthread_mutex_trylock for a while. This appears to be very */ - /* beneficial in many cases. */ - /* I suspect that under high contention this is nearly always better */ - /* than the spin lock. But it's a bit slower on a uniprocessor. */ - /* Hence we still default to the spin lock. */ - /* This is also used to acquire the mark lock for the parallel */ - /* marker. */ - - /* Here we use a strict exponential backoff scheme. I don't know */ - /* whether that's better or worse than the above. We eventually */ - /* yield by calling pthread_mutex_lock(); it never makes sense to */ - /* explicitly sleep. */ - - void GC_generic_lock(pthread_mutex_t * lock) - { - unsigned pause_length = 1; - unsigned i; - - if (0 == pthread_mutex_trylock(lock)) return; - for (; pause_length <= SPIN_MAX; pause_length <<= 1) { - for (i = 0; i < pause_length; ++i) { - GC_pause(); - } - switch(pthread_mutex_trylock(lock)) { - case 0: - return; - case EBUSY: - break; - default: - ABORT("Unexpected error from pthread_mutex_trylock"); - } - } - pthread_mutex_lock(lock); - } - - #endif /* !USE_SPIN_LOCK || PARALLEL_MARK */ - - #if defined(USE_SPIN_LOCK) - - /* Reasonably fast spin locks. Basically the same implementation */ - /* as STL alloc.h. This isn't really the right way to do this. */ - /* but until the POSIX scheduling mess gets straightened out ... */ - - volatile unsigned int GC_allocate_lock = 0; - - - void GC_lock() - { - # define low_spin_max 30 /* spin cycles if we suspect uniprocessor */ - # define high_spin_max SPIN_MAX /* spin cycles for multiprocessor */ - static unsigned spin_max = low_spin_max; - unsigned my_spin_max; - static unsigned last_spins = 0; - unsigned my_last_spins; - int i; - - if (!GC_test_and_set(&GC_allocate_lock)) { - return; - } - my_spin_max = spin_max; - my_last_spins = last_spins; - for (i = 0; i < my_spin_max; i++) { - if (GC_collecting || GC_nprocs == 1) goto yield; - if (i < my_last_spins/2 || GC_allocate_lock) { - GC_pause(); - continue; - } - if (!GC_test_and_set(&GC_allocate_lock)) { - /* - * got it! - * Spinning worked. Thus we're probably not being scheduled - * against the other process with which we were contending. - * Thus it makes sense to spin longer the next time. - */ - last_spins = i; - spin_max = high_spin_max; - return; - } - } - /* We are probably being scheduled against the other process. Sleep. */ - spin_max = low_spin_max; - yield: - for (i = 0;; ++i) { - if (!GC_test_and_set(&GC_allocate_lock)) { - return; - } - # define SLEEP_THRESHOLD 12 - /* nanosleep(<= 2ms) just spins under Linux. We */ - /* want to be careful to avoid that behavior. */ - if (i < SLEEP_THRESHOLD) { - sched_yield(); - } else { - struct timespec ts; - - if (i > 24) i = 24; - /* Don't wait for more than about 15msecs, even */ - /* under extreme contention. */ - ts.tv_sec = 0; - ts.tv_nsec = 1 << i; - nanosleep(&ts, 0); - } - } - } - - #else /* !USE_SPINLOCK */ - - void GC_lock() - { - if (1 == GC_nprocs || GC_collecting) { - pthread_mutex_lock(&GC_allocate_ml); - } else { - GC_generic_lock(&GC_allocate_ml); - } - } - - #endif /* !USE_SPINLOCK */ - - #if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) - - #ifdef GC_ASSERTIONS - pthread_t GC_mark_lock_holder = NO_THREAD; - #endif - - #if 0 - /* Ugly workaround for a linux threads bug in the final versions */ - /* of glibc2.1. Pthread_mutex_trylock sets the mutex owner */ - /* field even when it fails to acquire the mutex. This causes */ - /* pthread_cond_wait to die. Remove for glibc2.2. */ - /* According to the man page, we should use */ - /* PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, but that isn't actually */ - /* defined. */ - static pthread_mutex_t mark_mutex = - {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, {0, 0}}; - #else - static pthread_mutex_t mark_mutex = PTHREAD_MUTEX_INITIALIZER; - #endif - - static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER; - - void GC_acquire_mark_lock() - { - /* - if (pthread_mutex_lock(&mark_mutex) != 0) { - ABORT("pthread_mutex_lock failed"); - } - */ - GC_generic_lock(&mark_mutex); - # ifdef GC_ASSERTIONS - GC_mark_lock_holder = pthread_self(); - # endif - } - - void GC_release_mark_lock() - { - GC_ASSERT(GC_mark_lock_holder == pthread_self()); - # ifdef GC_ASSERTIONS - GC_mark_lock_holder = NO_THREAD; - # endif - if (pthread_mutex_unlock(&mark_mutex) != 0) { - ABORT("pthread_mutex_unlock failed"); - } - } - - /* Collector must wait for a freelist builders for 2 reasons: */ - /* 1) Mark bits may still be getting examined without lock. */ - /* 2) Partial free lists referenced only by locals may not be scanned */ - /* correctly, e.g. if they contain "pointer-free" objects, since the */ - /* free-list link may be ignored. */ - void GC_wait_builder() - { - GC_ASSERT(GC_mark_lock_holder == pthread_self()); - # ifdef GC_ASSERTIONS - GC_mark_lock_holder = NO_THREAD; - # endif - if (pthread_cond_wait(&builder_cv, &mark_mutex) != 0) { - ABORT("pthread_cond_wait failed"); - } - GC_ASSERT(GC_mark_lock_holder == NO_THREAD); - # ifdef GC_ASSERTIONS - GC_mark_lock_holder = pthread_self(); - # endif - } - - void GC_wait_for_reclaim() - { - GC_acquire_mark_lock(); - while (GC_fl_builder_count > 0) { - GC_wait_builder(); - } - GC_release_mark_lock(); - } - - void GC_notify_all_builder() - { - GC_ASSERT(GC_mark_lock_holder == pthread_self()); - if (pthread_cond_broadcast(&builder_cv) != 0) { - ABORT("pthread_cond_broadcast failed"); - } - } - - #endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */ - - #ifdef PARALLEL_MARK - - static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER; - - void GC_wait_marker() - { - GC_ASSERT(GC_mark_lock_holder == pthread_self()); - # ifdef GC_ASSERTIONS - GC_mark_lock_holder = NO_THREAD; - # endif - if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) { - ABORT("pthread_cond_wait failed"); - } - GC_ASSERT(GC_mark_lock_holder == NO_THREAD); - # ifdef GC_ASSERTIONS - GC_mark_lock_holder = pthread_self(); - # endif - } - - void GC_notify_all_marker() - { - if (pthread_cond_broadcast(&mark_cv) != 0) { - ABORT("pthread_cond_broadcast failed"); - } - } - - #endif /* PARALLEL_MARK */ - - # endif /* GC_LINUX_THREADS and friends */ - --- 0 ---- diff -Nrc3pad gcc-3.3.3/boehm-gc/Mac_files/MacOS_config.h gcc-3.4.0/boehm-gc/Mac_files/MacOS_config.h *** gcc-3.3.3/boehm-gc/Mac_files/MacOS_config.h 2001-08-17 18:30:47.000000000 +0000 --- gcc-3.4.0/boehm-gc/Mac_files/MacOS_config.h 2003-07-28 04:18:21.000000000 +0000 *************** *** 72,78 **** // implementations, and it sometimes has a significant performance // impact. However, it is dangerous for many not-quite-ANSI C // programs that call things like printf in asynchronous signal handlers. ! // -DOPERATOR_NEW_ARRAY declares that the C++ compiler supports the // new syntax "operator new[]" for allocating and deleting arrays. // See gc_cpp.h for details. No effect on the C part of the collector. // This is defined implicitly in a few environments. --- 72,78 ---- // implementations, and it sometimes has a significant performance // impact. However, it is dangerous for many not-quite-ANSI C // programs that call things like printf in asynchronous signal handlers. ! // -DGC_OPERATOR_NEW_ARRAY declares that the C++ compiler supports the // new syntax "operator new[]" for allocating and deleting arrays. // See gc_cpp.h for details. No effect on the C part of the collector. // This is defined implicitly in a few environments. *************** *** 86,89 **** // since some ports use malloc or calloc to obtain system memory. // (Probably works for UNIX, and win32.) // -DNO_DEBUG removes GC_dump and the debugging routines it calls. ! // Reduces code size slightly at the expense of debuggability. \ No newline at end of file --- 86,89 ---- // since some ports use malloc or calloc to obtain system memory. // (Probably works for UNIX, and win32.) // -DNO_DEBUG removes GC_dump and the debugging routines it calls. ! // Reduces code size slightly at the expense of debuggability. diff -Nrc3pad gcc-3.3.3/boehm-gc/Mac_files/MacOS_Test_config.h gcc-3.4.0/boehm-gc/Mac_files/MacOS_Test_config.h *** gcc-3.3.3/boehm-gc/Mac_files/MacOS_Test_config.h 2001-08-17 18:30:47.000000000 +0000 --- gcc-3.4.0/boehm-gc/Mac_files/MacOS_Test_config.h 2003-07-28 04:18:21.000000000 +0000 *************** *** 74,80 **** // implementations, and it sometimes has a significant performance // impact. However, it is dangerous for many not-quite-ANSI C // programs that call things like printf in asynchronous signal handlers. ! // -DOPERATOR_NEW_ARRAY declares that the C++ compiler supports the // new syntax "operator new[]" for allocating and deleting arrays. // See gc_cpp.h for details. No effect on the C part of the collector. // This is defined implicitly in a few environments. --- 74,80 ---- // implementations, and it sometimes has a significant performance // impact. However, it is dangerous for many not-quite-ANSI C // programs that call things like printf in asynchronous signal handlers. ! // -DGC_OPERATOR_NEW_ARRAY declares that the C++ compiler supports the // new syntax "operator new[]" for allocating and deleting arrays. // See gc_cpp.h for details. No effect on the C part of the collector. // This is defined implicitly in a few environments. diff -Nrc3pad gcc-3.3.3/boehm-gc/mach_dep.c gcc-3.4.0/boehm-gc/mach_dep.c *** gcc-3.3.3/boehm-gc/mach_dep.c 2002-07-18 20:06:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/mach_dep.c 2003-10-03 18:43:06.000000000 +0000 *************** asm static void PushMacRegisters() *** 74,80 **** /* on your architecture. Run the test_setjmp program to see whether */ /* there is any chance it will work. */ ! #ifndef USE_GENERIC_PUSH_REGS void GC_push_regs() { # ifdef RT --- 74,81 ---- /* on your architecture. Run the test_setjmp program to see whether */ /* there is any chance it will work. */ ! #if !defined(USE_GENERIC_PUSH_REGS) && !defined(USE_ASM_PUSH_REGS) ! #undef HAVE_PUSH_REGS void GC_push_regs() { # ifdef RT *************** void GC_push_regs() *** 91,96 **** --- 92,98 ---- asm("pushl r8"); asm("calls $1,_GC_push_one"); asm("pushl r7"); asm("calls $1,_GC_push_one"); asm("pushl r6"); asm("calls $1,_GC_push_one"); + # define HAVE_PUSH_REGS # endif # if defined(M68K) && (defined(SUNOS4) || defined(NEXT)) /* M68K SUNOS - could be replaced by generic code */ *************** void GC_push_regs() *** 113,118 **** --- 115,121 ---- asm("movl d7,sp@"); asm("jbsr _GC_push_one"); asm("addqw #0x4,sp"); /* put stack back where it was */ + # define HAVE_PUSH_REGS # endif # if defined(M68K) && defined(HP) *************** void GC_push_regs() *** 135,140 **** --- 138,144 ---- asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one"); asm("addq.w &0x4,%sp"); /* put stack back where it was */ + # define HAVE_PUSH_REGS # endif /* M68K HP */ # if defined(M68K) && defined(AMIGA) *************** void GC_push_regs() *** 158,163 **** --- 162,168 ---- asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one"); asm("addq.w &0x4,%sp"); /* put stack back where it was */ + # define HAVE_PUSH_REGS # else /* !__GNUC__ */ GC_push_one(getreg(REG_A2)); GC_push_one(getreg(REG_A3)); *************** void GC_push_regs() *** 174,179 **** --- 179,185 ---- GC_push_one(getreg(REG_D5)); GC_push_one(getreg(REG_D6)); GC_push_one(getreg(REG_D7)); + # define HAVE_PUSH_REGS # endif /* !__GNUC__ */ # endif /* AMIGA */ *************** void GC_push_regs() *** 196,205 **** --- 202,213 ---- PushMacReg(d7); add.w #4,sp ; fix stack. } + # define HAVE_PUSH_REGS # undef PushMacReg # endif /* THINK_C */ # if defined(__MWERKS__) PushMacRegisters(); + # define HAVE_PUSH_REGS # endif /* __MWERKS__ */ # endif /* MACOS */ *************** void GC_push_regs() *** 222,234 **** asm("pushl %esi"); asm("call _GC_push_one"); asm("addl $4,%esp"); asm("pushl %edi"); asm("call _GC_push_one"); asm("addl $4,%esp"); asm("pushl %ebx"); asm("call _GC_push_one"); asm("addl $4,%esp"); # endif # if ( defined(I386) && defined(LINUX) && defined(__ELF__) ) \ || ( defined(I386) && defined(FREEBSD) && defined(__ELF__) ) \ || ( defined(I386) && defined(NETBSD) && defined(__ELF__) ) \ || ( defined(I386) && defined(OPENBSD) && defined(__ELF__) ) \ ! || ( defined(I386) && defined(HURD) && defined(__ELF__) ) /* This is modified for Linux with ELF (Note: _ELF_ only) */ /* This section handles FreeBSD with ELF. */ --- 230,244 ---- asm("pushl %esi"); asm("call _GC_push_one"); asm("addl $4,%esp"); asm("pushl %edi"); asm("call _GC_push_one"); asm("addl $4,%esp"); asm("pushl %ebx"); asm("call _GC_push_one"); asm("addl $4,%esp"); + # define HAVE_PUSH_REGS # endif # if ( defined(I386) && defined(LINUX) && defined(__ELF__) ) \ || ( defined(I386) && defined(FREEBSD) && defined(__ELF__) ) \ || ( defined(I386) && defined(NETBSD) && defined(__ELF__) ) \ || ( defined(I386) && defined(OPENBSD) && defined(__ELF__) ) \ ! || ( defined(I386) && defined(HURD) && defined(__ELF__) ) \ ! || ( defined(I386) && defined(DGUX) ) /* This is modified for Linux with ELF (Note: _ELF_ only) */ /* This section handles FreeBSD with ELF. */ *************** void GC_push_regs() *** 243,248 **** --- 253,259 ---- asm("pushl %esi; call GC_push_one; addl $4,%esp"); asm("pushl %edi; call GC_push_one; addl $4,%esp"); asm("pushl %ebx; call GC_push_one; addl $4,%esp"); + # define HAVE_PUSH_REGS # endif # if ( defined(I386) && defined(BEOS) && defined(__ELF__) ) *************** void GC_push_regs() *** 254,259 **** --- 265,271 ---- asm("pushl %esi; call GC_push_one; addl $4,%esp"); asm("pushl %edi; call GC_push_one; addl $4,%esp"); asm("pushl %ebx; call GC_push_one; addl $4,%esp"); + # define HAVE_PUSH_REGS # endif # if defined(I386) && defined(MSWIN32) && !defined(__MINGW32__) \ *************** void GC_push_regs() *** 280,285 **** --- 292,298 ---- __asm push edi __asm call GC_push_one __asm add esp,4 + # define HAVE_PUSH_REGS # endif # if defined(I386) && (defined(SVR4) || defined(SCO) || defined(SCO_ELF)) *************** void GC_push_regs() *** 291,296 **** --- 304,310 ---- asm("pushl %ebp"); asm("call GC_push_one"); asm("addl $4,%esp"); asm("pushl %esi"); asm("call GC_push_one"); asm("addl $4,%esp"); asm("pushl %edi"); asm("call GC_push_one"); asm("addl $4,%esp"); + # define HAVE_PUSH_REGS # endif # ifdef NS32K *************** void GC_push_regs() *** 299,312 **** asm ("movd r5, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r6, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r7, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); # endif # if defined(SPARC) ! { ! word GC_save_regs_in_stack(); ! ! GC_save_regs_ret_val = GC_save_regs_in_stack(); ! } # endif # ifdef RT --- 313,324 ---- asm ("movd r5, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r6, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r7, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); + # define HAVE_PUSH_REGS # endif # if defined(SPARC) ! GC_save_regs_ret_val = GC_save_regs_in_stack(); ! # define HAVE_PUSH_REGS # endif # ifdef RT *************** void GC_push_regs() *** 322,327 **** --- 334,340 ---- asm("cas r11, r13, r0"); GC_push_one(TMP_SP); /* through */ asm("cas r11, r14, r0"); GC_push_one(TMP_SP); /* r15 */ asm("cas r11, r15, r0"); GC_push_one(TMP_SP); + # define HAVE_PUSH_REGS # endif # if defined(M68K) && defined(SYSV) *************** void GC_push_regs() *** 345,350 **** --- 358,364 ---- asm("movl %d7,%sp@"); asm("jbsr GC_push_one"); asm("addqw #0x4,%sp"); /* put stack back where it was */ + # define HAVE_PUSH_REGS # else /* !__GNUC__*/ asm("subq.w &0x4,%sp"); /* allocate word on top of stack */ *************** void GC_push_regs() *** 362,367 **** --- 376,382 ---- asm("mov.l %d7,(%sp)"); asm("jsr GC_push_one"); asm("addq.w &0x4,%sp"); /* put stack back where it was */ + # define HAVE_PUSH_REGS # endif /* !__GNUC__ */ # endif /* M68K/SYSV */ *************** void GC_push_regs() *** 371,397 **** extern int *__libc_stack_end; GC_push_all_stack (sp, __libc_stack_end); } # endif /* other machines... */ ! # if !defined(M68K) && !defined(VAX) && !defined(RT) ! # if !defined(SPARC) && !defined(I386) && !defined(NS32K) ! # if !defined(POWERPC) && !defined(UTS4) ! # if !defined(PJ) && !(defined(MIPS) && defined(LINUX)) ! --> bad news <-- ! # endif ! # endif ! # endif # endif } ! #endif /* !USE_GENERIC_PUSH_REGS */ #if defined(USE_GENERIC_PUSH_REGS) void GC_generic_push_regs(cold_gc_frame) ptr_t cold_gc_frame; { { # ifdef HAVE_BUILTIN_UNWIND_INIT /* This was suggested by Richard Henderson as the way to */ /* force callee-save registers and register windows onto */ --- 386,412 ---- extern int *__libc_stack_end; GC_push_all_stack (sp, __libc_stack_end); + # define HAVE_PUSH_REGS + /* Isn't this redundant with the code to push the stack? */ } # endif /* other machines... */ ! # if !defined(HAVE_PUSH_REGS) ! --> We just generated an empty GC_push_regs, which ! --> is almost certainly broken. Try defining ! --> USE_GENERIC_PUSH_REGS instead. # endif } ! #endif /* !USE_GENERIC_PUSH_REGS && !USE_ASM_PUSH_REGS */ #if defined(USE_GENERIC_PUSH_REGS) void GC_generic_push_regs(cold_gc_frame) ptr_t cold_gc_frame; { { + word dummy; + # ifdef HAVE_BUILTIN_UNWIND_INIT /* This was suggested by Richard Henderson as the way to */ /* force callee-save registers and register windows onto */ *************** ptr_t cold_gc_frame; *** 427,434 **** /* needed on IA64, since some non-windowed registers are */ /* preserved. */ { - word GC_save_regs_in_stack(); - GC_save_regs_ret_val = GC_save_regs_in_stack(); /* On IA64 gcc, could use __builtin_ia64_flushrs() and */ /* __builtin_ia64_flushrs(). The latter will be done */ --- 442,447 ---- *************** ptr_t cold_gc_frame; *** 437,442 **** --- 450,459 ---- } # endif GC_push_current_stack(cold_gc_frame); + /* 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 /* USE_GENERIC_PUSH_REGS */ *************** ptr_t cold_gc_frame; *** 445,451 **** /* the stack. Return sp. */ # ifdef SPARC asm(" .seg \"text\""); ! # ifdef SVR4 asm(" .globl GC_save_regs_in_stack"); asm("GC_save_regs_in_stack:"); asm(" .type GC_save_regs_in_stack,#function"); --- 462,468 ---- /* the stack. Return sp. */ # ifdef SPARC asm(" .seg \"text\""); ! # if defined(SVR4) || defined(NETBSD) asm(" .globl GC_save_regs_in_stack"); asm("GC_save_regs_in_stack:"); asm(" .type GC_save_regs_in_stack,#function"); diff -Nrc3pad gcc-3.3.3/boehm-gc/Makefile.am gcc-3.4.0/boehm-gc/Makefile.am *** gcc-3.3.3/boehm-gc/Makefile.am 2003-01-28 01:44:52.000000000 +0000 --- gcc-3.4.0/boehm-gc/Makefile.am 2003-07-28 04:18:19.000000000 +0000 *************** MULTICLEAN = true *** 18,32 **** noinst_LTLIBRARIES = libgcjgc.la libgcjgc_convenience.la GC_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 irix_threads.c \ ! linux_threads.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 \ solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \ ! backgraph.c win32_threads.c ! EXTRA_GC_SOURCES = alpha_mach_dep.s \ ! mips_sgi_mach_dep.S mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \ rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \ sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s --- 18,40 ---- noinst_LTLIBRARIES = libgcjgc.la libgcjgc_convenience.la + if POWERPC_DARWIN + asm_libgc_sources = powerpc_darwin_mach_dep.s + else + asm_libgc_sources = + endif + GC_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 aix_irix_threads.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 \ solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \ ! backgraph.c win32_threads.c \ ! pthread_support.c pthread_stop_world.c darwin_stop_world.c \ ! $(asm_libgc_sources) ! EXTRA_GC_SOURCES = alpha_mach_dep.S \ ! mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_darwin_mach_dep.s \ rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \ sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s *************** TESTS = gctest *** 63,69 **** ## FIXME: relies on internal code generated by automake. all_objs = @addobjs@ $(libgcjgc_la_OBJECTS) $(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \ ! include/private/gc_hdrs.h include/gc.h include/gc_gcj.h include/gc_mark.h ## FIXME: we shouldn't have to do this, but automake forces us to. .s.lo: --- 71,79 ---- ## FIXME: relies on internal code generated by automake. all_objs = @addobjs@ $(libgcjgc_la_OBJECTS) $(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \ ! include/private/gc_hdrs.h include/gc.h include/gc_gcj.h \ ! include/gc_pthread_redirects.h include/gc_config_macros.h \ ! include/gc_mark.h @addincludes@ ## FIXME: we shouldn't have to do this, but automake forces us to. .s.lo: diff -Nrc3pad gcc-3.3.3/boehm-gc/Makefile.direct gcc-3.4.0/boehm-gc/Makefile.direct *** gcc-3.3.3/boehm-gc/Makefile.direct 2002-02-12 04:37:53.000000000 +0000 --- gcc-3.4.0/boehm-gc/Makefile.direct 2003-07-28 04:18:20.000000000 +0000 *************** CFLAGS= -O -I$(srcdir)/include -DATOMIC_ *** 27,34 **** # To build the parallel collector on Linux, add to the above: # -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC ! # To build the parallel collector n a static library on HP/UX, add to the above: # -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -DUSE_HPUX_TLS -D_POSIX_C_SOURCE=199506L # HOSTCC and HOSTCFLAGS are used to build executables that will be run as # part of the build process, i.e. on the build machine. These will usually --- 27,37 ---- # To build the parallel collector on Linux, add to the above: # -DGC_LINUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC ! # To build the parallel collector in a static library on HP/UX, ! # add to the above: # -DGC_HPUX_THREADS -DPARALLEL_MARK -DTHREAD_LOCAL_ALLOC -DUSE_HPUX_TLS -D_POSIX_C_SOURCE=199506L + # To build the thread-safe collector on Tru64, add to the above: + # -pthread -DGC_OSF1_THREADS # HOSTCC and HOSTCFLAGS are used to build executables that will be run as # part of the build process, i.e. on the build machine. These will usually *************** HOSTCFLAGS=$(CFLAGS) *** 60,65 **** --- 63,78 ---- # Also requires -D_REENTRANT or -D_POSIX_C_SOURCE=199506L. See README.hp. # -DGC_LINUX_THREADS enables support for Xavier Leroy's Linux threads. # see README.linux. -D_REENTRANT may also be required. + # -DGC_OSF1_THREADS enables support for Tru64 pthreads. Untested. + # -DGC_FREEBSD_THREADS enables support for FreeBSD pthreads. Untested. + # Appeared to run into some underlying thread problems. + # -DGC_DARWIN_THREADS enables support for Mac OS X pthreads. Untested. + # -DGC_DGUX386_THREADS enables support for DB/UX on I386 threads. + # See README.DGUX386. + # -DGC_WIN32_THREADS enables support for win32 threads. That makes sense + # for this Makefile only under Cygwin. + # -DGC_THREADS should set the appropriate one of the above macros. + # It assumes pthreads for Solaris. # -DALL_INTERIOR_POINTERS allows all pointers to the interior # of objects to be recognized. (See gc_priv.h for consequences.) # Alternatively, GC_all_interior_pointers can be set at process *************** HOSTCFLAGS=$(CFLAGS) *** 93,105 **** # See gc_cpp.h for details. No effect on the C part of the collector. # This is defined implicitly in a few environments. Must also be defined # by clients that use gc_cpp.h. ! # -DREDIRECT_MALLOC=X causes malloc, realloc, and free to be ! # defined as aliases for X, GC_realloc, and GC_free, respectively. # Calloc and strdup are redefined in terms of the new malloc. X should # be either GC_malloc or GC_malloc_uncollectable, or # GC_debug_malloc_replacement. (The latter invokes GC_debug_malloc # with dummy source location information, but still results in ! # properly remembered call stacks on Linux/X86 and Solaris/SPARC.) # The former is occasionally useful for working around leaks in code # you don't want to (or can't) look at. It may not work for # existing code, but it often does. Neither works on all platforms, --- 106,120 ---- # See gc_cpp.h for details. No effect on the C part of the collector. # This is defined implicitly in a few environments. Must also be defined # by clients that use gc_cpp.h. ! # -DREDIRECT_MALLOC=X causes malloc to be defined as alias for X. ! # Unless the following macros are defined, realloc is also redirected ! # to GC_realloc, and free is redirected to GC_free. # Calloc and strdup are redefined in terms of the new malloc. X should # be either GC_malloc or GC_malloc_uncollectable, or # GC_debug_malloc_replacement. (The latter invokes GC_debug_malloc # with dummy source location information, but still results in ! # properly remembered call stacks on Linux/X86 and Solaris/SPARC. ! # It requires that the following two macros also be used.) # The former is occasionally useful for working around leaks in code # you don't want to (or can't) look at. It may not work for # existing code, but it often does. Neither works on all platforms, *************** HOSTCFLAGS=$(CFLAGS) *** 111,116 **** --- 126,134 ---- # The canonical use is -DREDIRECT_REALLOC=GC_debug_realloc_replacement, # together with -DREDIRECT_MALLOC=GC_debug_malloc_replacement to # generate leak reports with call stacks for both malloc and realloc. + # This also requires the following: + # -DREDIRECT_FREE=X causes free to be redirected to X. The + # canonical use is -DREDIRECT_FREE=GC_debug_free. # -DIGNORE_FREE turns calls to free into a noop. Only useful with # -DREDIRECT_MALLOC. # -DNO_DEBUGGING removes GC_dump and the debugging routines it calls. *************** HOSTCFLAGS=$(CFLAGS) *** 197,204 **** # 15% or so. # -DUSE_3DNOW_PREFETCH causes the collector to issue AMD 3DNow style # prefetch instructions. Same restrictions as USE_I686_PREFETCH. ! # UNTESTED!! ! # -DGC_USE_LD_WRAP in combination with the gld flags listed in README.linux # causes the collector some system and pthread calls in a more transparent # fashion than the usual macro-based approach. Requires GNU ld, and # currently probably works only with Linux. --- 215,225 ---- # 15% or so. # -DUSE_3DNOW_PREFETCH causes the collector to issue AMD 3DNow style # prefetch instructions. Same restrictions as USE_I686_PREFETCH. ! # Minimally tested. Didn't appear to be an obvious win on a K6-2/500. ! # -DUSE_PPC_PREFETCH causes the collector to issue PowerPC style ! # prefetch instructions. No effect except on PowerPC OS X platforms. ! # Performance impact untested. ! # -DGC_USE_LD_WRAP in combination with the old flags listed in README.linux # causes the collector some system and pthread calls in a more transparent # fashion than the usual macro-based approach. Requires GNU ld, and # currently probably works only with Linux. *************** HOSTCFLAGS=$(CFLAGS) *** 226,231 **** --- 247,270 ---- # -DSTUBBORN_ALLOC allows allocation of "hard to change" objects, and thus # makes incremental collection easier. Was enabled by default until 6.0. # Rarely used, to my knowledge. + # -DHANDLE_FORK attempts to make GC_malloc() work in a child process fork()ed + # from a multithreaded parent. Currently only supported by pthread_support.c. + # (Similar code should work on Solaris or Irix, but it hasn't been tried.) + # -DTEST_WITH_SYSTEM_MALLOC causes gctest to allocate (and leak) large chunks + # of memory with the standard system malloc. This will cause the root + # set and collected heap to grow significantly if malloced memory is + # somehow getting traced by the collector. This has no impact on the + # generated library; it only affects the test. + # -DPOINTER_MASK=0x... causes candidate pointers to be ANDed with the + # given mask before being considered. If either this or the following + # macro is defined, it will be assumed that all pointers stored in + # the heap need to be processed this way. Stack and register pointers + # will be considered both with and without processing. + # These macros are normally needed only to support systems that use + # high-order pointer tags. EXPERIMENTAL. + # -DPOINTER_SHIFT=n causes the collector to left shift candidate pointers + # by the indicated amount before trying to interpret them. Applied + # after POINTER_MASK. EXPERIMENTAL. See also the preceding macro. # CXXFLAGS= $(CFLAGS) *************** AR= ar *** 233,247 **** RANLIB= ranlib ! OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o irix_threads.o linux_threads.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o gcj_mlc.o specific.o gc_dlopen.o backgraph.o ! CSRCS= 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 malloc.c stubborn.c checksums.c solaris_threads.c irix_threads.c linux_threads.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c gc_dlopen.c backgraph.c CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o ! SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.s \ sparc_mach_dep.S include/gc.h include/gc_typed.h \ include/private/gc_hdrs.h include/private/gc_priv.h \ include/private/gcconfig.h include/private/gc_pmark.h \ --- 272,286 ---- RANLIB= ranlib ! OBJS= alloc.o reclaim.o allchblk.o misc.o mach_dep.o os_dep.o mark_rts.o headers.o mark.o obj_map.o blacklst.o finalize.o new_hblk.o dbg_mlc.o malloc.o stubborn.o checksums.o solaris_threads.o aix_irix_threads.o pthread_support.o pthread_stop_world.o darwin_stop_world.o typd_mlc.o ptr_chck.o mallocx.o solaris_pthreads.o gcj_mlc.o specific.o gc_dlopen.o backgraph.o win32_threads.o ! CSRCS= 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 malloc.c stubborn.c checksums.c solaris_threads.c aix_irix_threads.c pthread_support.c pthread_stop_world.c darwin_stop_world.c typd_mlc.c ptr_chck.c mallocx.c solaris_pthreads.c gcj_mlc.c specific.c gc_dlopen.c backgraph.c win32_threads.c CORD_SRCS= cord/cordbscs.c cord/cordxtra.c cord/cordprnt.c cord/de.c cord/cordtest.c include/cord.h include/ec.h include/private/cord_pos.h cord/de_win.c cord/de_win.h cord/de_cmds.h cord/de_win.ICO cord/de_win.RC CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o ! SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.S \ sparc_mach_dep.S include/gc.h include/gc_typed.h \ include/private/gc_hdrs.h include/private/gc_priv.h \ include/private/gcconfig.h include/private/gc_pmark.h \ *************** SRCS= $(CSRCS) mips_sgi_mach_dep.s rs600 *** 249,262 **** threadlibs.c if_mach.c if_not_there.c gc_cpp.cc include/gc_cpp.h \ gcname.c include/weakpointer.h include/private/gc_locks.h \ gcc_support.c mips_ultrix_mach_dep.s include/gc_alloc.h \ ! include/new_gc_alloc.h include/javaxfc.h sparc_sunos4_mach_dep.s \ ! sparc_netbsd_mach_dep.s \ include/private/solaris_threads.h include/gc_backptr.h \ hpux_test_and_clear.s include/gc_gcj.h \ include/gc_local_alloc.h include/private/dbg_mlc.h \ ! include/private/specific.h powerpc_macosx_mach_dep.s \ include/leak_detector.h include/gc_amiga_redirects.h \ ! include/gc_pthread_redirects.h $(CORD_SRCS) DOC_FILES= README.QUICK doc/README.Mac doc/README.MacOSX doc/README.OS2 \ doc/README.amiga doc/README.cords doc/debugging.html \ --- 288,304 ---- threadlibs.c if_mach.c if_not_there.c gc_cpp.cc include/gc_cpp.h \ gcname.c include/weakpointer.h include/private/gc_locks.h \ gcc_support.c mips_ultrix_mach_dep.s include/gc_alloc.h \ ! include/new_gc_alloc.h include/gc_allocator.h \ ! include/javaxfc.h sparc_sunos4_mach_dep.s sparc_netbsd_mach_dep.s \ include/private/solaris_threads.h include/gc_backptr.h \ hpux_test_and_clear.s include/gc_gcj.h \ include/gc_local_alloc.h include/private/dbg_mlc.h \ ! include/private/specific.h powerpc_darwin_mach_dep.s \ include/leak_detector.h include/gc_amiga_redirects.h \ ! include/gc_pthread_redirects.h ia64_save_regs_in_stack.s \ ! include/gc_config_macros.h include/private/pthread_support.h \ ! include/private/pthread_stop_world.h include/private/darwin_semaphore.h \ ! include/private/darwin_stop_world.h $(CORD_SRCS) DOC_FILES= README.QUICK doc/README.Mac doc/README.MacOSX doc/README.OS2 \ doc/README.amiga doc/README.cords doc/debugging.html \ *************** DOC_FILES= README.QUICK doc/README.Mac d *** 265,279 **** doc/README.win32 doc/barrett_diagram doc/README \ doc/README.contributors doc/README.changes doc/gc.man \ doc/README.environment doc/tree.html doc/gcdescr.html \ ! doc/README.autoconf doc/README.macros doc/README.ews4800 TESTS= tests/test.c tests/test_cpp.cc tests/trace_test.c \ tests/leak_test.c tests/thread_leak_test.c GNU_BUILD_FILES= configure.in Makefile.am configure acinclude.m4 \ libtool.m4 install-sh configure.host Makefile.in \ ! aclocal.m4 config.sub config.guess ltconfig \ ! ltmain.sh mkinstalldirs OTHER_MAKEFILES= OS2_MAKEFILE NT_MAKEFILE NT_THREADS_MAKEFILE gc.mak \ BCC_MAKEFILE EMX_MAKEFILE WCC_MAKEFILE Makefile.dj \ --- 307,325 ---- doc/README.win32 doc/barrett_diagram doc/README \ doc/README.contributors doc/README.changes doc/gc.man \ doc/README.environment doc/tree.html doc/gcdescr.html \ ! doc/README.autoconf doc/README.macros doc/README.ews4800 \ ! doc/README.DGUX386 doc/README.arm.cross doc/leak.html \ ! doc/scale.html doc/gcinterface.html doc/README.darwin TESTS= tests/test.c tests/test_cpp.cc tests/trace_test.c \ tests/leak_test.c tests/thread_leak_test.c GNU_BUILD_FILES= configure.in Makefile.am configure acinclude.m4 \ libtool.m4 install-sh configure.host Makefile.in \ ! ltconfig aclocal.m4 config.sub config.guess \ ! include/Makefile.am include/Makefile.in \ ! doc/Makefile.am doc/Makefile.in \ ! ltmain.sh mkinstalldirs depcomp missing OTHER_MAKEFILES= OS2_MAKEFILE NT_MAKEFILE NT_THREADS_MAKEFILE gc.mak \ BCC_MAKEFILE EMX_MAKEFILE WCC_MAKEFILE Makefile.dj \ *************** OTHER_FILES= Makefile setjmp_t.c callpro *** 285,291 **** MacProjects.sit.hqx MacOS.c \ Mac_files/datastart.c Mac_files/dataend.c \ Mac_files/MacOS_config.h Mac_files/MacOS_Test_config.h \ ! add_gc_prefix.c gc_cpp.cpp win32_threads.c \ version.h AmigaOS.c \ $(TESTS) $(GNU_BUILD_FILES) $(OTHER_MAKEFILES) --- 331,337 ---- MacProjects.sit.hqx MacOS.c \ Mac_files/datastart.c Mac_files/dataend.c \ Mac_files/MacOS_config.h Mac_files/MacOS_Test_config.h \ ! add_gc_prefix.c gc_cpp.cpp \ version.h AmigaOS.c \ $(TESTS) $(GNU_BUILD_FILES) $(OTHER_MAKEFILES) *************** mach_dep.o $(SRCS) *** 330,345 **** $(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/private/gcconfig.h $(srcdir)/include/gc_typed.h \ ! Makefile # The dependency on Makefile is needed. Changing # options such as -DSILENT affects the size of GC_arrays, # invalidating all .o files that rely on gc_priv.h mark.o typd_mlc.o finalize.o ptr_chck.o: $(srcdir)/include/gc_mark.h $(srcdir)/include/private/gc_pmark.h ! specific.o linux_threads.o: $(srcdir)/include/private/specific.h solaris_threads.o solaris_pthreads.o: $(srcdir)/include/private/solaris_threads.h --- 376,391 ---- $(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 Makefile # The dependency on Makefile is needed. Changing # options such as -DSILENT affects the size of GC_arrays, # invalidating all .o files that rely on gc_priv.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: $(srcdir)/include/private/specific.h solaris_threads.o solaris_pthreads.o: $(srcdir)/include/private/solaris_threads.h *************** liblinuxgc.so: $(OBJS) dyn_load.o *** 434,450 **** # 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)/mips_sgi_mach_dep.s $(srcdir)/mips_ultrix_mach_dep.s \ ! $(srcdir)/rs6000_mach_dep.s $(srcdir)/powerpc_macosx_mach_dep.s $(UTILS) rm -f mach_dep.o ! ./if_mach MIPS IRIX5 $(AS) -o mach_dep.o $(srcdir)/mips_sgi_mach_dep.s ./if_mach MIPS RISCOS $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s ./if_mach MIPS ULTRIX $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s ! ./if_mach RS6000 "" $(AS) -o mach_dep.o $(srcdir)/rs6000_mach_dep.s ! ./if_mach POWERPC MACOSX $(AS) -o mach_dep.o $(srcdir)/powerpc_macosx_mach_dep.s ! # ./if_mach ALPHA "" $(AS) -o mach_dep.o $(srcdir)/alpha_mach_dep.s ! # alpha_mach_dep.s assumes that pointers are not saved in fp registers. ! # Gcc on a 21264 can spill pointers to fp registers. Oops. ./if_mach SPARC SUNOS5 $(CC) -c -o mach_dep.o $(srcdir)/sparc_mach_dep.S ./if_mach SPARC SUNOS4 $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s ./if_mach SPARC OPENBSD $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s --- 480,497 ---- # 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)/mips_sgi_mach_dep.s \ ! $(srcdir)/mips_ultrix_mach_dep.s \ ! $(srcdir)/rs6000_mach_dep.s $(srcdir)/powerpc_darwin_mach_dep.s \ ! $(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) rm -f mach_dep.o ! ./if_mach MIPS IRIX5 $(CC) -c -o mach_dep.o $(srcdir)/mips_sgi_mach_dep.s ./if_mach MIPS RISCOS $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s ./if_mach MIPS ULTRIX $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s ! ./if_mach POWERPC DARWIN $(AS) -o mach_dep.o $(srcdir)/powerpc_darwin_mach_dep.s ! ./if_mach ALPHA LINUX $(CC) -c -o mach_dep.o $(srcdir)/alpha_mach_dep.S ./if_mach SPARC SUNOS5 $(CC) -c -o mach_dep.o $(srcdir)/sparc_mach_dep.S ./if_mach SPARC SUNOS4 $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s ./if_mach SPARC OPENBSD $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s *************** cord/de: $(srcdir)/cord/de.c cord/cordbs *** 491,497 **** ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/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/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -ldld `./threadlibs` ./if_mach RS6000 "" $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses ! ./if_mach POWERPC MACOSX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a ./if_mach I386 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs` ./if_mach ALPHA LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs` ./if_mach IA64 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs` --- 538,544 ---- ./if_mach SPARC DRSNX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/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/de.c cord/cordbscs.o cord/cordxtra.o gc.a $(CURSES) -ldld `./threadlibs` ./if_mach RS6000 "" $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses ! ./if_mach POWERPC DARWIN $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a ./if_mach I386 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs` ./if_mach ALPHA LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs` ./if_mach IA64 LINUX $(CC) $(CFLAGS) -o cord/de $(srcdir)/cord/de.c cord/cordbscs.o cord/cordxtra.o gc.a -lcurses `./threadlibs` *************** if_not_there: $(srcdir)/if_not_there.c *** 510,516 **** 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 \ ! threadlibs $(CORD_OBJS) cord/cordtest cord/de -rm -f *~ gctest: tests/test.o gc.a $(UTILS) --- 557,563 ---- 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 \ ! threadlibs $(CORD_OBJS) cord/cordtest cord/de -rm -f *~ gctest: tests/test.o gc.a $(UTILS) diff -Nrc3pad gcc-3.3.3/boehm-gc/Makefile.dj gcc-3.4.0/boehm-gc/Makefile.dj *** gcc-3.3.3/boehm-gc/Makefile.dj 2001-10-16 09:01:34.000000000 +0000 --- gcc-3.4.0/boehm-gc/Makefile.dj 2003-07-28 04:18:20.000000000 +0000 *************** CFLAGS= -O -I$(srcdir)/include -DATOMIC_ *** 152,158 **** # currently probably works only with Linux. ! CXXFLAGS= $(CFLAGS) -DOPERATOR_NEW_ARRAY AR= ar RANLIB= ranlib --- 152,158 ---- # currently probably works only with Linux. ! CXXFLAGS= $(CFLAGS) -DGC_OPERATOR_NEW_ARRAY AR= ar RANLIB= ranlib *************** CORD_SRCS= cord/cordbscs.c cord/cordxtr *** 165,172 **** CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o ! SRCS= $(CSRCS) mips_sgi_mach_dep.s rs6000_mach_dep.s alpha_mach_dep.s \ ! sparc_mach_dep.s include/gc.h include/gc_typed.h \ include/private/gc_hdrs.h include/private/gc_priv.h \ include/private/gcconfig.h include/private/gc_mark.h \ include/gc_inl.h include/gc_inline.h gc.man \ --- 165,172 ---- CORD_OBJS= cord/cordbscs.o cord/cordxtra.o cord/cordprnt.o ! SRCS= $(CSRCS) mips_sgi_mach_dep.S rs6000_mach_dep.s alpha_mach_dep.S \ ! sparc_mach_dep.S include/gc.h include/gc_typed.h \ include/private/gc_hdrs.h include/private/gc_priv.h \ include/private/gcconfig.h include/private/gc_mark.h \ include/gc_inl.h include/gc_inline.h gc.man \ *************** SRCS= $(CSRCS) mips_sgi_mach_dep.s rs600 *** 177,183 **** include/private/solaris_threads.h include/gc_backptr.h \ hpux_test_and_clear.s include/gc_gcj.h \ include/gc_local_alloc.h include/private/dbg_mlc.h \ ! include/private/specific.h powerpc_macosx_mach_dep.s \ include/leak_detector.h $(CORD_SRCS) OTHER_FILES= Makefile PCR-Makefile OS2_MAKEFILE NT_MAKEFILE BCC_MAKEFILE \ --- 177,183 ---- include/private/solaris_threads.h include/gc_backptr.h \ hpux_test_and_clear.s include/gc_gcj.h \ include/gc_local_alloc.h include/private/dbg_mlc.h \ ! include/private/specific.h powerpc_darwin_mach_dep.s \ include/leak_detector.h $(CORD_SRCS) OTHER_FILES= Makefile PCR-Makefile OS2_MAKEFILE NT_MAKEFILE BCC_MAKEFILE \ *************** liblinuxgc.so: $(OBJS) dyn_load.o *** 284,299 **** gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o -lo ln liblinuxgc.so libgc.so ! mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.s $(srcdir)/mips_ultrix_mach_dep.s \ ! $(srcdir)/rs6000_mach_dep.s $(srcdir)/powerpc_macosx_mach_dep.s $(UTILS) rm -f mach_dep.o ! ./if_mach MIPS IRIX5 $(AS) -o mach_dep.o $(srcdir)/mips_sgi_mach_dep.s ./if_mach MIPS RISCOS $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s ./if_mach MIPS ULTRIX $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s ./if_mach RS6000 "" $(AS) -o mach_dep.o $(srcdir)/rs6000_mach_dep.s ! ./if_mach POWERPC MACOSX $(AS) -o mach_dep.o $(srcdir)/powerpc_macosx_mach_dep.s ! ./if_mach ALPHA "" $(AS) -o mach_dep.o $(srcdir)/alpha_mach_dep.s ! ./if_mach SPARC SUNOS5 $(AS) -o mach_dep.o $(srcdir)/sparc_mach_dep.s ./if_mach SPARC SUNOS4 $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s ./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c --- 284,299 ---- gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o -lo ln liblinuxgc.so libgc.so ! mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.S $(srcdir)/mips_ultrix_mach_dep.s \ ! $(srcdir)/rs6000_mach_dep.s $(srcdir)/powerpc_darwin_mach_dep.s $(UTILS) rm -f mach_dep.o ! ./if_mach MIPS IRIX5 $(AS) -o mach_dep.o $(srcdir)/mips_sgi_mach_dep.S ./if_mach MIPS RISCOS $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s ./if_mach MIPS ULTRIX $(AS) -o mach_dep.o $(srcdir)/mips_ultrix_mach_dep.s ./if_mach RS6000 "" $(AS) -o mach_dep.o $(srcdir)/rs6000_mach_dep.s ! ./if_mach POWERPC MACOSX $(AS) -o mach_dep.o $(srcdir)/powerpc_darwin_mach_dep.s ! ./if_mach ALPHA "" $(AS) -o mach_dep.o $(srcdir)/alpha_mach_dep.S ! ./if_mach SPARC SUNOS5 $(AS) -o mach_dep.o $(srcdir)/sparc_mach_dep.S ./if_mach SPARC SUNOS4 $(AS) -o mach_dep.o $(srcdir)/sparc_sunos4_mach_dep.s ./if_not_there mach_dep.o $(CC) -c $(SPECIALCFLAGS) $(srcdir)/mach_dep.c diff -Nrc3pad gcc-3.3.3/boehm-gc/Makefile.in gcc-3.4.0/boehm-gc/Makefile.in *** gcc-3.3.3/boehm-gc/Makefile.in 2004-02-14 20:34:20.000000000 +0000 --- gcc-3.4.0/boehm-gc/Makefile.in 2004-04-19 02:23:04.000000000 +0000 *************** *** 1,6 **** ! # Makefile.in generated automatically by automake 1.4 from Makefile.am ! # Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. # This Makefile.in 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. --- 1,6 ---- ! # Makefile.in generated automatically by automake 1.4-p5 from Makefile.am ! # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in 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. *************** target_triplet = @target@ *** 66,74 **** --- 66,76 ---- AR = @AR@ AS = @AS@ CC = @CC@ + CFLAGS = @CFLAGS@ CPP = @CPP@ CXX = @CXX@ CXXCPP = @CXXCPP@ + CXXFLAGS = @CXXFLAGS@ CXXINCLUDES = @CXXINCLUDES@ DLLTOOL = @DLLTOOL@ EXEEXT = @EXEEXT@ *************** RANLIB = @RANLIB@ *** 89,95 **** --- 91,100 ---- STRIP = @STRIP@ THREADLIBS = @THREADLIBS@ VERSION = @VERSION@ + addincludes = @addincludes@ + addlibs = @addlibs@ addobjs = @addobjs@ + addtests = @addtests@ gc_basedir = @gc_basedir@ mkinstalldirs = @mkinstalldirs@ target_all = @target_all@ *************** MULTIDO = true *** 109,125 **** MULTICLEAN = true noinst_LTLIBRARIES = libgcjgc.la libgcjgc_convenience.la GC_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 irix_threads.c \ ! linux_threads.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 \ solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \ ! backgraph.c win32_threads.c ! EXTRA_GC_SOURCES = alpha_mach_dep.s \ ! mips_sgi_mach_dep.S mips_ultrix_mach_dep.s powerpc_macosx_mach_dep.s \ rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \ sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s --- 114,134 ---- MULTICLEAN = true noinst_LTLIBRARIES = libgcjgc.la libgcjgc_convenience.la + @POWERPC_DARWIN_TRUE@asm_libgc_sources = @POWERPC_DARWIN_TRUE@powerpc_darwin_mach_dep.s + @POWERPC_DARWIN_FALSE@asm_libgc_sources = GC_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 aix_irix_threads.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 \ solaris_pthreads.c solaris_threads.c specific.c stubborn.c typd_mlc.c \ ! backgraph.c win32_threads.c \ ! pthread_support.c pthread_stop_world.c darwin_stop_world.c \ ! $(asm_libgc_sources) ! EXTRA_GC_SOURCES = alpha_mach_dep.S \ ! mips_sgi_mach_dep.s mips_ultrix_mach_dep.s powerpc_darwin_mach_dep.s \ rs6000_mach_dep.s sparc_mach_dep.S sparc_netbsd_mach_dep.s \ sparc_sunos4_mach_dep.s ia64_save_regs_in_stack.s *************** DEFS = @DEFS@ -I. -I$(srcdir) *** 213,236 **** CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ ! libgcjgc_la_OBJECTS = allchblk.lo alloc.lo blacklst.lo checksums.lo \ ! dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo headers.lo \ ! irix_threads.lo linux_threads.lo malloc.lo mallocx.lo mark.lo \ ! mark_rts.lo misc.lo new_hblk.lo obj_map.lo os_dep.lo pcr_interface.lo \ ! ptr_chck.lo real_malloc.lo reclaim.lo solaris_pthreads.lo \ ! solaris_threads.lo specific.lo stubborn.lo typd_mlc.lo backgraph.lo \ ! win32_threads.lo libgcjgc_convenience_la_LDFLAGS = ! libgcjgc_convenience_la_OBJECTS = allchblk.lo alloc.lo blacklst.lo \ ! checksums.lo dbg_mlc.lo dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \ ! headers.lo irix_threads.lo linux_threads.lo malloc.lo mallocx.lo \ ! mark.lo mark_rts.lo misc.lo new_hblk.lo obj_map.lo os_dep.lo \ ! pcr_interface.lo ptr_chck.lo real_malloc.lo reclaim.lo \ ! solaris_pthreads.lo solaris_threads.lo specific.lo stubborn.lo \ ! typd_mlc.lo backgraph.lo win32_threads.lo check_PROGRAMS = gctest$(EXEEXT) gctest_DEPENDENCIES = ./libgcjgc.la - CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) DIST_COMMON = ChangeLog Makefile.am Makefile.in acinclude.m4 aclocal.m4 \ --- 222,274 ---- CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ ! @POWERPC_DARWIN_FALSE@libgcjgc_la_OBJECTS = allchblk.lo alloc.lo \ ! @POWERPC_DARWIN_FALSE@blacklst.lo checksums.lo dbg_mlc.lo dyn_load.lo \ ! @POWERPC_DARWIN_FALSE@finalize.lo gc_dlopen.lo gcj_mlc.lo headers.lo \ ! @POWERPC_DARWIN_FALSE@aix_irix_threads.lo malloc.lo mallocx.lo mark.lo \ ! @POWERPC_DARWIN_FALSE@mark_rts.lo misc.lo new_hblk.lo obj_map.lo \ ! @POWERPC_DARWIN_FALSE@os_dep.lo pcr_interface.lo ptr_chck.lo \ ! @POWERPC_DARWIN_FALSE@real_malloc.lo reclaim.lo solaris_pthreads.lo \ ! @POWERPC_DARWIN_FALSE@solaris_threads.lo specific.lo stubborn.lo \ ! @POWERPC_DARWIN_FALSE@typd_mlc.lo backgraph.lo win32_threads.lo \ ! @POWERPC_DARWIN_FALSE@pthread_support.lo pthread_stop_world.lo \ ! @POWERPC_DARWIN_FALSE@darwin_stop_world.lo ! @POWERPC_DARWIN_TRUE@libgcjgc_la_OBJECTS = allchblk.lo alloc.lo \ ! @POWERPC_DARWIN_TRUE@blacklst.lo checksums.lo dbg_mlc.lo dyn_load.lo \ ! @POWERPC_DARWIN_TRUE@finalize.lo gc_dlopen.lo gcj_mlc.lo headers.lo \ ! @POWERPC_DARWIN_TRUE@aix_irix_threads.lo malloc.lo mallocx.lo mark.lo \ ! @POWERPC_DARWIN_TRUE@mark_rts.lo misc.lo new_hblk.lo obj_map.lo \ ! @POWERPC_DARWIN_TRUE@os_dep.lo pcr_interface.lo ptr_chck.lo \ ! @POWERPC_DARWIN_TRUE@real_malloc.lo reclaim.lo solaris_pthreads.lo \ ! @POWERPC_DARWIN_TRUE@solaris_threads.lo specific.lo stubborn.lo \ ! @POWERPC_DARWIN_TRUE@typd_mlc.lo backgraph.lo win32_threads.lo \ ! @POWERPC_DARWIN_TRUE@pthread_support.lo pthread_stop_world.lo \ ! @POWERPC_DARWIN_TRUE@darwin_stop_world.lo powerpc_darwin_mach_dep.lo libgcjgc_convenience_la_LDFLAGS = ! @POWERPC_DARWIN_FALSE@libgcjgc_convenience_la_OBJECTS = allchblk.lo \ ! @POWERPC_DARWIN_FALSE@alloc.lo blacklst.lo checksums.lo dbg_mlc.lo \ ! @POWERPC_DARWIN_FALSE@dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \ ! @POWERPC_DARWIN_FALSE@headers.lo aix_irix_threads.lo malloc.lo \ ! @POWERPC_DARWIN_FALSE@mallocx.lo mark.lo mark_rts.lo misc.lo \ ! @POWERPC_DARWIN_FALSE@new_hblk.lo obj_map.lo os_dep.lo pcr_interface.lo \ ! @POWERPC_DARWIN_FALSE@ptr_chck.lo real_malloc.lo reclaim.lo \ ! @POWERPC_DARWIN_FALSE@solaris_pthreads.lo solaris_threads.lo \ ! @POWERPC_DARWIN_FALSE@specific.lo stubborn.lo typd_mlc.lo backgraph.lo \ ! @POWERPC_DARWIN_FALSE@win32_threads.lo pthread_support.lo \ ! @POWERPC_DARWIN_FALSE@pthread_stop_world.lo darwin_stop_world.lo ! @POWERPC_DARWIN_TRUE@libgcjgc_convenience_la_OBJECTS = allchblk.lo \ ! @POWERPC_DARWIN_TRUE@alloc.lo blacklst.lo checksums.lo dbg_mlc.lo \ ! @POWERPC_DARWIN_TRUE@dyn_load.lo finalize.lo gc_dlopen.lo gcj_mlc.lo \ ! @POWERPC_DARWIN_TRUE@headers.lo aix_irix_threads.lo malloc.lo \ ! @POWERPC_DARWIN_TRUE@mallocx.lo mark.lo mark_rts.lo misc.lo new_hblk.lo \ ! @POWERPC_DARWIN_TRUE@obj_map.lo os_dep.lo pcr_interface.lo ptr_chck.lo \ ! @POWERPC_DARWIN_TRUE@real_malloc.lo reclaim.lo solaris_pthreads.lo \ ! @POWERPC_DARWIN_TRUE@solaris_threads.lo specific.lo stubborn.lo \ ! @POWERPC_DARWIN_TRUE@typd_mlc.lo backgraph.lo win32_threads.lo \ ! @POWERPC_DARWIN_TRUE@pthread_support.lo pthread_stop_world.lo \ ! @POWERPC_DARWIN_TRUE@darwin_stop_world.lo powerpc_darwin_mach_dep.lo check_PROGRAMS = gctest$(EXEEXT) gctest_DEPENDENCIES = ./libgcjgc.la COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) DIST_COMMON = ChangeLog Makefile.am Makefile.in acinclude.m4 aclocal.m4 \ *************** maintainer-clean-recursive: *** 368,374 **** dot_seen=no; \ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ rev="$$subdir $$rev"; \ ! test "$$subdir" = "." && dot_seen=yes; \ done; \ test "$$dot_seen" = "no" && rev=". $$rev"; \ target=`echo $@ | sed s/-recursive//`; \ --- 406,412 ---- dot_seen=no; \ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ rev="$$subdir $$rev"; \ ! test "$$subdir" != "." || dot_seen=yes; \ done; \ test "$$dot_seen" = "no" && rev=". $$rev"; \ target=`echo $@ | sed s/-recursive//`; \ *************** mostlyclean distclean maintainer-clean *** 598,604 **** test.o: tests/test.c $(COMPILE) -c $(srcdir)/tests/test.c $(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \ ! include/private/gc_hdrs.h include/gc.h include/gc_gcj.h include/gc_mark.h .s.lo: $(LTCOMPILE) -Wp,-P -x assembler-with-cpp -c $< --- 636,644 ---- test.o: tests/test.c $(COMPILE) -c $(srcdir)/tests/test.c $(all_objs) : include/private/gcconfig.h include/private/gc_priv.h \ ! include/private/gc_hdrs.h include/gc.h include/gc_gcj.h \ ! include/gc_pthread_redirects.h include/gc_config_macros.h \ ! include/gc_mark.h @addincludes@ .s.lo: $(LTCOMPILE) -Wp,-P -x assembler-with-cpp -c $< diff -Nrc3pad gcc-3.3.3/boehm-gc/malloc.c gcc-3.4.0/boehm-gc/malloc.c *** gcc-3.3.3/boehm-gc/malloc.c 2002-02-12 04:37:53.000000000 +0000 --- gcc-3.4.0/boehm-gc/malloc.c 2004-01-07 21:47:35.000000000 +0000 *************** register int k; *** 182,187 **** --- 182,188 ---- ptr_t result; DCL_LOCK_STATE; + if (GC_have_errors) GC_print_all_errors(); GC_INVOKE_FINALIZERS(); if (SMALL_OBJ(lb)) { DISABLE_SIGNALS(); *************** register int k; *** 216,222 **** GC_words_allocd += lw; UNLOCK(); ENABLE_SIGNALS(); ! if (init & !GC_debugging_started && 0 != result) { BZERO(result, n_blocks * HBLKSIZE); } } --- 217,223 ---- GC_words_allocd += lw; UNLOCK(); ENABLE_SIGNALS(); ! if (init && !GC_debugging_started && 0 != result) { BZERO(result, n_blocks * HBLKSIZE); } } *************** DCL_LOCK_STATE; *** 294,299 **** --- 295,305 ---- return(GENERAL_MALLOC((word)lb, NORMAL)); } /* See above comment on signals. */ + 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_words_allocd += lw; *************** DCL_LOCK_STATE; *** 338,343 **** --- 344,350 ---- return((GC_PTR)REDIRECT_MALLOC(n*lb)); } + #ifndef strdup # include # ifdef __STDC__ char *strdup(const char *s) *************** DCL_LOCK_STATE; *** 346,356 **** char *s; # endif { ! size_t len = strlen + 1; char * result = ((char *)REDIRECT_MALLOC(len+1)); BCOPY(s, result, len+1); return result; } # endif /* REDIRECT_MALLOC */ /* Explicitly deallocate an object p. */ --- 353,368 ---- char *s; # endif { ! size_t len = strlen(s) + 1; char * result = ((char *)REDIRECT_MALLOC(len+1)); BCOPY(s, result, len+1); 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. */ + # endif /* REDIRECT_MALLOC */ /* Explicitly deallocate an object p. */ *************** DCL_LOCK_STATE; *** 373,378 **** --- 385,391 ---- /* Required by ANSI. It's not my fault ... */ h = HBLKPTR(p); hhdr = HDR(h); + GC_ASSERT(GC_base(p) == p); # if defined(REDIRECT_MALLOC) && \ (defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \ || defined(__MINGW32__)) /* Should this be MSWIN32 in general? */ *************** void GC_free_inner(GC_PTR p) *** 454,460 **** } #endif /* THREADS */ ! # ifdef REDIRECT_MALLOC # ifdef __STDC__ void free(GC_PTR p) # else --- 467,476 ---- } #endif /* THREADS */ ! # if defined(REDIRECT_MALLOC) && !defined(REDIRECT_FREE) ! # define REDIRECT_FREE GC_free ! # endif ! # ifdef REDIRECT_FREE # ifdef __STDC__ void free(GC_PTR p) # else *************** void GC_free_inner(GC_PTR p) *** 463,469 **** # endif { # ifndef IGNORE_FREE ! GC_free(p); # endif } # endif /* REDIRECT_MALLOC */ --- 479,485 ---- # endif { # ifndef IGNORE_FREE ! REDIRECT_FREE(p); # endif } # endif /* REDIRECT_MALLOC */ diff -Nrc3pad gcc-3.3.3/boehm-gc/mallocx.c gcc-3.4.0/boehm-gc/mallocx.c *** gcc-3.3.3/boehm-gc/mallocx.c 2001-08-18 01:04:43.000000000 +0000 --- gcc-3.4.0/boehm-gc/mallocx.c 2004-01-07 21:47:35.000000000 +0000 *************** int obj_kind; *** 142,148 **** } } ! # if defined(REDIRECT_MALLOC) || defined(REDIRECT_REALLOC) # ifdef __STDC__ GC_PTR realloc(GC_PTR p, size_t lb) # else --- 142,152 ---- } } ! # if defined(REDIRECT_MALLOC) && !defined(REDIRECT_REALLOC) ! # define REDIRECT_REALLOC GC_realloc ! # endif ! ! # ifdef REDIRECT_REALLOC # ifdef __STDC__ GC_PTR realloc(GC_PTR p, size_t lb) # else *************** int obj_kind; *** 151,163 **** size_t lb; # endif { ! # ifdef REDIRECT_REALLOC ! return(REDIRECT_REALLOC(p, lb)); ! # else ! return(GC_realloc(p, lb)); ! # endif } ! # endif /* REDIRECT_MALLOC */ /* The same thing, except caller does not hold allocation lock. */ --- 155,163 ---- size_t lb; # endif { ! return(REDIRECT_REALLOC(p, lb)); } ! # endif /* REDIRECT_REALLOC */ /* The same thing, except caller does not hold allocation lock. */ *************** register int k; *** 177,182 **** --- 177,183 ---- lw = ROUNDED_UP_WORDS(lb); n_blocks = OBJ_SZ_TO_BLOCKS(lw); init = GC_obj_kinds[k].ok_init; + if (GC_have_errors) GC_print_all_errors(); GC_INVOKE_FINALIZERS(); DISABLE_SIGNALS(); LOCK(); *************** register int k; *** 201,207 **** if (0 == result) { return((*GC_oom_fn)(lb)); } else { ! if (init & !GC_debugging_started) { BZERO(result, n_blocks * HBLKSIZE); } return(result); --- 202,208 ---- if (0 == result) { return((*GC_oom_fn)(lb)); } else { ! if (init && !GC_debugging_started) { BZERO(result, n_blocks * HBLKSIZE); } return(result); *************** register struct obj_kind * kind = GC_obj *** 286,291 **** --- 287,293 ---- register ptr_t op; DCL_LOCK_STATE; + if (GC_have_errors) GC_print_all_errors(); GC_INVOKE_FINALIZERS(); DISABLE_SIGNALS(); LOCK(); *************** DCL_LOCK_STATE; *** 354,359 **** --- 356,362 ---- return; } lw = ALIGNED_WORDS(lb); + if (GC_have_errors) GC_print_all_errors(); GC_INVOKE_FINALIZERS(); DISABLE_SIGNALS(); LOCK(); *************** DCL_LOCK_STATE; *** 375,380 **** --- 378,384 ---- while ((hbp = *rlh) != 0) { hhdr = HDR(hbp); *rlh = hhdr -> hb_next; + hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no; # ifdef PARALLEL_MARK { signed_word my_words_allocd_tmp = GC_words_allocd_tmp; *************** DCL_LOCK_STATE; *** 575,580 **** --- 579,622 ---- } } + #ifdef __STDC__ + /* Not well tested nor integrated. */ + /* Debug version is tricky and currently missing. */ + #include + + GC_PTR GC_memalign(size_t align, size_t lb) + { + size_t new_lb; + size_t offset; + ptr_t result; + + # ifdef ALIGN_DOUBLE + if (align <= WORDS_TO_BYTES(2) && lb > align) return GC_malloc(lb); + # endif + if (align <= WORDS_TO_BYTES(1)) return GC_malloc(lb); + if (align >= HBLKSIZE/2 || lb >= HBLKSIZE/2) { + if (align > HBLKSIZE) return GC_oom_fn(LONG_MAX-1024) /* Fail */; + return GC_malloc(lb <= HBLKSIZE? HBLKSIZE : lb); + /* Will be HBLKSIZE aligned. */ + } + /* 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; + result = GC_malloc(new_lb); + offset = (word)result % align; + if (offset != 0) { + offset = align - offset; + if (!GC_all_interior_pointers) { + if (offset >= VALID_OFFSET_SZ) return GC_malloc(HBLKSIZE); + GC_register_displacement(offset); + } + } + result = (GC_PTR) ((ptr_t)result + offset); + GC_ASSERT((word)result % align == 0); + return result; + } + #endif + # ifdef ATOMIC_UNCOLLECTABLE /* Allocate lb bytes of pointerfree, untraced, uncollectable data */ /* This is normally roughly equivalent to the system malloc. */ diff -Nrc3pad gcc-3.3.3/boehm-gc/mark.c gcc-3.4.0/boehm-gc/mark.c *** gcc-3.3.3/boehm-gc/mark.c 2002-03-29 22:52:12.000000000 +0000 --- gcc-3.4.0/boehm-gc/mark.c 2003-07-28 04:18:20.000000000 +0000 *************** *** 19,24 **** --- 19,28 ---- # include # include "private/gc_pmark.h" + #if defined(MSWIN32) && defined(__GNUC__) + # include + #endif + /* We put this here to minimize the risk of inlining. */ /*VARARGS*/ #ifdef __WATCOMC__ *************** static void alloc_mark_stack(); *** 261,280 **** /* remains valid until all marking is complete. */ /* A zero value indicates that it's OK to miss some */ /* register values. */ ! GC_bool GC_mark_some(cold_gc_frame) ! ptr_t cold_gc_frame; { - #if defined(MSWIN32) && !defined(__GNUC__) - /* Windows 98 appears to asynchronously create and remove writable */ - /* memory mappings, for reasons we haven't yet understood. Since */ - /* we look for writable regions to determine the root set, we may */ - /* try to mark from an address range that disappeared since we */ - /* started the collection. Thus we have to recover from faults here. */ - /* This code does not appear to be necessary for Windows 95/NT/2000. */ - /* Note that this code should never generate an incremental GC write */ - /* fault. */ - __try { - #endif /* defined(MSWIN32) && !defined(__GNUC__) */ switch(GC_mark_state) { case MS_NONE: return(FALSE); --- 265,284 ---- /* remains valid until all marking is complete. */ /* A zero value indicates that it's OK to miss some */ /* register values. */ ! /* We hold the allocation lock. In the case of */ ! /* incremental collection, the world may not be stopped.*/ ! #ifdef MSWIN32 ! /* For win32, this is called after we establish a structured */ ! /* exception handler, in case Windows unmaps one of our root */ ! /* segments. See below. In either case, we acquire the */ ! /* allocator lock long before we get here. */ ! GC_bool GC_mark_some_inner(cold_gc_frame) ! ptr_t cold_gc_frame; ! #else ! GC_bool GC_mark_some(cold_gc_frame) ! ptr_t cold_gc_frame; ! #endif { switch(GC_mark_state) { case MS_NONE: return(FALSE); *************** ptr_t cold_gc_frame; *** 395,417 **** ABORT("GC_mark_some: bad state"); return(FALSE); } ! #if defined(MSWIN32) && !defined(__GNUC__) ! } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? ! EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { ! # ifdef CONDPRINT ! if (GC_print_stats) { ! GC_printf0("Caught ACCESS_VIOLATION in marker. " ! "Memory mapping disappeared.\n"); } ! # endif /* CONDPRINT */ ! /* We have bad roots on the stack. Discard mark stack. */ ! /* Rescan from marked objects. Redetermine roots. */ ! GC_invalidate_mark_state(); ! scan_ptr = 0; ! return FALSE; } ! #endif /* defined(MSWIN32) && !defined(__GNUC__) */ ! } GC_bool GC_mark_stack_empty() --- 399,528 ---- ABORT("GC_mark_some: bad state"); return(FALSE); } ! } ! ! ! #ifdef MSWIN32 ! ! # ifdef __GNUC__ ! ! typedef struct { ! EXCEPTION_REGISTRATION ex_reg; ! void *alt_path; ! } ext_ex_regn; ! ! ! static EXCEPTION_DISPOSITION mark_ex_handler( ! struct _EXCEPTION_RECORD *ex_rec, ! void *est_frame, ! struct _CONTEXT *context, ! void *disp_ctxt) ! { ! if (ex_rec->ExceptionCode == STATUS_ACCESS_VIOLATION) { ! ext_ex_regn *xer = (ext_ex_regn *)est_frame; ! ! /* Unwind from the inner function assuming the standard */ ! /* function prologue. */ ! /* Assumes code has not been compiled with */ ! /* -fomit-frame-pointer. */ ! context->Esp = context->Ebp; ! context->Ebp = *((DWORD *)context->Esp); ! context->Esp = context->Esp - 8; ! ! /* Resume execution at the "real" handler within the */ ! /* wrapper function. */ ! context->Eip = (DWORD )(xer->alt_path); ! ! return ExceptionContinueExecution; ! ! } else { ! return ExceptionContinueSearch; ! } ! } ! # endif /* __GNUC__ */ ! ! ! GC_bool GC_mark_some(cold_gc_frame) ! ptr_t cold_gc_frame; ! { ! GC_bool ret_val; ! ! # ifndef __GNUC__ ! /* Windows 98 appears to asynchronously create and remove */ ! /* writable memory mappings, for reasons we haven't yet */ ! /* understood. Since we look for writable regions to */ ! /* determine the root set, we may try to mark from an */ ! /* address range that disappeared since we started the */ ! /* collection. Thus we have to recover from faults here. */ ! /* This code does not appear to be necessary for Windows */ ! /* 95/NT/2000. Note that this code should never generate */ ! /* an incremental GC write fault. */ ! ! __try { ! ! # else /* __GNUC__ */ ! ! /* Manually install an exception handler since GCC does */ ! /* not yet support Structured Exception Handling (SEH) on */ ! /* Win32. */ ! ! ext_ex_regn er; ! ! er.alt_path = &&handle_ex; ! 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)); ! ! # endif /* __GNUC__ */ ! ! ret_val = GC_mark_some_inner(cold_gc_frame); ! ! # ifndef __GNUC__ ! ! } __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? ! EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { ! ! # else /* __GNUC__ */ ! ! /* Prevent GCC from considering the following code unreachable */ ! /* and thus eliminating it. */ ! if (er.alt_path != 0) ! goto rm_handler; ! ! handle_ex: ! /* Execution resumes from here on an access violation. */ ! ! # endif /* __GNUC__ */ ! ! # ifdef CONDPRINT ! if (GC_print_stats) { ! GC_printf0("Caught ACCESS_VIOLATION in marker. " ! "Memory mapping disappeared.\n"); ! } ! # endif /* CONDPRINT */ ! ! /* We have bad roots on the stack. Discard mark stack. */ ! /* Rescan from marked objects. Redetermine roots. */ ! GC_invalidate_mark_state(); ! scan_ptr = 0; ! ! ret_val = FALSE; ! ! # ifndef __GNUC__ ! } ! ! # else /* __GNUC__ */ ! ! rm_handler: ! /* Uninstall the exception handler */ ! asm volatile ("mov %0, %%fs:0" : : "r" (er.ex_reg.prev)); ! ! # endif /* __GNUC__ */ ! ! return ret_val; } ! #endif /* MSWIN32 */ GC_bool GC_mark_stack_empty() *************** GC_bool GC_mark_stack_empty() *** 434,446 **** /* for the large object. */ /* - just return current if it does not point to a large object. */ /*ARGSUSED*/ ! # ifdef PRINT_BLACK_LIST ! ptr_t GC_find_start(current, hhdr, new_hdr_p, source) ! ptr_t source; ! # else ! ptr_t GC_find_start(current, hhdr, new_hdr_p) ! # define source 0 ! # endif register ptr_t current; register hdr *hhdr, **new_hdr_p; { --- 545,551 ---- /* for the large object. */ /* - just return current if it does not point to a large object. */ /*ARGSUSED*/ ! ptr_t GC_find_start(current, hhdr, new_hdr_p) register ptr_t current; register hdr *hhdr, **new_hdr_p; { *************** register hdr *hhdr, **new_hdr_p; *** 468,474 **** } else { return(current); } - # undef source } void GC_invalidate_mark_state() --- 573,578 ---- *************** mse * mark_stack_limit; *** 546,553 **** /* Large length. */ /* Process part of the range to avoid pushing too much on the */ /* stack. */ ! GC_ASSERT(descr < GC_greatest_plausible_heap_addr ! - GC_least_plausible_heap_addr); # ifdef PARALLEL_MARK # define SHARE_BYTES 2048 if (descr > SHARE_BYTES && GC_parallel --- 650,657 ---- /* 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 PARALLEL_MARK # define SHARE_BYTES 2048 if (descr > SHARE_BYTES && GC_parallel *************** mse * mark_stack_limit; *** 578,583 **** --- 682,688 ---- while (descr != 0) { if ((signed_word)descr < 0) { current = *current_p; + FIXUP_POINTER(current); if ((ptr_t)current >= least_ha && (ptr_t)current < greatest_ha) { PREFETCH(current); HC_PUSH_CONTENTS((ptr_t)current, mark_stack_top, *************** mse * mark_stack_limit; *** 652,657 **** --- 757,763 ---- PREFETCH((ptr_t)limit - PREF_DIST*CACHE_LINE_SIZE); GC_ASSERT(limit >= current_p); deferred = *limit; + FIXUP_POINTER(deferred); limit = (word *)((char *)limit - ALIGNMENT); if ((ptr_t)deferred >= least_ha && (ptr_t)deferred < greatest_ha) { PREFETCH(deferred); *************** mse * mark_stack_limit; *** 661,666 **** --- 767,773 ---- /* Unroll once, so we don't do too many of the prefetches */ /* based on limit. */ deferred = *limit; + FIXUP_POINTER(deferred); limit = (word *)((char *)limit - ALIGNMENT); if ((ptr_t)deferred >= least_ha && (ptr_t)deferred < greatest_ha) { PREFETCH(deferred); *************** mse * mark_stack_limit; *** 675,680 **** --- 782,788 ---- /* Since HC_PUSH_CONTENTS expands to a lot of code, */ /* we don't. */ current = *current_p; + FIXUP_POINTER(current); PREFETCH((ptr_t)current_p + PREF_DIST*CACHE_LINE_SIZE); if ((ptr_t)current >= least_ha && (ptr_t)current < greatest_ha) { /* Prefetch the contents of the object we just pushed. It's */ *************** mse * GC_steal_mark_stack(mse * low, mse *** 726,747 **** mse *top = local - 1; unsigned i = 0; GC_ASSERT(high >= low-1 && high - low + 1 <= GC_mark_stack_size); for (p = low; p <= high && i <= max; ++p) { word descr = *(volatile word *) &(p -> mse_descr); if (descr != 0) { *(volatile word *) &(p -> mse_descr) = 0; ++top; top -> mse_descr = descr; top -> mse_start = p -> mse_start; GC_ASSERT( top -> mse_descr & GC_DS_TAGS != GC_DS_LENGTH || top -> mse_descr < GC_greatest_plausible_heap_addr - GC_least_plausible_heap_addr); - /* There is no synchronization here. We assume that at */ - /* least one thread will see the original descriptor. */ - /* Otherwise we need a barrier. */ - /* More than one thread may get this entry, but that's only */ - /* a minor performance problem. */ /* If this is a big object, count it as */ /* size/256 + 1 objects. */ ++i; --- 834,866 ---- mse *top = local - 1; unsigned i = 0; + /* Make sure that prior writes to the mark stack are visible. */ + /* On some architectures, the fact that the reads are */ + /* volatile should suffice. */ + # if !defined(IA64) && !defined(HP_PA) && !defined(I386) + GC_memory_barrier(); + # endif GC_ASSERT(high >= low-1 && high - low + 1 <= GC_mark_stack_size); for (p = low; p <= high && i <= max; ++p) { word descr = *(volatile word *) &(p -> mse_descr); + /* In the IA64 memory model, the following volatile store is */ + /* ordered after this read of descr. Thus a thread must read */ + /* the original nonzero value. HP_PA appears to be similar, */ + /* and if I'm reading the P4 spec correctly, X86 is probably */ + /* also OK. In some other cases we need a barrier. */ + # if !defined(IA64) && !defined(HP_PA) && !defined(I386) + GC_memory_barrier(); + # endif if (descr != 0) { *(volatile word *) &(p -> mse_descr) = 0; + /* More than one thread may get this entry, but that's only */ + /* a minor performance problem. */ ++top; top -> mse_descr = descr; top -> mse_start = p -> mse_start; GC_ASSERT( top -> mse_descr & GC_DS_TAGS != GC_DS_LENGTH || top -> mse_descr < GC_greatest_plausible_heap_addr - GC_least_plausible_heap_addr); /* If this is a big object, count it as */ /* size/256 + 1 objects. */ ++i; *************** void GC_return_mark_stack(mse * low, mse *** 778,784 **** BCOPY(low, my_start, stack_size * sizeof(mse)); GC_ASSERT(GC_mark_stack_top = my_top); # if !defined(IA64) && !defined(HP_PA) ! GC_memory_write_barrier(); # endif /* On IA64, the volatile write acts as a release barrier. */ GC_mark_stack_top = my_top + stack_size; --- 897,903 ---- BCOPY(low, my_start, stack_size * sizeof(mse)); GC_ASSERT(GC_mark_stack_top = my_top); # if !defined(IA64) && !defined(HP_PA) ! GC_memory_barrier(); # endif /* On IA64, the volatile write acts as a release barrier. */ GC_mark_stack_top = my_top + stack_size; *************** ptr_t top; *** 1342,1349 **** # define GC_least_plausible_heap_addr least_ha if (top == 0) return; ! /* check all pointers in range and put in push if they appear */ ! /* to be valid. */ lim = t - 1 /* longword */; for (p = b; p <= lim; p = (word *)(((char *)p) + ALIGNMENT)) { q = *p; --- 1461,1468 ---- # define GC_least_plausible_heap_addr least_ha if (top == 0) return; ! /* check all pointers in range and push if they appear */ ! /* to be valid. */ lim = t - 1 /* longword */; for (p = b; p <= lim; p = (word *)(((char *)p) + ALIGNMENT)) { q = *p; *************** ptr_t bottom; *** 1366,1372 **** ptr_t top; ptr_t cold_gc_frame; { ! if (GC_all_interior_pointers) { # define EAGER_BYTES 1024 /* Push the hot end of the stack eagerly, so that register values */ /* saved inside GC frames are marked before they disappear. */ --- 1485,1491 ---- ptr_t top; ptr_t cold_gc_frame; { ! if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) { # define EAGER_BYTES 1024 /* Push the hot end of the stack eagerly, so that register values */ /* saved inside GC frames are marked before they disappear. */ *************** ptr_t cold_gc_frame; *** 1375,1380 **** --- 1494,1500 ---- GC_push_all_stack(bottom, top); return; } + GC_ASSERT(bottom <= cold_gc_frame && cold_gc_frame <= top); # ifdef STACK_GROWS_DOWN GC_push_all(cold_gc_frame - sizeof(ptr_t), top); GC_push_all_eager(bottom, cold_gc_frame); *************** void GC_push_all_stack(bottom, top) *** 1395,1401 **** ptr_t bottom; ptr_t top; { ! if (GC_all_interior_pointers) { GC_push_all(bottom, top); } else { GC_push_all_eager(bottom, top); --- 1515,1521 ---- ptr_t bottom; ptr_t top; { ! if (!NEED_FIXUP_POINTER && GC_all_interior_pointers) { GC_push_all(bottom, top); } else { GC_push_all_eager(bottom, top); diff -Nrc3pad gcc-3.3.3/boehm-gc/mark_rts.c gcc-3.4.0/boehm-gc/mark_rts.c *** gcc-3.3.3/boehm-gc/mark_rts.c 2003-03-04 06:38:29.000000000 +0000 --- gcc-3.4.0/boehm-gc/mark_rts.c 2003-07-28 04:18:20.000000000 +0000 *************** void GC_clear_roots GC_PROTO((void)) *** 275,308 **** } /* Internal use only; lock held. */ void GC_remove_tmp_roots() { register int i; for (i = 0; i < n_root_sets; ) { if (GC_static_roots[i].r_tmp) { ! GC_root_size -= ! (GC_static_roots[i].r_end - GC_static_roots[i].r_start); ! GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start; ! GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end; ! GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp; ! n_root_sets--; } else { i++; - } } - # if !defined(MSWIN32) && !defined(MSWINCE) - { - register int i; - - for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0; - for (i = 0; i < n_root_sets; i++) - add_roots_to_index(GC_static_roots + i); } ! # endif } #if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION) /* Workaround for the OS mapping and unmapping behind our back: */ /* Is the address p in one of the temporary static root sections? */ --- 275,347 ---- } /* Internal use only; lock held. */ + static void GC_remove_root_at_pos(i) + int i; + { + GC_root_size -= (GC_static_roots[i].r_end - GC_static_roots[i].r_start); + GC_static_roots[i].r_start = GC_static_roots[n_root_sets-1].r_start; + GC_static_roots[i].r_end = GC_static_roots[n_root_sets-1].r_end; + GC_static_roots[i].r_tmp = GC_static_roots[n_root_sets-1].r_tmp; + n_root_sets--; + } + + #if !defined(MSWIN32) && !defined(MSWINCE) + static void GC_rebuild_root_index() + { + register int i; + + for (i = 0; i < RT_SIZE; i++) GC_root_index[i] = 0; + for (i = 0; i < n_root_sets; i++) + add_roots_to_index(GC_static_roots + i); + } + #endif + + /* Internal use only; lock held. */ void GC_remove_tmp_roots() { register int i; for (i = 0; i < n_root_sets; ) { if (GC_static_roots[i].r_tmp) { ! GC_remove_root_at_pos(i); } else { i++; } } ! #if !defined(MSWIN32) && !defined(MSWINCE) ! GC_rebuild_root_index(); ! #endif ! } ! ! #if !defined(MSWIN32) && !defined(MSWINCE) ! void GC_remove_roots(b, e) ! char * b; char * e; ! { ! DCL_LOCK_STATE; + DISABLE_SIGNALS(); + LOCK(); + GC_remove_roots_inner(b, e); + UNLOCK(); + ENABLE_SIGNALS(); } + /* Should only be called when the lock is held */ + void GC_remove_roots_inner(b,e) + char * b; char * e; + { + int i; + for (i = 0; i < n_root_sets; ) { + if (GC_static_roots[i].r_start >= (ptr_t)b && GC_static_roots[i].r_end <= (ptr_t)e) { + GC_remove_root_at_pos(i); + } else { + i++; + } + } + GC_rebuild_root_index(); + } + #endif /* !defined(MSWIN32) && !defined(MSWINCE) */ + #if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION) /* Workaround for the OS mapping and unmapping behind our back: */ /* Is the address p in one of the temporary static root sections? */ *************** ptr_t cold_gc_frame; *** 573,580 **** /* Mark thread local free lists, even if their mark */ /* descriptor excludes the link field. */ # ifdef THREAD_LOCAL_ALLOC ! GC_mark_thread_local_free_lists(); # endif /* --- 612,622 ---- /* Mark thread local free lists, even if their mark */ /* descriptor excludes the link field. */ + /* If the world is not stopped, this is unsafe. It is */ + /* also unnecessary, since we will do this again with the */ + /* world stopped. */ # ifdef THREAD_LOCAL_ALLOC ! if (GC_world_stopped) GC_mark_thread_local_free_lists(); # endif /* diff -Nrc3pad gcc-3.3.3/boehm-gc/mips_sgi_mach_dep.s gcc-3.4.0/boehm-gc/mips_sgi_mach_dep.s *** gcc-3.3.3/boehm-gc/mips_sgi_mach_dep.s 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/mips_sgi_mach_dep.s 2003-10-20 18:37:01.000000000 +0000 *************** *** 0 **** --- 1,46 ---- + #include + #include + /* This file must be preprocessed. But the SGI assembler always does */ + /* that. Furthermore, a generic preprocessor won't do, since some of */ + /* the SGI-supplied include files rely on behavior of the MIPS */ + /* assembler. Hence we treat and name this file as though it required */ + /* no preprocessing. */ + + # define call_push(x) move $4,x; jal GC_push_one + + .option pic2 + .text + /* Mark from machine registers that are saved by C compiler */ + # define FRAMESZ 32 + # define RAOFF FRAMESZ-SZREG + # define GPOFF FRAMESZ-(2*SZREG) + NESTED(GC_push_regs, FRAMESZ, ra) + .mask 0x80000000,-SZREG # inform debugger of saved ra loc + move t0,gp + SETUP_GPX(t8) + PTR_SUBU sp,FRAMESZ + # ifdef SETUP_GP64 + SETUP_GP64(GPOFF, GC_push_regs) + # endif + SAVE_GP(GPOFF) + REG_S ra,RAOFF(sp) + # if (_MIPS_SIM == _ABIO32) + call_push($2) + call_push($3) + # endif + call_push($16) + call_push($17) + call_push($18) + call_push($19) + call_push($20) + call_push($21) + call_push($22) + call_push($23) + call_push($30) + REG_L ra,RAOFF(sp) + # ifdef RESTORE_GP64 + RESTORE_GP64 + # endif + PTR_ADDU sp,FRAMESZ + j ra + .end GC_push_regs diff -Nrc3pad gcc-3.3.3/boehm-gc/mips_sgi_mach_dep.S gcc-3.4.0/boehm-gc/mips_sgi_mach_dep.S *** gcc-3.3.3/boehm-gc/mips_sgi_mach_dep.S 2002-02-13 05:38:39.000000000 +0000 --- gcc-3.4.0/boehm-gc/mips_sgi_mach_dep.S 1970-01-01 00:00:00.000000000 +0000 *************** *** 1,41 **** - #include - #include - - # define call_push(x) move $4,x; jal GC_push_one - - .option pic2 - .text - /* Mark from machine registers that are saved by C compiler */ - # define FRAMESZ 32 - # define RAOFF FRAMESZ-SZREG - # define GPOFF FRAMESZ-(2*SZREG) - NESTED(GC_push_regs, FRAMESZ, ra) - .mask 0x80000000,-SZREG # inform debugger of saved ra loc - move t0,gp - SETUP_GPX(t8) - PTR_SUBU sp,FRAMESZ - # ifdef SETUP_GP64 - SETUP_GP64(GPOFF, GC_push_regs) - # endif - SAVE_GP(GPOFF) - REG_S ra,RAOFF(sp) - # if (_MIPS_SIM == _MIPS_SIM_ABI32) - call_push($2) - call_push($3) - # endif - call_push($16) - call_push($17) - call_push($18) - call_push($19) - call_push($20) - call_push($21) - call_push($22) - call_push($23) - call_push($30) - REG_L ra,RAOFF(sp) - # ifdef RESTORE_GP64 - RESTORE_GP64 - # endif - PTR_ADDU sp,FRAMESZ - j ra - .end GC_push_regs --- 0 ---- diff -Nrc3pad gcc-3.3.3/boehm-gc/misc.c gcc-3.4.0/boehm-gc/misc.c *** gcc-3.3.3/boehm-gc/misc.c 2003-03-04 06:38:30.000000000 +0000 --- gcc-3.4.0/boehm-gc/misc.c 2003-10-03 18:43:06.000000000 +0000 *************** *** 46,53 **** # ifdef GC_SOLARIS_THREADS mutex_t GC_allocate_ml; /* Implicitly initialized. */ # else ! # ifdef GC_WIN32_THREADS ! # if !defined(GC_NOT_DLL) && (defined(_DLL) || defined(GC_DLL)) __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml; # else CRITICAL_SECTION GC_allocate_ml; --- 46,55 ---- # ifdef GC_SOLARIS_THREADS mutex_t GC_allocate_ml; /* Implicitly initialized. */ # else ! # if defined(GC_WIN32_THREADS) ! # if defined(GC_PTHREADS) ! pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER; ! # elif defined(GC_DLL) __declspec(dllexport) CRITICAL_SECTION GC_allocate_ml; # else CRITICAL_SECTION GC_allocate_ml; *************** *** 75,82 **** #undef STACKBASE #endif ! /* Dont unnecessarily call GC_register_main_static_data() in case */ ! /* dyn_load.c isn't linked in. */ #ifdef DYNAMIC_LOADING # define GC_REGISTER_MAIN_STATIC_DATA() GC_register_main_static_data() #else --- 77,84 ---- #undef STACKBASE #endif ! /* Dont unnecessarily call GC_register_main_static_data() in case */ ! /* dyn_load.c isn't linked in. */ #ifdef DYNAMIC_LOADING # define GC_REGISTER_MAIN_STATIC_DATA() GC_register_main_static_data() #else *************** GC_bool GC_debugging_started = FALSE; *** 90,95 **** --- 92,98 ---- /* defined here so we don't have to load debug_malloc.o */ void (*GC_check_heap) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0; + void (*GC_print_all_smashed) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0; void (*GC_start_call_back) GC_PROTO((void)) = (void (*) GC_PROTO((void)))0; *************** GC_bool GC_print_stats = 0; *** 109,114 **** --- 112,121 ---- GC_bool GC_print_back_height = 0; + #ifndef NO_DEBUGGING + GC_bool GC_dump_regularly = 0; /* Generate regular debugging dumps. */ + #endif + #ifdef FIND_LEAK int GC_find_leak = 1; #else *************** GC_PTR (*GC_oom_fn) GC_PROTO((size_t byt *** 137,142 **** --- 144,156 ---- extern signed_word GC_mem_found; + void * GC_project2(arg1, arg2) + void *arg1; + void *arg2; + { + return arg2; + } + # ifdef MERGE_SIZES /* Set things up so that GC_size_map[i] >= words(i), */ /* but not too much bigger */ *************** void GC_init() *** 455,461 **** DISABLE_SIGNALS(); ! #ifdef MSWIN32 if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml); #endif /* MSWIN32 */ --- 469,475 ---- DISABLE_SIGNALS(); ! #if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) if (!GC_is_initialized) InitializeCriticalSection(&GC_allocate_ml); #endif /* MSWIN32 */ *************** void GC_init() *** 473,478 **** --- 487,501 ---- GC_init_parallel(); } # endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */ + + # if defined(DYNAMIC_LOADING) && defined(DARWIN) + { + /* This must be called WITHOUT the allocation lock held + and before any threads are created */ + extern void GC_init_dyld(); + GC_init_dyld(); + } + # endif } #if defined(MSWIN32) || defined(MSWINCE) *************** void GC_init() *** 485,490 **** --- 508,529 ---- extern void GC_setpagesize(); + + #ifdef MSWIN32 + extern GC_bool GC_no_win32_dlls; + #else + # define GC_no_win32_dlls FALSE + #endif + + void GC_exit_check GC_PROTO((void)) + { + GC_gcollect(); + } + + #ifdef SEARCH_FOR_DATA_START + extern void GC_init_linux_data_start GC_PROTO((void)); + #endif + #ifdef UNIX_LIKE extern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int))); *************** int sig; *** 495,506 **** GC_err_printf1("Caught signal %d: looping in handler\n", sig); for(;;); } - #endif ! #ifdef MSWIN32 ! extern GC_bool GC_no_win32_dlls; ! #else ! # define GC_no_win32_dlls FALSE #endif void GC_init_inner() --- 534,556 ---- GC_err_printf1("Caught signal %d: looping in handler\n", sig); for(;;); } ! static GC_bool installed_looping_handler = FALSE; ! ! void maybe_install_looping_handler() ! { ! /* Install looping handler before the write fault handler, so we */ ! /* handle write faults correctly. */ ! if (!installed_looping_handler && 0 != GETENV("GC_LOOP_ON_ABORT")) { ! GC_set_and_save_fault_handler(looping_handler); ! installed_looping_handler = TRUE; ! } ! } ! ! #else /* !UNIX_LIKE */ ! ! # define maybe_install_looping_handler() ! #endif void GC_init_inner() *************** void GC_init_inner() *** 515,528 **** GC_print_stats = 1; # endif # if defined(MSWIN32) || defined(MSWINCE) ! InitializeCriticalSection(&GC_write_cs); # endif - if (0 != GETENV("GC_PRINT_STATS")) { GC_print_stats = 1; } if (0 != GETENV("GC_FIND_LEAK")) { GC_find_leak = 1; } if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) { GC_all_interior_pointers = 1; --- 565,585 ---- GC_print_stats = 1; # endif # if defined(MSWIN32) || defined(MSWINCE) ! InitializeCriticalSection(&GC_write_cs); # endif if (0 != GETENV("GC_PRINT_STATS")) { GC_print_stats = 1; } + # ifndef NO_DEBUGGING + if (0 != GETENV("GC_DUMP_REGULARLY")) { + GC_dump_regularly = 1; + } + # endif if (0 != GETENV("GC_FIND_LEAK")) { GC_find_leak = 1; + # ifdef __STDC__ + atexit(GC_exit_check); + # endif } if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) { GC_all_interior_pointers = 1; *************** void GC_init_inner() *** 560,570 **** } } } ! # ifdef UNIX_LIKE ! if (0 != GETENV("GC_LOOP_ON_ABORT")) { ! GC_set_and_save_fault_handler(looping_handler); ! } ! # endif /* 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); --- 617,623 ---- } } } ! 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); *************** void GC_init_inner() *** 585,591 **** # if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__) GC_init_netbsd_elf(); # endif ! # if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) GC_thr_init(); # endif # ifdef GC_SOLARIS_THREADS --- 638,645 ---- # if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__) GC_init_netbsd_elf(); # endif ! # if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) \ ! || defined(GC_WIN32_THREADS) GC_thr_init(); # endif # ifdef GC_SOLARIS_THREADS *************** void GC_init_inner() *** 599,609 **** # if defined(LINUX) && defined(IA64) GC_register_stackbottom = GC_get_register_stack_base(); # endif } # endif ! GC_ASSERT(sizeof (ptr_t) == sizeof(word)); ! GC_ASSERT(sizeof (signed_word) == sizeof(word)); ! GC_ASSERT(sizeof (struct hblk) == HBLKSIZE); # ifndef THREADS # if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN) ABORT( --- 653,673 ---- # if defined(LINUX) && defined(IA64) GC_register_stackbottom = GC_get_register_stack_base(); # endif + } else { + # if defined(LINUX) && defined(IA64) + if (GC_register_stackbottom == 0) { + WARN("GC_register_stackbottom should be set with GC_stackbottom", 0); + /* The following is likely to fail, since we rely on */ + /* alignment properties that may not hold with a user set */ + /* GC_stackbottom. */ + GC_register_stackbottom = GC_get_register_stack_base(); + } + # endif } # endif ! GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word)); ! GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word)); ! GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE); # ifndef THREADS # if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN) ABORT( *************** void GC_init_inner() *** 642,647 **** --- 706,723 ---- initial_heap_sz = divHBLKSZ(initial_heap_sz); } } + { + char * sz_str = GETENV("GC_MAXIMUM_HEAP_SIZE"); + if (sz_str != NULL) { + word max_heap_sz = (word)atol(sz_str); + if (max_heap_sz < initial_heap_sz * HBLKSIZE) { + 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)) { GC_err_printf0("Can't start up: not enough memory\n"); EXIT(); *************** void GC_init_inner() *** 677,682 **** --- 753,759 ---- GC_incremental = TRUE; } # endif /* !SMALL_CONFIG */ + COND_DUMP; /* Get black list set up and/or incrmental GC started */ if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner(); GC_is_initialized = TRUE; *************** void GC_enable_incremental GC_PROTO(()) *** 712,719 **** if (GC_incremental) goto out; GC_setpagesize(); if (GC_no_win32_dlls) goto out; ! # ifndef GC_SOLARIS_THREADS ! GC_dirty_init(); # endif if (!GC_is_initialized) { GC_init_inner(); --- 789,797 ---- if (GC_incremental) goto out; GC_setpagesize(); if (GC_no_win32_dlls) goto out; ! # ifndef GC_SOLARIS_THREADS ! maybe_install_looping_handler(); /* Before write fault handler! */ ! GC_dirty_init(); # endif if (!GC_is_initialized) { GC_init_inner(); *************** GC_warn_proc GC_current_warn_proc = GC_d *** 925,930 **** --- 1003,1011 ---- { GC_warn_proc result; + # ifdef GC_WIN32_THREADS + GC_ASSERT(GC_is_initialized); + # endif LOCK(); result = GC_current_warn_proc; GC_current_warn_proc = p; *************** GC_warn_proc GC_current_warn_proc = GC_d *** 932,937 **** --- 1013,1029 ---- return(result); } + # if defined(__STDC__) || defined(__cplusplus) + GC_word GC_set_free_space_divisor (GC_word value) + # else + GC_word GC_set_free_space_divisor (value) + GC_word value; + # endif + { + GC_word old = GC_free_space_divisor; + GC_free_space_divisor = value; + return old; + } #ifndef PCR void GC_abort(msg) *************** GC_CONST char * msg; *** 958,1079 **** } #endif - #ifdef NEED_CALLINFO - - #ifdef HAVE_BUILTIN_BACKTRACE - # include - # ifdef LINUX - # include - # endif - #endif - - void GC_print_callers (info) - struct callinfo info[NFRAMES]; - { - register int i; - - # if NFRAMES == 1 - GC_err_printf0("\tCaller at allocation:\n"); - # else - GC_err_printf0("\tCall chain at allocation:\n"); - # endif - for (i = 0; i < NFRAMES; i++) { - if (info[i].ci_pc == 0) break; - # if NARGS > 0 - { - int j; - - GC_err_printf0("\t\targs: "); - for (j = 0; j < NARGS; j++) { - if (j != 0) GC_err_printf0(", "); - GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]), - ~(info[i].ci_arg[j])); - } - GC_err_printf0("\n"); - } - # endif - # if defined(HAVE_BUILTIN_BACKTRACE) && !defined(REDIRECT_MALLOC) - /* Unfortunately backtrace_symbols calls malloc, which makes */ - /* it dangersous if that has been redirected. */ - { - char **sym_name = - backtrace_symbols((void **)(&(info[i].ci_pc)), 1); - char *name = sym_name[0]; - GC_bool found_it = (strchr(name, '(') != 0); - FILE *pipe; - # ifdef LINUX - if (!found_it) { - # define EXE_SZ 100 - static char exe_name[EXE_SZ]; - # define CMD_SZ 200 - char cmd_buf[CMD_SZ]; - # define RESULT_SZ 200 - static char result_buf[RESULT_SZ]; - size_t result_len; - static GC_bool found_exe_name = FALSE; - static GC_bool will_fail = FALSE; - int ret_code; - /* Unfortunately, this is the common case for the */ - /* main executable. */ - /* Try to get it via a hairy and expensive scheme. */ - /* First we get the name of the executable: */ - if (will_fail) goto out; - if (!found_exe_name) { - ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ); - if (ret_code < 0 || ret_code >= EXE_SZ || exe_name[0] != '/') { - will_fail = TRUE; /* Dont try again. */ - goto out; - } - exe_name[ret_code] = '\0'; - found_exe_name = TRUE; - } - /* Then we use popen to start addr2line -e */ - /* There are faster ways to do this, but hopefully this */ - /* isn't time critical. */ - sprintf(cmd_buf, "/usr/bin/addr2line -e %s 0x%lx", exe_name, - (unsigned long)info[i].ci_pc); - pipe = popen(cmd_buf, "r"); - if (pipe < 0 || fgets(result_buf, RESULT_SZ, pipe) == 0) { - will_fail = TRUE; - goto out; - } - result_len = strlen(result_buf); - if (result_buf[result_len - 1] == '\n') --result_len; - if (result_buf[0] == '?' - || result_buf[result_len-2] == ':' - && result_buf[result_len-1] == '0') - goto out; - if (result_len < RESULT_SZ - 25) { - /* Add in hex address */ - sprintf(result_buf + result_len, " [0x%lx]", - (unsigned long)info[i].ci_pc); - } - name = result_buf; - pclose(pipe); - out: - } - # endif - GC_err_printf1("\t\t%s\n", name); - free(sym_name); - } - # else - GC_err_printf1("\t\t##PC##= 0x%lx\n", info[i].ci_pc); - # endif - } - } - - #endif /* SAVE_CALL_CHAIN */ - - /* Needed by SRC_M3, gcj, and should perhaps be the official interface */ - /* to GC_dont_gc. */ void GC_enable() { GC_dont_gc--; } void GC_disable() { GC_dont_gc++; } #if !defined(NO_DEBUGGING) --- 1050,1067 ---- } #endif void GC_enable() { + LOCK(); GC_dont_gc--; + UNLOCK(); } void GC_disable() { + LOCK(); GC_dont_gc++; + UNLOCK(); } #if !defined(NO_DEBUGGING) *************** void GC_dump() *** 1088,1093 **** --- 1076,1083 ---- GC_print_hblkfreelist(); GC_printf0("\n***Blocks in use:\n"); GC_print_block_list(); + GC_printf0("\n***Finalization statistics:\n"); + GC_print_finalization_stats(); } #endif /* NO_DEBUGGING */ diff -Nrc3pad gcc-3.3.3/boehm-gc/os_dep.c gcc-3.4.0/boehm-gc/os_dep.c *** gcc-3.3.3/boehm-gc/os_dep.c 2002-07-19 08:54:43.000000000 +0000 --- gcc-3.4.0/boehm-gc/os_dep.c 2003-09-22 16:00:23.000000000 +0000 *************** *** 80,91 **** # define NEED_FIND_LIMIT # endif - #ifdef NEED_FIND_LIMIT - # include - #endif - #if defined(FREEBSD) && defined(I386) # include #endif #ifdef AMIGA --- 80,94 ---- # define NEED_FIND_LIMIT # endif #if defined(FREEBSD) && defined(I386) # include + # if !defined(PCR) + # define NEED_FIND_LIMIT + # endif + #endif + + #ifdef NEED_FIND_LIMIT + # include #endif #ifdef AMIGA *************** *** 129,134 **** --- 132,142 ---- # define jmp_buf sigjmp_buf #endif + #ifdef DARWIN + /* for get_etext and friends */ + #include + #endif + #ifdef DJGPP /* Apparently necessary for djgpp 2.01. May cause problems with */ /* other versions. */ *************** *** 147,152 **** --- 155,310 ---- # define OPT_PROT_EXEC 0 #endif + #if defined(LINUX) && \ + (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64) || !defined(SMALL_CONFIG)) + + /* We need to parse /proc/self/maps, either to find dynamic libraries, */ + /* and/or to find the register backing store base (IA64). Do it once */ + /* here. */ + + #define READ read + + /* Repeatedly perform a read call until the buffer is filled or */ + /* we encounter EOF. */ + ssize_t GC_repeat_read(int fd, char *buf, size_t count) + { + ssize_t num_read = 0; + ssize_t result; + + while (num_read < count) { + result = READ(fd, buf + num_read, count - num_read); + if (result < 0) return result; + if (result == 0) break; + num_read += result; + } + return num_read; + } + + /* + * Apply fn to a buffer containing the contents of /proc/self/maps. + * Return the result of fn or, if we failed, 0. + */ + + word GC_apply_to_maps(word (*fn)(char *)) + { + int f; + int result; + int maps_size; + char maps_temp[32768]; + char *maps_buf; + + /* Read /proc/self/maps */ + /* Note that we may not allocate, and thus can't use stdio. */ + f = open("/proc/self/maps", O_RDONLY); + if (-1 == f) return 0; + /* stat() doesn't work for /proc/self/maps, so we have to + read it to find out how large it is... */ + maps_size = 0; + do { + result = GC_repeat_read(f, maps_temp, sizeof(maps_temp)); + if (result <= 0) return 0; + maps_size += result; + } while (result == sizeof(maps_temp)); + + if (maps_size > sizeof(maps_temp)) { + /* If larger than our buffer, close and re-read it. */ + close(f); + f = open("/proc/self/maps", O_RDONLY); + if (-1 == f) return 0; + maps_buf = alloca(maps_size); + if (NULL == maps_buf) return 0; + result = GC_repeat_read(f, maps_buf, maps_size); + if (result <= 0) return 0; + } else { + /* Otherwise use the fixed size buffer */ + maps_buf = maps_temp; + } + + close(f); + maps_buf[result] = '\0'; + + /* Apply fn to result. */ + return fn(maps_buf); + } + + #endif /* Need GC_apply_to_maps */ + + #if defined(LINUX) && (defined(USE_PROC_FOR_LIBRARIES) || defined(IA64)) + // + // GC_parse_map_entry parses an entry from /proc/self/maps so we can + // locate all writable data segments that belong to shared libraries. + // The format of one of these entries and the fields we care about + // is as follows: + // XXXXXXXX-XXXXXXXX r-xp 00000000 30:05 260537 name of mapping...\n + // ^^^^^^^^ ^^^^^^^^ ^^^^ ^^ + // start end prot maj_dev + // 0 9 18 32 + // + // For 64 bit ABIs: + // 0 17 34 56 + // + // The parser is called with a pointer to the entry and the return value + // is either NULL or is advanced to the next entry(the byte after the + // trailing '\n'.) + // + #if CPP_WORDSZ == 32 + # define OFFSET_MAP_START 0 + # define OFFSET_MAP_END 9 + # define OFFSET_MAP_PROT 18 + # define OFFSET_MAP_MAJDEV 32 + # define ADDR_WIDTH 8 + #endif + + #if CPP_WORDSZ == 64 + # define OFFSET_MAP_START 0 + # define OFFSET_MAP_END 17 + # define OFFSET_MAP_PROT 34 + # define OFFSET_MAP_MAJDEV 56 + # define ADDR_WIDTH 16 + #endif + + /* + * Assign various fields of the first line in buf_ptr to *start, *end, + * *prot_buf and *maj_dev. Only *prot_buf may be set for unwritable maps. + */ + char *GC_parse_map_entry(char *buf_ptr, word *start, word *end, + char *prot_buf, unsigned int *maj_dev) + { + int i; + char *tok; + + if (buf_ptr == NULL || *buf_ptr == '\0') { + return NULL; + } + + memcpy(prot_buf, buf_ptr+OFFSET_MAP_PROT, 4); + /* do the protections first. */ + prot_buf[4] = '\0'; + + if (prot_buf[1] == 'w') {/* we can skip all of this if it's not writable. */ + + tok = buf_ptr; + buf_ptr[OFFSET_MAP_START+ADDR_WIDTH] = '\0'; + *start = strtoul(tok, NULL, 16); + + tok = buf_ptr+OFFSET_MAP_END; + buf_ptr[OFFSET_MAP_END+ADDR_WIDTH] = '\0'; + *end = strtoul(tok, NULL, 16); + + buf_ptr += OFFSET_MAP_MAJDEV; + tok = buf_ptr; + while (*buf_ptr != ':') buf_ptr++; + *buf_ptr++ = '\0'; + *maj_dev = strtoul(tok, NULL, 16); + } + + while (*buf_ptr && *buf_ptr++ != '\n'); + + return buf_ptr; + } + + #endif /* Need to parse /proc/self/maps. */ + #if defined(SEARCH_FOR_DATA_START) /* The I386 case can be handled without a search. The Alpha case */ /* used to be handled differently as well, but the rules changed */ *************** *** 154,159 **** --- 312,322 ---- /* cover all versions. */ # ifdef LINUX + /* Some Linux distributions arrange to define __data_start. Some */ + /* define data_start as a weak symbol. The latter is technically */ + /* broken, since the user program may define data_start, in which */ + /* case we lose. Nonetheless, we try both, prefering __data_start. */ + /* We assume gcc-compatible pragmas. */ # pragma weak __data_start extern int __data_start[]; # pragma weak data_start *************** *** 169,184 **** # ifdef LINUX /* Try the easy approaches first: */ ! if (__data_start != 0) { ! GC_data_start = (ptr_t)__data_start; return; } ! if (data_start != 0) { ! GC_data_start = (ptr_t)data_start; return; } # endif /* LINUX */ ! GC_data_start = GC_find_limit((ptr_t)_end, FALSE); } #endif --- 332,347 ---- # ifdef LINUX /* Try the easy approaches first: */ ! if ((ptr_t)__data_start != 0) { ! GC_data_start = (ptr_t)(__data_start); return; } ! if ((ptr_t)data_start != 0) { ! GC_data_start = (ptr_t)(data_start); return; } # endif /* LINUX */ ! GC_data_start = GC_find_limit((ptr_t)(_end), FALSE); } #endif *************** ptr_t GC_get_stack_base() *** 617,623 **** } /* Return the first nonaddressible location > p (up) or */ ! /* the smallest location q s.t. [q,p] is addressible (!up). */ ptr_t GC_find_limit(p, up) ptr_t p; GC_bool up; --- 780,787 ---- } /* Return the first nonaddressible location > p (up) or */ ! /* the smallest location q s.t. [q,p) is addressable (!up). */ ! /* We assume that p (up) or p-1 (!up) is addressable. */ ptr_t GC_find_limit(p, up) ptr_t p; GC_bool up; *************** ptr_t GC_get_stack_base() *** 650,667 **** } # endif ! # if defined(ECOS) || defined(NOSYS) ! ptr_t GC_get_stack_base() ! { ! return STACKBOTTOM; ! } ! ! #else #ifdef LINUX_STACKBOTTOM #include #include # define STAT_SKIP 27 /* Number of fields preceding startstack */ /* field in /proc/self/stat */ --- 814,831 ---- } # endif ! #if defined(ECOS) || defined(NOSYS) ! ptr_t GC_get_stack_base() ! { ! return STACKBOTTOM; ! } ! #endif #ifdef LINUX_STACKBOTTOM #include #include + #include # define STAT_SKIP 27 /* Number of fields preceding startstack */ /* field in /proc/self/stat */ *************** ptr_t GC_get_stack_base() *** 670,675 **** --- 834,866 ---- extern ptr_t __libc_stack_end; # ifdef IA64 + /* Try to read the backing store base from /proc/self/maps. */ + /* We look for the writable mapping with a 0 major device, */ + /* which is as close to our frame as possible, but below it.*/ + static word backing_store_base_from_maps(char *maps) + { + char prot_buf[5]; + char *buf_ptr = maps; + word start, end; + unsigned int maj_dev; + word current_best = 0; + word dummy; + + for (;;) { + buf_ptr = GC_parse_map_entry(buf_ptr, &start, &end, prot_buf, &maj_dev); + if (buf_ptr == NULL) return current_best; + if (prot_buf[1] == 'w' && maj_dev == 0) { + if (end < (word)(&dummy) && start > current_best) current_best = start; + } + } + return current_best; + } + + static word backing_store_base_from_proc(void) + { + return GC_apply_to_maps(backing_store_base_from_maps); + } + # pragma weak __libc_ia64_register_backing_store_base extern ptr_t __libc_ia64_register_backing_store_base; *************** ptr_t GC_get_stack_base() *** 679,691 **** && 0 != __libc_ia64_register_backing_store_base) { /* Glibc 2.2.4 has a bug such that for dynamically linked */ /* executables __libc_ia64_register_backing_store_base is */ ! /* defined but ininitialized during constructor calls. */ /* Hence we check for both nonzero address and value. */ return __libc_ia64_register_backing_store_base; } else { ! word result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT; ! result += BACKING_STORE_ALIGNMENT - 1; ! result &= ~(BACKING_STORE_ALIGNMENT - 1); return (ptr_t)result; } } --- 870,888 ---- && 0 != __libc_ia64_register_backing_store_base) { /* Glibc 2.2.4 has a bug such that for dynamically linked */ /* executables __libc_ia64_register_backing_store_base is */ ! /* defined but uninitialized during constructor calls. */ /* Hence we check for both nonzero address and value. */ return __libc_ia64_register_backing_store_base; } else { ! word result = backing_store_base_from_proc(); ! if (0 == result) { ! /* Use dumb heuristics. Works only for default configuration. */ ! result = (word)GC_stackbottom - BACKING_STORE_DISPLACEMENT; ! result += BACKING_STORE_ALIGNMENT - 1; ! result &= ~(BACKING_STORE_ALIGNMENT - 1); ! /* Verify that it's at least readable. If not, we goofed. */ ! GC_noop1(*(word *)result); ! } return (ptr_t)result; } } *************** ptr_t GC_get_stack_base() *** 697,707 **** /* using direct I/O system calls in order to avoid calling malloc */ /* in case REDIRECT_MALLOC is defined. */ # define STAT_BUF_SIZE 4096 ! # if defined(GC_USE_LD_WRAP) ! # define STAT_READ __real_read ! # else ! # define STAT_READ read ! # endif char stat_buf[STAT_BUF_SIZE]; int f; char c; --- 894,901 ---- /* using direct I/O system calls in order to avoid calling malloc */ /* in case REDIRECT_MALLOC is defined. */ # define STAT_BUF_SIZE 4096 ! # define STAT_READ read ! /* Should probably call the real read, if read is wrapped. */ char stat_buf[STAT_BUF_SIZE]; int f; char c; *************** ptr_t GC_get_stack_base() *** 710,716 **** /* First try the easy way. This should work for glibc 2.2 */ if (0 != &__libc_stack_end) { ! return __libc_stack_end; } f = open("/proc/self/stat", O_RDONLY); if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) { --- 904,919 ---- /* First try the easy way. This should work for glibc 2.2 */ if (0 != &__libc_stack_end) { ! # ifdef IA64 ! /* Some versions of glibc set the address 16 bytes too */ ! /* low while the initialization code is running. */ ! if (((word)__libc_stack_end & 0xfff) + 0x10 < 0x1000) { ! return __libc_stack_end + 0x10; ! } /* Otherwise it's not safe to add 16 bytes and we fall */ ! /* back to using /proc. */ ! # else ! return __libc_stack_end; ! # endif } f = open("/proc/self/stat", O_RDONLY); if (f < 0 || STAT_READ(f, stat_buf, STAT_BUF_SIZE) < 2 * STAT_SKIP) { *************** ptr_t GC_get_stack_base() *** 760,771 **** #endif /* FREEBSD_STACKBOTTOM */ #if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \ ! && !defined(MSWINCE) && !defined(OS2) ptr_t GC_get_stack_base() { word dummy; ptr_t result; # define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1) --- 963,977 ---- #endif /* FREEBSD_STACKBOTTOM */ #if !defined(BEOS) && !defined(AMIGA) && !defined(MSWIN32) \ ! && !defined(MSWINCE) && !defined(OS2) && !defined(NOSYS) && !defined(ECOS) ptr_t GC_get_stack_base() { + # if defined(HEURISTIC1) || defined(HEURISTIC2) || \ + defined(LINUX_STACKBOTTOM) || defined(FREEBSD_STACKBOTTOM) word dummy; ptr_t result; + # endif # define STACKBOTTOM_ALIGNMENT_M1 ((word)STACK_GRAN - 1) *************** ptr_t GC_get_stack_base() *** 814,822 **** return(result); # endif /* STACKBOTTOM */ } - # endif /* NOSYS ECOS */ ! # endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS */ /* * Register static data segment(s) as roots. --- 1020,1027 ---- return(result); # endif /* STACKBOTTOM */ } ! # endif /* ! AMIGA, !OS 2, ! MS Windows, !BEOS, !NOSYS, !ECOS */ /* * Register static data segment(s) as roots. *************** void GC_register_data_segments() *** 924,938 **** /* Unfortunately, we have to handle win32s very differently from NT, */ /* Since VirtualQuery has very different semantics. In particular, */ /* under win32s a VirtualQuery call on an unmapped page returns an */ ! /* invalid result. Under GC_register_data_segments is a noop and */ /* all real work is done by GC_register_dynamic_libraries. Under */ /* win32s, we cannot find the data segments associated with dll's. */ ! /* We rgister the main data segment here. */ ! # ifdef __GCC__ ! GC_bool GC_no_win32_dlls = TRUE; /* GCC can't do SEH, so we can't use VirtualQuery */ ! # else GC_bool GC_no_win32_dlls = FALSE; ! # endif void GC_init_win32() { --- 1129,1142 ---- /* Unfortunately, we have to handle win32s very differently from NT, */ /* Since VirtualQuery has very different semantics. In particular, */ /* under win32s a VirtualQuery call on an unmapped page returns an */ ! /* invalid result. Under NT, GC_register_data_segments is a noop and */ /* all real work is done by GC_register_dynamic_libraries. Under */ /* win32s, we cannot find the data segments associated with dll's. */ ! /* We register the main data segment here. */ GC_bool GC_no_win32_dlls = FALSE; ! /* This used to be set for gcc, to avoid dealing with */ ! /* the structured exception handling issues. But we now have */ ! /* assembly code to do that right. */ void GC_init_win32() { *************** void GC_register_data_segments() *** 964,999 **** return(p); } # endif /* Is p the start of either the malloc heap, or of one of our */ /* heap sections? */ GC_bool GC_is_heap_base (ptr_t p) { ! register unsigned i; # ifndef REDIRECT_MALLOC ! static ptr_t malloc_heap_pointer = 0; ! if (0 == malloc_heap_pointer) { ! MEMORY_BASIC_INFORMATION buf; ! void *pTemp = malloc( 1 ); ! register DWORD result = VirtualQuery(pTemp, &buf, sizeof(buf)); ! ! free( pTemp ); ! ! ! if (result != sizeof(buf)) { ! ABORT("Weird VirtualQuery result"); ! } ! malloc_heap_pointer = (ptr_t)(buf.AllocationBase); } ! if (p == malloc_heap_pointer) return(TRUE); # endif for (i = 0; i < GC_n_heap_bases; i++) { ! if (GC_heap_bases[i] == p) return(TRUE); } ! return(FALSE); } # ifdef MSWIN32 --- 1168,1269 ---- return(p); } # endif + + # ifndef REDIRECT_MALLOC + /* We maintain a linked list of AllocationBase values that we know */ + /* correspond to malloc heap sections. Currently this is only called */ + /* during a GC. But there is some hope that for long running */ + /* programs we will eventually see most heap sections. */ + + /* In the long run, it would be more reliable to occasionally walk */ + /* the malloc heap with HeapWalk on the default heap. But that */ + /* apparently works only for NT-based Windows. */ + + /* In the long run, a better data structure would also be nice ... */ + struct GC_malloc_heap_list { + void * allocation_base; + struct GC_malloc_heap_list *next; + } *GC_malloc_heap_l = 0; + + /* Is p the base of one of the malloc heap sections we already know */ + /* about? */ + GC_bool GC_is_malloc_heap_base(ptr_t p) + { + struct GC_malloc_heap_list *q = GC_malloc_heap_l; + + while (0 != q) { + if (q -> allocation_base == p) return TRUE; + q = q -> next; + } + return FALSE; + } + + void *GC_get_allocation_base(void *p) + { + MEMORY_BASIC_INFORMATION buf; + DWORD result = VirtualQuery(p, &buf, sizeof(buf)); + if (result != sizeof(buf)) { + ABORT("Weird VirtualQuery result"); + } + return buf.AllocationBase; + } + + size_t GC_max_root_size = 100000; /* Appr. largest root size. */ + + void GC_add_current_malloc_heap() + { + struct GC_malloc_heap_list *new_l = + malloc(sizeof(struct GC_malloc_heap_list)); + void * candidate = GC_get_allocation_base(new_l); + + if (new_l == 0) return; + if (GC_is_malloc_heap_base(candidate)) { + /* Try a little harder to find malloc heap. */ + size_t req_size = 10000; + do { + void *p = malloc(req_size); + if (0 == p) { free(new_l); return; } + candidate = GC_get_allocation_base(p); + free(p); + req_size *= 2; + } while (GC_is_malloc_heap_base(candidate) + && req_size < GC_max_root_size/10 && req_size < 500000); + if (GC_is_malloc_heap_base(candidate)) { + free(new_l); return; + } + } + # ifdef CONDPRINT + if (GC_print_stats) + GC_printf1("Found new system malloc AllocationBase at 0x%lx\n", + candidate); + # endif + new_l -> allocation_base = candidate; + new_l -> next = GC_malloc_heap_l; + GC_malloc_heap_l = new_l; + } + # endif /* REDIRECT_MALLOC */ /* Is p the start of either the malloc heap, or of one of our */ /* heap sections? */ GC_bool GC_is_heap_base (ptr_t p) { ! unsigned i; # ifndef REDIRECT_MALLOC ! static word last_gc_no = -1; ! if (last_gc_no != GC_gc_no) { ! GC_add_current_malloc_heap(); ! last_gc_no = GC_gc_no; } ! if (GC_root_size > GC_max_root_size) GC_max_root_size = GC_root_size; ! if (GC_is_malloc_heap_base(p)) return TRUE; # endif for (i = 0; i < GC_n_heap_bases; i++) { ! if (GC_heap_bases[i] == p) return TRUE; } ! return FALSE ; } # ifdef MSWIN32 *************** void GC_register_data_segments() *** 1043,1049 **** # if (defined(SVR4) || defined(AUX) || defined(DGUX) \ || (defined(LINUX) && defined(SPARC))) && !defined(PCR) ! char * GC_SysVGetDataStart(max_page_size, etext_addr) int max_page_size; int * etext_addr; { --- 1313,1319 ---- # if (defined(SVR4) || defined(AUX) || defined(DGUX) \ || (defined(LINUX) && defined(SPARC))) && !defined(PCR) ! ptr_t GC_SysVGetDataStart(max_page_size, etext_addr) int max_page_size; int * etext_addr; { *************** int * etext_addr; *** 1069,1080 **** /* 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) - MIN_PAGE_SIZE, FALSE); } ! return((char *)result); } # endif #ifdef AMIGA --- 1339,1383 ---- /* 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); } ! return((ptr_t)result); } # endif + # if defined(FREEBSD) && defined(I386) && !defined(PCR) + /* 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(max_page_size, etext_addr) + int max_page_size; + int * etext_addr; + { + word text_end = ((word)(etext_addr) + sizeof(word) - 1) + & ~(sizeof(word) - 1); + /* etext rounded to word boundary */ + VOLATILE word next_page = (text_end + (word)max_page_size - 1) + & ~((word)max_page_size - 1); + VOLATILE ptr_t result = (ptr_t)text_end; + GC_setup_temporary_fault_handler(); + 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) + *(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); + } + return(result); + } + + # endif + #ifdef AMIGA *************** int * etext_addr; *** 1086,1093 **** void GC_register_data_segments() { ! # if !defined(PCR) && !defined(SRC_M3) && !defined(NEXT) && !defined(MACOS) \ ! && !defined(MACOSX) # if defined(REDIRECT_MALLOC) && defined(GC_SOLARIS_THREADS) /* As of Solaris 2.3, the Solaris threads implementation */ /* allocates the data structure for the initial thread with */ --- 1389,1395 ---- void GC_register_data_segments() { ! # if !defined(PCR) && !defined(SRC_M3) && !defined(MACOS) # if defined(REDIRECT_MALLOC) && defined(GC_SOLARIS_THREADS) /* As of Solaris 2.3, the Solaris threads implementation */ /* allocates the data structure for the initial thread with */ *************** void GC_register_data_segments() *** 1104,1112 **** # endif # endif # endif - # if !defined(PCR) && (defined(NEXT) || defined(MACOSX)) - GC_add_roots_inner(DATASTART, (char *) get_end(), FALSE); - # endif # if defined(MACOS) { # if defined(THINK_C) --- 1406,1411 ---- *************** word bytes; *** 1216,1233 **** ptr_t GC_unix_get_mem(bytes) word bytes; { - static GC_bool initialized = FALSE; - static int fd; void *result; static ptr_t last_addr = HEAP_START; ! if (!initialized) { ! fd = open("/dev/zero", O_RDONLY); ! initialized = TRUE; ! } if (bytes & (GC_page_size -1)) ABORT("Bad GET_MEM arg"); ! result = mmap(last_addr, bytes, PROT_READ | PROT_WRITE | OPT_PROT_EXEC, ! GC_MMAP_FLAGS, fd, 0/* offset */); if (result == MAP_FAILED) return(0); last_addr = (ptr_t)result + bytes + GC_page_size - 1; last_addr = (ptr_t)((word)last_addr & ~(GC_page_size - 1)); --- 1515,1542 ---- ptr_t GC_unix_get_mem(bytes) word bytes; { void *result; static ptr_t last_addr = HEAP_START; ! # ifndef USE_MMAP_ANON ! static GC_bool initialized = FALSE; ! static int fd; ! ! if (!initialized) { ! fd = open("/dev/zero", O_RDONLY); ! fcntl(fd, F_SETFD, FD_CLOEXEC); ! initialized = TRUE; ! } ! # endif ! if (bytes & (GC_page_size -1)) ABORT("Bad GET_MEM arg"); ! # ifdef USE_MMAP_ANON ! result = mmap(last_addr, bytes, PROT_READ | PROT_WRITE | OPT_PROT_EXEC, ! GC_MMAP_FLAGS | MAP_ANON, -1, 0/* offset */); ! # else ! result = mmap(last_addr, bytes, PROT_READ | PROT_WRITE | OPT_PROT_EXEC, ! GC_MMAP_FLAGS, fd, 0/* offset */); ! # endif if (result == MAP_FAILED) return(0); last_addr = (ptr_t)result + bytes + GC_page_size - 1; last_addr = (ptr_t)((word)last_addr & ~(GC_page_size - 1)); *************** word bytes; *** 1322,1328 **** result = (ptr_t) GlobalAlloc(0, bytes + HBLKSIZE); result = (ptr_t)(((word)result + HBLKSIZE) & ~(HBLKSIZE-1)); } else { ! result = (ptr_t) VirtualAlloc(NULL, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); } --- 1631,1645 ---- result = (ptr_t) GlobalAlloc(0, bytes + HBLKSIZE); result = (ptr_t)(((word)result + HBLKSIZE) & ~(HBLKSIZE-1)); } else { ! /* VirtualProtect only works on regions returned by a */ ! /* single VirtualAlloc call. Thus we allocate one */ ! /* extra page, which will prevent merging of blocks */ ! /* in separate regions, and eliminate any temptation */ ! /* to call VirtualProtect on a range spanning regions. */ ! /* This wastes a small amount of memory, and risks */ ! /* increased fragmentation. But better alternatives */ ! /* would require effort. */ ! result = (ptr_t) VirtualAlloc(NULL, bytes + 1, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); } *************** word bytes; *** 1378,1383 **** --- 1695,1704 ---- /* Reserve more pages */ word res_bytes = (bytes + GC_sysinfo.dwAllocationGranularity-1) & ~(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 argument */ + /* to span regions, so we should be OK for now. */ result = (ptr_t) VirtualAlloc(NULL, res_bytes, MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); *************** void GC_remap(ptr_t start, word bytes) *** 1508,1513 **** --- 1829,1835 ---- } # else if (-1 == zero_descr) zero_descr = open("/dev/zero", O_RDWR); + fcntl(zero_descr, F_SETFD, FD_CLOEXEC); if (0 == start_addr) return; result = mmap(start_addr, len, PROT_READ | PROT_WRITE | OPT_PROT_EXEC, MAP_FIXED | MAP_PRIVATE, zero_descr, 0); *************** void (*GC_push_other_roots) GC_PROTO((vo *** 1694,1700 **** * make sure that other system calls are similarly protected * or write only to the stack. */ - GC_bool GC_dirty_maintained = FALSE; # ifdef DEFAULT_VDB --- 2016,2021 ---- *************** GC_bool GC_dirty_maintained = FALSE; *** 1708,1713 **** --- 2029,2037 ---- /* Initialize virtual dirty bit implementation. */ void GC_dirty_init() { + # ifdef PRINTSTATS + GC_printf0("Initializing DEFAULT_VDB...\n"); + # endif GC_dirty_maintained = TRUE; } *************** GC_bool is_ptrfree; *** 1776,1792 **** /* * This implementation maintains dirty bits itself by catching write * faults and keeping track of them. We assume nobody else catches ! * SIGBUS or SIGSEGV. We assume no write faults occur in system calls ! * except as a result of a read system call. This means clients must ! * either ensure that system calls do not touch the heap, or must ! * provide their own wrappers analogous to the one for read. * We assume the page size is a multiple of HBLKSIZE. ! * This implementation is currently SunOS 4.X and IRIX 5.X specific, though we ! * tried to use portable code where easily possible. It is known ! * not to work under a number of other systems. */ ! # if !defined(MSWIN32) && !defined(MSWINCE) # include # include --- 2100,2120 ---- /* * This implementation maintains dirty bits itself by catching write * faults and keeping track of them. We assume nobody else catches ! * SIGBUS or SIGSEGV. We assume no write faults occur in system calls. ! * This means that clients must ensure that system calls don't write ! * to the write-protected heap. Probably the best way to do this is to ! * ensure that system calls write at most to POINTERFREE objects in the ! * heap, and do even that only if we are on a platform on which those ! * are not protected. Another alternative is to wrap system calls ! * (see example for read below), but the current implementation holds ! * a lock across blocking calls, making it problematic for multithreaded ! * applications. * We assume the page size is a multiple of HBLKSIZE. ! * We prefer them to be the same. We avoid protecting POINTERFREE ! * objects only if they are the same. */ ! # if !defined(MSWIN32) && !defined(MSWINCE) && !defined(DARWIN) # include # include *************** GC_bool is_ptrfree; *** 1805,1810 **** --- 2133,2155 ---- # else + # ifdef DARWIN + /* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to + decrease the likelihood of some of the problems described below. */ + #include + extern mach_port_t GC_task_self; + #define PROTECT(addr,len) \ + if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \ + FALSE,VM_PROT_READ) != KERN_SUCCESS) { \ + ABORT("vm_portect failed"); \ + } + #define UNPROTECT(addr,len) \ + if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \ + FALSE,VM_PROT_READ|VM_PROT_WRITE) != KERN_SUCCESS) { \ + ABORT("vm_portect failed"); \ + } + # else + # ifndef MSWINCE # include # endif *************** GC_bool is_ptrfree; *** 1822,1841 **** &protect_junk)) { \ ABORT("un-VirtualProtect failed"); \ } ! ! # endif #if defined(SUNOS4) || defined(FREEBSD) typedef void (* SIG_PF)(); ! #endif #if defined(SUNOS5SIGS) || defined(OSF1) || defined(LINUX) \ ! || defined(MACOSX) || defined(HURD) # ifdef __STDC__ typedef void (* SIG_PF)(int); # else typedef void (* SIG_PF)(); # endif ! #endif #if defined(MSWIN32) typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_PF; # undef SIG_DFL --- 2167,2188 ---- &protect_junk)) { \ ABORT("un-VirtualProtect failed"); \ } ! # endif /* !DARWIN */ ! # endif /* MSWIN32 || MSWINCE || DARWIN */ #if defined(SUNOS4) || defined(FREEBSD) typedef void (* SIG_PF)(); ! #endif /* SUNOS4 || FREEBSD */ ! #if defined(SUNOS5SIGS) || defined(OSF1) || defined(LINUX) \ ! || defined(HURD) # ifdef __STDC__ typedef void (* SIG_PF)(int); # else typedef void (* SIG_PF)(); # endif ! #endif /* SUNOS5SIGS || OSF1 || LINUX || HURD */ ! #if defined(MSWIN32) typedef LPTOP_LEVEL_EXCEPTION_FILTER SIG_PF; # undef SIG_DFL *************** GC_bool is_ptrfree; *** 1849,1855 **** #if defined(IRIX5) || defined(OSF1) || defined(HURD) typedef void (* REAL_SIG_PF)(int, int, struct sigcontext *); ! #endif #if defined(SUNOS5SIGS) # ifdef HPUX # define SIGINFO __siginfo --- 2196,2203 ---- #if defined(IRIX5) || defined(OSF1) || defined(HURD) typedef void (* REAL_SIG_PF)(int, int, struct sigcontext *); ! #endif /* IRIX5 || OSF1 || HURD */ ! #if defined(SUNOS5SIGS) # ifdef HPUX # define SIGINFO __siginfo *************** GC_bool is_ptrfree; *** 1861,1873 **** # else typedef void (* REAL_SIG_PF)(); # endif ! #endif #if defined(LINUX) # if __GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 2 typedef struct sigcontext s_c; # else /* glibc < 2.2 */ # include ! # if (LINUX_VERSION_CODE >= 0x20100) && !defined(M68K) || defined(ALPHA) typedef struct sigcontext s_c; # else typedef struct sigcontext_struct s_c; --- 2209,2222 ---- # else typedef void (* REAL_SIG_PF)(); # endif ! #endif /* SUNOS5SIGS */ ! #if defined(LINUX) # if __GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 2 typedef struct sigcontext s_c; # else /* glibc < 2.2 */ # include ! # if (LINUX_VERSION_CODE >= 0x20100) && !defined(M68K) || defined(ALPHA) || defined(ARM32) typedef struct sigcontext s_c; # else typedef struct sigcontext_struct s_c; *************** GC_bool is_ptrfree; *** 1895,2033 **** return (char *)faultaddr; } # endif /* !ALPHA */ ! # endif ! ! # if defined(MACOSX) /* Should also test for PowerPC? */ ! typedef void (* REAL_SIG_PF)(int, int, struct sigcontext *); ! ! /* Decodes the machine instruction which was responsible for the sending of the ! SIGBUS signal. Sadly this is the only way to find the faulting address because ! the signal handler doesn't get it directly from the kernel (although it is ! available on the Mach level, but droppped by the BSD personality before it ! calls our signal handler...) ! This code should be able to deal correctly with all PPCs starting from the ! 601 up to and including the G4s (including Velocity Engine). */ ! #define EXTRACT_OP1(iw) (((iw) & 0xFC000000) >> 26) ! #define EXTRACT_OP2(iw) (((iw) & 0x000007FE) >> 1) ! #define EXTRACT_REGA(iw) (((iw) & 0x001F0000) >> 16) ! #define EXTRACT_REGB(iw) (((iw) & 0x03E00000) >> 21) ! #define EXTRACT_REGC(iw) (((iw) & 0x0000F800) >> 11) ! #define EXTRACT_DISP(iw) ((short *) &(iw))[1] ! ! static char *get_fault_addr(struct sigcontext *scp) ! { ! unsigned int instr = *((unsigned int *) scp->sc_ir); ! unsigned int * regs = &((unsigned int *) scp->sc_regs)[2]; ! int disp = 0, tmp; ! unsigned int baseA = 0, baseB = 0; ! unsigned int addr, alignmask = 0xFFFFFFFF; ! ! #ifdef GC_DEBUG_DECODER ! GC_err_printf1("Instruction: 0x%lx\n", instr); ! GC_err_printf1("Opcode 1: d\n", (int)EXTRACT_OP1(instr)); ! #endif ! switch(EXTRACT_OP1(instr)) { ! case 38: /* stb */ ! case 39: /* stbu */ ! case 54: /* stfd */ ! case 55: /* stfdu */ ! case 52: /* stfs */ ! case 53: /* stfsu */ ! case 44: /* sth */ ! case 45: /* sthu */ ! case 47: /* stmw */ ! case 36: /* stw */ ! case 37: /* stwu */ ! tmp = EXTRACT_REGA(instr); ! if(tmp > 0) ! baseA = regs[tmp]; ! disp = EXTRACT_DISP(instr); ! break; ! case 31: ! #ifdef GC_DEBUG_DECODER ! GC_err_printf1("Opcode 2: %d\n", (int)EXTRACT_OP2(instr)); ! #endif ! switch(EXTRACT_OP2(instr)) { ! case 86: /* dcbf */ ! case 54: /* dcbst */ ! case 1014: /* dcbz */ ! case 247: /* stbux */ ! case 215: /* stbx */ ! case 759: /* stfdux */ ! case 727: /* stfdx */ ! case 983: /* stfiwx */ ! case 695: /* stfsux */ ! case 663: /* stfsx */ ! case 918: /* sthbrx */ ! case 439: /* sthux */ ! case 407: /* sthx */ ! case 661: /* stswx */ ! case 662: /* stwbrx */ ! case 150: /* stwcx. */ ! case 183: /* stwux */ ! case 151: /* stwx */ ! case 135: /* stvebx */ ! case 167: /* stvehx */ ! case 199: /* stvewx */ ! case 231: /* stvx */ ! case 487: /* stvxl */ ! tmp = EXTRACT_REGA(instr); ! if(tmp > 0) ! baseA = regs[tmp]; ! baseB = regs[EXTRACT_REGC(instr)]; ! /* determine Altivec alignment mask */ ! switch(EXTRACT_OP2(instr)) { ! case 167: /* stvehx */ ! alignmask = 0xFFFFFFFE; ! break; ! case 199: /* stvewx */ ! alignmask = 0xFFFFFFFC; ! break; ! case 231: /* stvx */ ! alignmask = 0xFFFFFFF0; ! break; ! case 487: /* stvxl */ ! alignmask = 0xFFFFFFF0; ! break; ! } ! break; ! case 725: /* stswi */ ! tmp = EXTRACT_REGA(instr); ! if(tmp > 0) ! baseA = regs[tmp]; ! break; ! default: /* ignore instruction */ ! #ifdef GC_DEBUG_DECODER ! GC_err_printf("Ignored by inner handler\n"); ! #endif ! return NULL; ! break; ! } ! break; ! default: /* ignore instruction */ ! #ifdef GC_DEBUG_DECODER ! GC_err_printf("Ignored by main handler\n"); ! #endif ! return NULL; ! break; ! } ! ! addr = (baseA + baseB) + disp; ! addr &= alignmask; ! #ifdef GC_DEBUG_DECODER ! GC_err_printf1("BaseA: %d\n", baseA); ! GC_err_printf1("BaseB: %d\n", baseB); ! GC_err_printf1("Disp: %d\n", disp); ! GC_err_printf1("Address: %d\n", addr); ! #endif ! return (char *)addr; ! } ! #endif /* MACOSX */ SIG_PF GC_old_bus_handler; SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */ ! #ifdef THREADS /* We need to lock around the bitmap update in the write fault handler */ /* in order to avoid the risk of losing a bit. We do this with a */ /* test-and-set spin lock if we know how to do that. Otherwise we */ --- 2244,2257 ---- return (char *)faultaddr; } # endif /* !ALPHA */ ! # endif /* LINUX */ + #ifndef DARWIN SIG_PF GC_old_bus_handler; SIG_PF GC_old_segv_handler; /* Also old MSWIN32 ACCESS_VIOLATION filter */ + #endif /* !DARWIN */ ! #if defined(THREADS) /* We need to lock around the bitmap update in the write fault handler */ /* in order to avoid the risk of losing a bit. We do this with a */ /* test-and-set spin lock if we know how to do that. Otherwise we */ *************** SIG_PF GC_old_segv_handler; /* Also old *** 2076,2081 **** --- 2300,2306 ---- #endif /* !THREADS */ /*ARGSUSED*/ + #if !defined(DARWIN) # if defined (SUNOS4) || defined(FREEBSD) void GC_write_fault_handler(sig, code, scp, addr) int sig, code; *************** SIG_PF GC_old_segv_handler; /* Also old *** 2091,2097 **** # define SIG_OK (sig == SIGBUS) # define CODE_OK (code == BUS_PAGE_FAULT) # endif ! # endif # if defined(IRIX5) || defined(OSF1) || defined(HURD) # include void GC_write_fault_handler(int sig, int code, struct sigcontext *scp) --- 2316,2323 ---- # define SIG_OK (sig == SIGBUS) # define CODE_OK (code == BUS_PAGE_FAULT) # endif ! # endif /* SUNOS4 || FREEBSD */ ! # if defined(IRIX5) || defined(OSF1) || defined(HURD) # include void GC_write_fault_handler(int sig, int code, struct sigcontext *scp) *************** SIG_PF GC_old_segv_handler; /* Also old *** 2107,2113 **** # define SIG_OK (sig == SIGBUS || sig == SIGSEGV) # define CODE_OK TRUE # endif ! # endif # if defined(LINUX) # if defined(ALPHA) || defined(M68K) void GC_write_fault_handler(int sig, int code, s_c * sc) --- 2333,2340 ---- # define SIG_OK (sig == SIGBUS || sig == SIGSEGV) # define CODE_OK TRUE # endif ! # endif /* IRIX5 || OSF1 || HURD */ ! # if defined(LINUX) # if defined(ALPHA) || defined(M68K) void GC_write_fault_handler(int sig, int code, s_c * sc) *************** SIG_PF GC_old_segv_handler; /* Also old *** 2115,2121 **** # if defined(IA64) || defined(HP_PA) void GC_write_fault_handler(int sig, siginfo_t * si, s_c * scp) # else ! void GC_write_fault_handler(int sig, s_c sc) # endif # endif # define SIG_OK (sig == SIGSEGV) --- 2342,2352 ---- # if defined(IA64) || defined(HP_PA) void GC_write_fault_handler(int sig, siginfo_t * si, s_c * scp) # else ! # if defined(ARM32) ! void GC_write_fault_handler(int sig, int a2, int a3, int a4, s_c sc) ! # else ! void GC_write_fault_handler(int sig, s_c sc) ! # endif # endif # endif # define SIG_OK (sig == SIGSEGV) *************** SIG_PF GC_old_segv_handler; /* Also old *** 2123,2129 **** /* Empirically c.trapno == 14, on IA32, but is that useful? */ /* Should probably consider alignment issues on other */ /* architectures. */ ! # endif # if defined(SUNOS5SIGS) # ifdef __STDC__ void GC_write_fault_handler(int sig, struct SIGINFO *scp, void * context) --- 2354,2361 ---- /* Empirically c.trapno == 14, on IA32, but is that useful? */ /* Should probably consider alignment issues on other */ /* architectures. */ ! # endif /* LINUX */ ! # if defined(SUNOS5SIGS) # ifdef __STDC__ void GC_write_fault_handler(int sig, struct SIGINFO *scp, void * context) *************** SIG_PF GC_old_segv_handler; /* Also old *** 2144,2156 **** # define SIG_OK (sig == SIGSEGV) # define CODE_OK (scp -> si_code == SEGV_ACCERR) # endif ! # endif ! ! # if defined(MACOSX) ! void GC_write_fault_handler(int sig, int code, struct sigcontext *scp) ! # define SIG_OK (sig == SIGBUS) ! # define CODE_OK (code == 0 /* experimentally determined */) ! # endif # if defined(MSWIN32) || defined(MSWINCE) LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info) --- 2376,2382 ---- # define SIG_OK (sig == SIGSEGV) # define CODE_OK (scp -> si_code == SEGV_ACCERR) # endif ! # endif /* SUNOS5SIGS */ # if defined(MSWIN32) || defined(MSWINCE) LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info) *************** SIG_PF GC_old_segv_handler; /* Also old *** 2158,2164 **** STATUS_ACCESS_VIOLATION) # define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] == 1) /* Write fault */ ! # endif { register unsigned i; # if defined(HURD) --- 2384,2390 ---- STATUS_ACCESS_VIOLATION) # define CODE_OK (exc_info -> ExceptionRecord -> ExceptionInformation[0] == 1) /* Write fault */ ! # endif /* MSWIN32 || MSWINCE */ { register unsigned i; # if defined(HURD) *************** SIG_PF GC_old_segv_handler; /* Also old *** 2218,2233 **** # if defined(POWERPC) char * addr = (char *) (sc.regs->dar); # else ! --> architecture not supported # endif # endif # endif # endif # endif # endif - # if defined(MACOSX) - char * addr = get_fault_addr(scp); - # endif # if defined(MSWIN32) || defined(MSWINCE) char * addr = (char *) (exc_info -> ExceptionRecord -> ExceptionInformation[1]); --- 2444,2460 ---- # if defined(POWERPC) char * addr = (char *) (sc.regs->dar); # else ! # if defined(ARM32) ! char * addr = (char *)sc.fault_address; ! # else ! --> architecture not supported ! # endif # endif # endif # endif # endif # endif # endif # if defined(MSWIN32) || defined(MSWINCE) char * addr = (char *) (exc_info -> ExceptionRecord -> ExceptionInformation[1]); *************** SIG_PF GC_old_segv_handler; /* Also old *** 2291,2299 **** (*(REAL_SIG_PF)old_handler) (sig, code, scp); return; # endif - # ifdef MACOSX - (*(REAL_SIG_PF)old_handler) (sig, code, scp); - # endif # ifdef MSWIN32 return((*old_handler)(exc_info)); # endif --- 2518,2523 ---- *************** SIG_PF GC_old_segv_handler; /* Also old *** 2335,2344 **** ABORT("Unexpected bus error or segmentation fault"); #endif } /* * We hold the allocation lock. We expect block h to be written ! * shortly. Ensure that all pages cvontaining any part of the n hblks * starting at h are no longer protected. If is_ptrfree is false, * also ensure that they will subsequently appear to be dirty. */ --- 2559,2569 ---- ABORT("Unexpected bus error or segmentation fault"); #endif } + #endif /* !DARWIN */ /* * We hold the allocation lock. We expect block h to be written ! * shortly. Ensure that all pages containing any part of the n hblks * starting at h are no longer protected. If is_ptrfree is false, * also ensure that they will subsequently appear to be dirty. */ *************** GC_bool is_ptrfree; *** 2367,2372 **** --- 2592,2598 ---- UNPROTECT(h_trunc, (ptr_t)h_end - (ptr_t)h_trunc); } + #if !defined(DARWIN) void GC_dirty_init() { # if defined(SUNOS5SIGS) || defined(IRIX5) || defined(LINUX) || \ *************** void GC_dirty_init() *** 2389,2401 **** (void)sigaddset(&act.sa_mask, SIG_SUSPEND); # endif /* SIG_SUSPEND */ # endif - # if defined(MACOSX) - struct sigaction act, oldact; - - act.sa_flags = SA_RESTART; - act.sa_handler = GC_write_fault_handler; - sigemptyset(&act.sa_mask); - # endif # ifdef PRINTSTATS GC_printf0("Inititalizing mprotect virtual dirty bit implementation\n"); # endif --- 2615,2620 ---- *************** void GC_dirty_init() *** 2435,2443 **** sigaction(SIGSEGV, 0, &oldact); sigaction(SIGSEGV, &act, 0); # else ! sigaction(SIGSEGV, &act, &oldact); # endif ! # if defined(_sigargs) || defined(HURD) /* This is Irix 5.x, not 6.x. Irix 5.x does not have */ /* sa_sigaction. */ GC_old_segv_handler = oldact.sa_handler; --- 2654,2665 ---- sigaction(SIGSEGV, 0, &oldact); sigaction(SIGSEGV, &act, 0); # else ! { ! int res = sigaction(SIGSEGV, &act, &oldact); ! if (res != 0) ABORT("Sigaction failed"); ! } # endif ! # if defined(_sigargs) || defined(HURD) || !defined(SA_SIGINFO) /* This is Irix 5.x, not 6.x. Irix 5.x does not have */ /* sa_sigaction. */ GC_old_segv_handler = oldact.sa_handler; *************** void GC_dirty_init() *** 2458,2464 **** # endif } # endif ! # if defined(MACOSX) || defined(HPUX) || defined(LINUX) || defined(HURD) sigaction(SIGBUS, &act, &oldact); GC_old_bus_handler = oldact.sa_handler; if (GC_old_bus_handler == SIG_IGN) { --- 2680,2686 ---- # endif } # endif ! # if defined(HPUX) || defined(LINUX) || defined(HURD) sigaction(SIGBUS, &act, &oldact); GC_old_bus_handler = oldact.sa_handler; if (GC_old_bus_handler == SIG_IGN) { *************** void GC_dirty_init() *** 2470,2476 **** GC_err_printf0("Replaced other SIGBUS handler\n"); # endif } ! # endif /* MACOS || HPUX || LINUX */ # if defined(MSWIN32) GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler); if (GC_old_segv_handler != NULL) { --- 2692,2698 ---- GC_err_printf0("Replaced other SIGBUS handler\n"); # endif } ! # endif /* HPUX || LINUX || HURD */ # if defined(MSWIN32) GC_old_segv_handler = SetUnhandledExceptionFilter(GC_write_fault_handler); if (GC_old_segv_handler != NULL) { *************** void GC_dirty_init() *** 2482,2487 **** --- 2704,2710 ---- } # endif } + #endif /* !DARWIN */ int GC_incremental_protection_needs() { *************** word len; *** 2628,2642 **** ((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE); } ! #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(THREADS) \ ! && !defined(GC_USE_LD_WRAP) ! /* Replacement for UNIX system call. */ ! /* Other calls that write to the heap should be handled similarly. */ ! /* Note that this doesn't work well for blocking reads: It will hold */ ! /* tha allocation lock for the entur duration of the call. Multithreaded */ ! /* clients should really ensure that it won't block, either by setting */ ! /* the descriptor nonblocking, or by calling select or poll first, to */ ! /* make sure that input is available. */ # if defined(__STDC__) && !defined(SUNOS4) # include # include --- 2851,2873 ---- ((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE); } ! #if 0 ! ! /* We no longer wrap read by default, since that was causing too many */ ! /* problems. It is preferred that the client instead avoids writing */ ! /* to the write-protected heap with a system call. */ ! /* This still serves as sample code if you do want to wrap system calls.*/ ! ! #if !defined(MSWIN32) && !defined(MSWINCE) && !defined(GC_USE_LD_WRAP) ! /* Replacement for UNIX system call. */ ! /* Other calls that write to the heap should be handled similarly. */ ! /* Note that this doesn't work well for blocking reads: It will hold */ ! /* the allocation lock for the entire duration of the call. Multithreaded */ ! /* clients should really ensure that it won't block, either by setting */ ! /* the descriptor nonblocking, or by calling select or poll first, to */ ! /* make sure that input is available. */ ! /* Another, preferred alternative is to ensure that system calls never */ ! /* write to the protected heap (see above). */ # if defined(__STDC__) && !defined(SUNOS4) # include # include *************** word len; *** 2706,2711 **** --- 2937,2944 ---- /* actually calls. */ #endif + #endif /* 0 */ + /*ARGSUSED*/ GC_bool GC_page_was_ever_dirty(h) struct hblk *h; *************** word n; *** 2721,2733 **** { } - # else /* !MPROTECT_VDB */ - - # ifdef GC_USE_LD_WRAP - ssize_t __wrap_read(int fd, void *buf, size_t nbyte) - { return __real_read(fd, buf, nbyte); } - # endif - # endif /* MPROTECT_VDB */ # ifdef PROC_VDB --- 2954,2959 ---- *************** void GC_dirty_init() *** 2806,2811 **** --- 3032,3038 ---- } GC_proc_fd = syscall(SYS_ioctl, fd, PIOCOPENPD, 0); close(fd); + syscall(SYS_fcntl, GC_proc_fd, F_SETFD, FD_CLOEXEC); if (GC_proc_fd < 0) { ABORT("/proc ioctl failed"); } *************** GC_bool is_ptrfree; *** 3045,3050 **** --- 3272,3823 ---- # endif /* PCR_VDB */ + #if defined(MPROTECT_VDB) && defined(DARWIN) + /* The following sources were used as a *reference* for this exception handling + code: + 1. Apple's mach/xnu documentation + 2. Timothy J. Wood's "Mach Exception Handlers 101" post to the + omnigroup's macosx-dev list. + www.omnigroup.com/mailman/archive/macosx-dev/2000-June/002030.html + 3. macosx-nat.c from Apple's GDB source code. + */ + + /* The bug that caused all this trouble should now be fixed. This should + eventually be removed if all goes well. */ + /* define BROKEN_EXCEPTION_HANDLING */ + + #include + #include + #include + #include + #include + #include + + /* These are not defined in any header, although they are documented */ + extern boolean_t exc_server(mach_msg_header_t *,mach_msg_header_t *); + extern kern_return_t exception_raise( + mach_port_t,mach_port_t,mach_port_t, + exception_type_t,exception_data_t,mach_msg_type_number_t); + extern kern_return_t exception_raise_state( + mach_port_t,mach_port_t,mach_port_t, + exception_type_t,exception_data_t,mach_msg_type_number_t, + thread_state_flavor_t*,thread_state_t,mach_msg_type_number_t, + thread_state_t,mach_msg_type_number_t*); + extern kern_return_t exception_raise_state_identity( + mach_port_t,mach_port_t,mach_port_t, + exception_type_t,exception_data_t,mach_msg_type_number_t, + thread_state_flavor_t*,thread_state_t,mach_msg_type_number_t, + thread_state_t,mach_msg_type_number_t*); + + + #define MAX_EXCEPTION_PORTS 16 + + static mach_port_t GC_task_self; + + static struct { + mach_msg_type_number_t count; + exception_mask_t masks[MAX_EXCEPTION_PORTS]; + exception_handler_t ports[MAX_EXCEPTION_PORTS]; + exception_behavior_t behaviors[MAX_EXCEPTION_PORTS]; + thread_state_flavor_t flavors[MAX_EXCEPTION_PORTS]; + } GC_old_exc_ports; + + static struct { + mach_port_t exception; + #if defined(THREADS) + mach_port_t reply; + #endif + } GC_ports; + + typedef struct { + mach_msg_header_t head; + } GC_msg_t; + + typedef enum { + GC_MP_NORMAL, GC_MP_DISCARDING, GC_MP_STOPPED + } GC_mprotect_state_t; + + /* FIXME: 1 and 2 seem to be safe to use in the msgh_id field, + but it isn't documented. Use the source and see if they + should be ok. */ + #define ID_STOP 1 + #define ID_RESUME 2 + + /* These values are only used on the reply port */ + #define ID_ACK 3 + + #if defined(THREADS) + + GC_mprotect_state_t GC_mprotect_state; + + /* The following should ONLY be called when the world is stopped */ + static void GC_mprotect_thread_notify(mach_msg_id_t id) { + struct { + GC_msg_t msg; + mach_msg_trailer_t trailer; + } buf; + mach_msg_return_t r; + /* remote, local */ + buf.msg.head.msgh_bits = + MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND,0); + buf.msg.head.msgh_size = sizeof(buf.msg); + buf.msg.head.msgh_remote_port = GC_ports.exception; + buf.msg.head.msgh_local_port = MACH_PORT_NULL; + buf.msg.head.msgh_id = id; + + r = mach_msg( + &buf.msg.head, + MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_LARGE, + sizeof(buf.msg), + sizeof(buf), + GC_ports.reply, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + if(r != MACH_MSG_SUCCESS) + ABORT("mach_msg failed in GC_mprotect_thread_notify"); + if(buf.msg.head.msgh_id != ID_ACK) + ABORT("invalid ack in GC_mprotect_thread_notify"); + } + + /* Should only be called by the mprotect thread */ + static void GC_mprotect_thread_reply() { + GC_msg_t msg; + mach_msg_return_t r; + /* remote, local */ + msg.head.msgh_bits = + MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND,0); + msg.head.msgh_size = sizeof(msg); + msg.head.msgh_remote_port = GC_ports.reply; + msg.head.msgh_local_port = MACH_PORT_NULL; + msg.head.msgh_id = ID_ACK; + + r = mach_msg( + &msg.head, + MACH_SEND_MSG, + sizeof(msg), + 0, + MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + if(r != MACH_MSG_SUCCESS) + ABORT("mach_msg failed in GC_mprotect_thread_reply"); + } + + void GC_mprotect_stop() { + GC_mprotect_thread_notify(ID_STOP); + } + void GC_mprotect_resume() { + GC_mprotect_thread_notify(ID_RESUME); + } + + #else /* !THREADS */ + /* The compiler should optimize away any GC_mprotect_state computations */ + #define GC_mprotect_state GC_MP_NORMAL + #endif + + static void *GC_mprotect_thread(void *arg) { + mach_msg_return_t r; + /* These two structures contain some private kernel data. We don't need to + access any of it so we don't bother defining a proper struct. The + correct definitions are in the xnu source code. */ + struct { + mach_msg_header_t head; + char data[256]; + } reply; + struct { + mach_msg_header_t head; + mach_msg_body_t msgh_body; + char data[1024]; + } msg; + + mach_msg_id_t id; + + for(;;) { + r = mach_msg( + &msg.head, + MACH_RCV_MSG|MACH_RCV_LARGE| + (GC_mprotect_state == GC_MP_DISCARDING ? MACH_RCV_TIMEOUT : 0), + 0, + sizeof(msg), + GC_ports.exception, + GC_mprotect_state == GC_MP_DISCARDING ? 0 : MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + + id = r == MACH_MSG_SUCCESS ? msg.head.msgh_id : -1; + + #if defined(THREADS) + if(GC_mprotect_state == GC_MP_DISCARDING) { + if(r == MACH_RCV_TIMED_OUT) { + GC_mprotect_state = GC_MP_STOPPED; + GC_mprotect_thread_reply(); + continue; + } + if(r == MACH_MSG_SUCCESS && (id == ID_STOP || id == ID_RESUME)) + ABORT("out of order mprotect thread request"); + } + #endif + + if(r != MACH_MSG_SUCCESS) { + GC_err_printf2("mach_msg failed with %d %s\n", + (int)r,mach_error_string(r)); + ABORT("mach_msg failed"); + } + + switch(id) { + #if defined(THREADS) + case ID_STOP: + if(GC_mprotect_state != GC_MP_NORMAL) + ABORT("Called mprotect_stop when state wasn't normal"); + GC_mprotect_state = GC_MP_DISCARDING; + break; + case ID_RESUME: + if(GC_mprotect_state != GC_MP_STOPPED) + ABORT("Called mprotect_resume when state wasn't stopped"); + GC_mprotect_state = GC_MP_NORMAL; + GC_mprotect_thread_reply(); + break; + #endif /* THREADS */ + default: + /* Handle the message (calls catch_exception_raise) */ + if(!exc_server(&msg.head,&reply.head)) + ABORT("exc_server failed"); + /* Send the reply */ + r = mach_msg( + &reply.head, + MACH_SEND_MSG, + reply.head.msgh_size, + 0, + MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + if(r != MACH_MSG_SUCCESS) { + /* This will fail if the thread dies, but the thread shouldn't + die... */ + #ifdef BROKEN_EXCEPTION_HANDLING + GC_err_printf2( + "mach_msg failed with %d %s while sending exc reply\n", + (int)r,mach_error_string(r)); + #else + ABORT("mach_msg failed while sending exception reply"); + #endif + } + } /* switch */ + } /* for(;;) */ + /* NOT REACHED */ + return NULL; + } + + /* All this SIGBUS code shouldn't be necessary. All protection faults should + be going throught the mach exception handler. However, it seems a SIGBUS is + occasionally sent for some unknown reason. Even more odd, it seems to be + meaningless and safe to ignore. */ + #ifdef BROKEN_EXCEPTION_HANDLING + + typedef void (* SIG_PF)(); + static SIG_PF GC_old_bus_handler; + + /* Updates to this aren't atomic, but the SIGBUSs seem pretty rare. + Even if this doesn't get updated property, it isn't really a problem */ + static int GC_sigbus_count; + + static void GC_darwin_sigbus(int num,siginfo_t *sip,void *context) { + if(num != SIGBUS) ABORT("Got a non-sigbus signal in the sigbus handler"); + + /* Ugh... some seem safe to ignore, but too many in a row probably means + trouble. GC_sigbus_count is reset for each mach exception that is + handled */ + if(GC_sigbus_count >= 8) { + ABORT("Got more than 8 SIGBUSs in a row!"); + } else { + GC_sigbus_count++; + GC_err_printf0("GC: WARNING: Ignoring SIGBUS.\n"); + } + } + #endif /* BROKEN_EXCEPTION_HANDLING */ + + void GC_dirty_init() { + kern_return_t r; + mach_port_t me; + pthread_t thread; + pthread_attr_t attr; + exception_mask_t mask; + + # ifdef PRINTSTATS + GC_printf0("Inititalizing mach/darwin mprotect virtual dirty bit " + "implementation\n"); + # endif + # ifdef BROKEN_EXCEPTION_HANDLING + GC_err_printf0("GC: WARNING: Enabling workarounds for various darwin " + "exception handling bugs.\n"); + # endif + GC_dirty_maintained = TRUE; + if (GC_page_size % HBLKSIZE != 0) { + GC_err_printf0("Page size not multiple of HBLKSIZE\n"); + ABORT("Page size not multiple of HBLKSIZE"); + } + + GC_task_self = me = mach_task_self(); + + r = mach_port_allocate(me,MACH_PORT_RIGHT_RECEIVE,&GC_ports.exception); + if(r != KERN_SUCCESS) ABORT("mach_port_allocate failed (exception port)"); + + r = mach_port_insert_right(me,GC_ports.exception,GC_ports.exception, + MACH_MSG_TYPE_MAKE_SEND); + if(r != KERN_SUCCESS) + ABORT("mach_port_insert_right failed (exception port)"); + + #if defined(THREADS) + r = mach_port_allocate(me,MACH_PORT_RIGHT_RECEIVE,&GC_ports.reply); + if(r != KERN_SUCCESS) ABORT("mach_port_allocate failed (reply port)"); + #endif + + /* The exceptions we want to catch */ + mask = EXC_MASK_BAD_ACCESS; + + r = task_get_exception_ports( + me, + mask, + GC_old_exc_ports.masks, + &GC_old_exc_ports.count, + GC_old_exc_ports.ports, + GC_old_exc_ports.behaviors, + GC_old_exc_ports.flavors + ); + if(r != KERN_SUCCESS) ABORT("task_get_exception_ports failed"); + + r = task_set_exception_ports( + me, + mask, + GC_ports.exception, + EXCEPTION_DEFAULT, + MACHINE_THREAD_STATE + ); + if(r != KERN_SUCCESS) ABORT("task_set_exception_ports failed"); + + if(pthread_attr_init(&attr) != 0) ABORT("pthread_attr_init failed"); + if(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED) != 0) + ABORT("pthread_attr_setdetachedstate failed"); + + # undef pthread_create + /* This will call the real pthread function, not our wrapper */ + if(pthread_create(&thread,&attr,GC_mprotect_thread,NULL) != 0) + ABORT("pthread_create failed"); + pthread_attr_destroy(&attr); + + /* Setup the sigbus handler for ignoring the meaningless SIGBUSs */ + #ifdef BROKEN_EXCEPTION_HANDLING + { + struct sigaction sa, oldsa; + sa.sa_handler = (SIG_PF)GC_darwin_sigbus; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART|SA_SIGINFO; + if(sigaction(SIGBUS,&sa,&oldsa) < 0) ABORT("sigaction"); + GC_old_bus_handler = (SIG_PF)oldsa.sa_handler; + if (GC_old_bus_handler != SIG_DFL) { + # ifdef PRINTSTATS + GC_err_printf0("Replaced other SIGBUS handler\n"); + # endif + } + } + #endif /* BROKEN_EXCEPTION_HANDLING */ + } + + /* The source code for Apple's GDB was used as a reference for the exception + forwarding code. This code is similar to be GDB code only because there is + only one way to do it. */ + static kern_return_t GC_forward_exception( + mach_port_t thread, + mach_port_t task, + exception_type_t exception, + exception_data_t data, + mach_msg_type_number_t data_count + ) { + int i; + kern_return_t r; + mach_port_t port; + exception_behavior_t behavior; + thread_state_flavor_t flavor; + + thread_state_data_t thread_state; + mach_msg_type_number_t thread_state_count = THREAD_STATE_MAX; + + for(i=0;i 0 ? code[0] : -1, + code_count > 1 ? code[1] : -1); + #endif + return FWD(); + } + + r = thread_get_state(thread,flavor, + (natural_t*)&exc_state,&exc_state_count); + if(r != KERN_SUCCESS) { + /* The thread is supposed to be suspended while the exception handler + is called. This shouldn't fail. */ + #ifdef BROKEN_EXCEPTION_HANDLING + GC_err_printf0("thread_get_state failed in " + "catch_exception_raise\n"); + return KERN_SUCCESS; + #else + ABORT("thread_get_state failed in catch_exception_raise"); + #endif + } + + /* This is the address that caused the fault */ + addr = (char*) exc_state.dar; + + if((HDR(addr)) == 0) { + /* Ugh... just like the SIGBUS problem above, it seems we get a bogus + KERN_PROTECTION_FAILURE every once and a while. We wait till we get + a bunch in a row before doing anything about it. If a "real" fault + ever occurres it'll just keep faulting over and over and we'll hit + the limit pretty quickly. */ + #ifdef BROKEN_EXCEPTION_HANDLING + static char *last_fault; + static int last_fault_count; + + if(addr != last_fault) { + last_fault = addr; + last_fault_count = 0; + } + if(++last_fault_count < 32) { + if(last_fault_count == 1) + GC_err_printf1( + "GC: WARNING: Ignoring KERN_PROTECTION_FAILURE at %p\n", + addr); + return KERN_SUCCESS; + } + + GC_err_printf1("Unexpected KERN_PROTECTION_FAILURE at %p\n",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. */ + GC_err_printf0("Aborting\n"); + exit(EXIT_FAILURE); + #else /* BROKEN_EXCEPTION_HANDLING */ + /* Pass it along to the next exception handler + (which should call SIGBUS/SIGSEGV) */ + return FWD(); + #endif /* !BROKEN_EXCEPTION_HANDLING */ + } + + #ifdef BROKEN_EXCEPTION_HANDLING + /* Reset the number of consecutive SIGBUSs */ + GC_sigbus_count = 0; + #endif + + if(GC_mprotect_state == GC_MP_NORMAL) { /* common case */ + h = (struct hblk*)((word)addr & ~(GC_page_size-1)); + UNPROTECT(h, GC_page_size); + for (i = 0; i < divHBLKSZ(GC_page_size); i++) { + register int index = PHT_HASH(h+i); + async_set_pht_entry_from_index(GC_dirty_pages, index); + } + } else if(GC_mprotect_state == GC_MP_DISCARDING) { + /* Lie to the thread for now. No sense UNPROTECT()ing the memory + when we're just going to PROTECT() it again later. The thread + will just fault again once it resumes */ + } else { + /* Shouldn't happen, i don't think */ + GC_printf0("KERN_PROTECTION_FAILURE while world is stopped\n"); + return FWD(); + } + return KERN_SUCCESS; + } + #undef FWD + + /* These should never be called, but just in case... */ + kern_return_t catch_exception_raise_state(mach_port_name_t exception_port, + int exception, exception_data_t code, mach_msg_type_number_t codeCnt, + int flavor, thread_state_t old_state, int old_stateCnt, + thread_state_t new_state, int new_stateCnt) + { + ABORT("catch_exception_raise_state"); + return(KERN_INVALID_ARGUMENT); + } + kern_return_t catch_exception_raise_state_identity( + mach_port_name_t exception_port, mach_port_t thread, mach_port_t task, + int exception, exception_data_t code, mach_msg_type_number_t codeCnt, + int flavor, thread_state_t old_state, int old_stateCnt, + thread_state_t new_state, int new_stateCnt) + { + ABORT("catch_exception_raise_state_identity"); + return(KERN_INVALID_ARGUMENT); + } + + + #endif /* DARWIN && MPROTECT_VDB */ + # ifndef HAVE_INCREMENTAL_PROTECTION_NEEDS int GC_incremental_protection_needs() { *************** GC_bool is_ptrfree; *** 3105,3123 **** # endif #endif /* SPARC */ ! #ifdef SAVE_CALL_CHAIN /* Fill in the pc and argument information for up to NFRAMES of my */ /* callers. Ignore my frame and my callers frame. */ #ifdef LINUX ! # include ! # if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2 ! # define HAVE_BUILTIN_BACKTRACE ! # endif #endif #if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \ ! && defined(HAVE_BUILTIN_BACKTRACE) #include --- 3878,3897 ---- # endif #endif /* SPARC */ ! #ifdef NEED_CALLINFO /* Fill in the pc and argument information for up to NFRAMES of my */ /* callers. Ignore my frame and my callers frame. */ #ifdef LINUX ! # include #endif + #endif /* NEED_CALLINFO */ + + #ifdef SAVE_CALL_CHAIN + #if NARGS == 0 && NFRAMES % 2 == 0 /* No padding */ \ ! && defined(GC_HAVE_BUILTIN_BACKTRACE) #include *************** struct callinfo info[NFRAMES]; *** 3163,3170 **** asm("movl %%ebp,%0" : "=r"(frame)); fp = frame; # else - word GC_save_regs_in_stack(); - frame = (struct frame *) GC_save_regs_in_stack (); fp = (struct frame *)((long) frame -> FR_SAVFP + BIAS); #endif --- 3937,3942 ---- *************** struct callinfo info[NFRAMES]; *** 3188,3218 **** #endif /* SAVE_CALL_CHAIN */ ! #if defined(LINUX) && defined(__ELF__) && \ ! (!defined(SMALL_CONFIG) || defined(USE_PROC_FOR_LIBRARIES)) ! #ifdef GC_USE_LD_WRAP ! # define READ __real_read ! #else ! # define READ read ! #endif ! ! /* Repeatedly perform a read call until the buffer is filled or */ ! /* we encounter EOF. */ ! ssize_t GC_repeat_read(int fd, char *buf, size_t count) { ! ssize_t num_read = 0; ! ssize_t result; ! while (num_read < count) { ! result = READ(fd, buf + num_read, count - num_read); ! if (result < 0) return result; ! if (result == 0) break; ! num_read += result; } ! return num_read; } ! #endif /* LINUX && ... */ #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) --- 3960,4098 ---- #endif /* SAVE_CALL_CHAIN */ ! #ifdef NEED_CALLINFO ! /* Print info to stderr. We do NOT hold the allocation lock */ ! void GC_print_callers (info) ! struct callinfo info[NFRAMES]; { ! register int i; ! static int reentry_count = 0; ! GC_bool stop = FALSE; ! ! LOCK(); ! ++reentry_count; ! UNLOCK(); ! # if NFRAMES == 1 ! GC_err_printf0("\tCaller at allocation:\n"); ! # else ! GC_err_printf0("\tCall chain at allocation:\n"); ! # endif ! for (i = 0; i < NFRAMES && !stop ; i++) { ! if (info[i].ci_pc == 0) break; ! # if NARGS > 0 ! { ! int j; ! ! GC_err_printf0("\t\targs: "); ! for (j = 0; j < NARGS; j++) { ! if (j != 0) GC_err_printf0(", "); ! GC_err_printf2("%d (0x%X)", ~(info[i].ci_arg[j]), ! ~(info[i].ci_arg[j])); ! } ! GC_err_printf0("\n"); ! } ! # endif ! if (reentry_count > 1) { ! /* We were called during an allocation during */ ! /* a previous GC_print_callers call; punt. */ ! GC_err_printf1("\t\t##PC##= 0x%lx\n", info[i].ci_pc); ! continue; ! } ! { ! # ifdef LINUX ! FILE *pipe; ! # endif ! # if defined(GC_HAVE_BUILTIN_BACKTRACE) ! char **sym_name = ! backtrace_symbols((void **)(&(info[i].ci_pc)), 1); ! char *name = sym_name[0]; ! # else ! char buf[40]; ! char *name = buf; ! sprintf(buf, "##PC##= 0x%lx", info[i].ci_pc); ! # endif ! # if defined(LINUX) && !defined(SMALL_CONFIG) ! /* Try for a line number. */ ! { ! # define EXE_SZ 100 ! static char exe_name[EXE_SZ]; ! # define CMD_SZ 200 ! char cmd_buf[CMD_SZ]; ! # define RESULT_SZ 200 ! static char result_buf[RESULT_SZ]; ! size_t result_len; ! static GC_bool found_exe_name = FALSE; ! static GC_bool will_fail = FALSE; ! int ret_code; ! /* Try to get it via a hairy and expensive scheme. */ ! /* First we get the name of the executable: */ ! if (will_fail) goto out; ! if (!found_exe_name) { ! ret_code = readlink("/proc/self/exe", exe_name, EXE_SZ); ! if (ret_code < 0 || ret_code >= EXE_SZ ! || exe_name[0] != '/') { ! will_fail = TRUE; /* Dont try again. */ ! goto out; ! } ! exe_name[ret_code] = '\0'; ! found_exe_name = TRUE; ! } ! /* Then we use popen to start addr2line -e */ ! /* There are faster ways to do this, but hopefully this */ ! /* isn't time critical. */ ! sprintf(cmd_buf, "/usr/bin/addr2line -f -e %s 0x%lx", exe_name, ! (unsigned long)info[i].ci_pc); ! pipe = popen(cmd_buf, "r"); ! if (pipe == NULL ! || (result_len = fread(result_buf, 1, RESULT_SZ - 1, pipe)) ! == 0) { ! if (pipe != NULL) pclose(pipe); ! will_fail = TRUE; ! goto out; ! } ! if (result_buf[result_len - 1] == '\n') --result_len; ! result_buf[result_len] = 0; ! if (result_buf[0] == '?' ! || result_buf[result_len-2] == ':' ! && result_buf[result_len-1] == '0') { ! pclose(pipe); ! goto out; ! } ! /* Get rid of embedded newline, if any. Test for "main" */ ! { ! char * nl = strchr(result_buf, '\n'); ! if (nl != NULL && nl < result_buf + result_len) { ! *nl = ':'; ! } ! if (strncmp(result_buf, "main", nl - result_buf) == 0) { ! stop = TRUE; ! } ! } ! if (result_len < RESULT_SZ - 25) { ! /* Add in hex address */ ! sprintf(result_buf + result_len, " [0x%lx]", ! (unsigned long)info[i].ci_pc); ! } ! name = result_buf; ! pclose(pipe); ! out:; ! } ! # endif /* LINUX */ ! GC_err_printf1("\t\t%s\n", name); ! # if defined(GC_HAVE_BUILTIN_BACKTRACE) ! free(sym_name); /* May call GC_free; that's OK */ ! # endif ! } } ! LOCK(); ! --reentry_count; ! UNLOCK(); } ! ! #endif /* NEED_CALLINFO */ ! #if defined(LINUX) && defined(__ELF__) && !defined(SMALL_CONFIG) *************** ssize_t GC_repeat_read(int fd, char *buf *** 3220,3239 **** /* Dump /proc/self/maps to GC_stderr, to enable looking up names for addresses in FIND_LEAK output. */ void GC_print_address_map() { - int f; - int result; - char maps_temp[32768]; GC_err_printf0("---------- Begin address map ----------\n"); ! f = open("/proc/self/maps", O_RDONLY); ! if (-1 == f) ABORT("Couldn't open /proc/self/maps"); ! do { ! result = GC_repeat_read(f, maps_temp, sizeof(maps_temp)); ! if (result <= 0) ABORT("Couldn't read /proc/self/maps"); ! GC_err_write(maps_temp, result); ! } while (result == sizeof(maps_temp)); ! GC_err_printf0("---------- End address map ----------\n"); } --- 4100,4115 ---- /* Dump /proc/self/maps to GC_stderr, to enable looking up names for addresses in FIND_LEAK output. */ + static word dump_maps(char *maps) + { + GC_err_write(maps, strlen(maps)); + return 1; + } + void GC_print_address_map() { GC_err_printf0("---------- Begin address map ----------\n"); ! GC_apply_to_maps(dump_maps); GC_err_printf0("---------- End address map ----------\n"); } diff -Nrc3pad gcc-3.3.3/boehm-gc/powerpc_darwin_mach_dep.s gcc-3.4.0/boehm-gc/powerpc_darwin_mach_dep.s *** gcc-3.3.3/boehm-gc/powerpc_darwin_mach_dep.s 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/powerpc_darwin_mach_dep.s 2003-07-28 03:46:10.000000000 +0000 *************** *** 0 **** --- 1,84 ---- + + ; GC_push_regs function. Under some optimization levels GCC will clobber + ; some of the non-volatile registers before we get a chance to save them + ; therefore, this can't be inline asm. + + .text + .align 2 + .globl _GC_push_regs + _GC_push_regs: + + ; Prolog + mflr r0 + stw r0,8(r1) + stwu r1,-80(r1) + + ; Push r13-r31 + mr r3,r13 + bl L_GC_push_one$stub + mr r3,r14 + bl L_GC_push_one$stub + mr r3,r15 + bl L_GC_push_one$stub + mr r3,r16 + bl L_GC_push_one$stub + mr r3,r17 + bl L_GC_push_one$stub + mr r3,r18 + bl L_GC_push_one$stub + mr r3,r19 + bl L_GC_push_one$stub + mr r3,r20 + bl L_GC_push_one$stub + mr r3,r21 + bl L_GC_push_one$stub + mr r3,r22 + bl L_GC_push_one$stub + mr r3,r23 + bl L_GC_push_one$stub + mr r3,r24 + bl L_GC_push_one$stub + mr r3,r25 + bl L_GC_push_one$stub + mr r3,r26 + bl L_GC_push_one$stub + mr r3,r27 + bl L_GC_push_one$stub + mr r3,r28 + bl L_GC_push_one$stub + mr r3,r29 + bl L_GC_push_one$stub + mr r3,r30 + bl L_GC_push_one$stub + mr r3,r31 + bl L_GC_push_one$stub + + ; + lwz r0,88(r1) + addi r1,r1,80 + mtlr r0 + + ; Return + blr + + ; PIC stuff, generated by GCC + + .data + .picsymbol_stub + L_GC_push_one$stub: + .indirect_symbol _GC_push_one + mflr r0 + bcl 20,31,L0$_GC_push_one + L0$_GC_push_one: + mflr r11 + addis r11,r11,ha16(L_GC_push_one$lazy_ptr-L0$_GC_push_one) + mtlr r0 + lwz r12,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)(r11) + mtctr r12 + addi r11,r11,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one) + bctr + .data + .lazy_symbol_pointer + L_GC_push_one$lazy_ptr: + .indirect_symbol _GC_push_one + .long dyld_stub_binding_helper diff -Nrc3pad gcc-3.3.3/boehm-gc/powerpc_macosx_mach_dep.s gcc-3.4.0/boehm-gc/powerpc_macosx_mach_dep.s *** gcc-3.3.3/boehm-gc/powerpc_macosx_mach_dep.s 2001-08-18 01:04:43.000000000 +0000 --- gcc-3.4.0/boehm-gc/powerpc_macosx_mach_dep.s 1970-01-01 00:00:00.000000000 +0000 *************** *** 1,95 **** - - .text - - .set linkageArea,24 - .set params,4 - .set alignment,4 - - .set spaceToSave,linkageArea+params+alignment - .set spaceToSave8,spaceToSave+8 - - ; Mark from machine registers that are saved by C compiler - .globl _GC_push_regs - _GC_push_regs: - ; PROLOG - mflr r0 ; get return address - stw r0,8(r1) ; save return address - stwu r1,-spaceToSave(r1) ; skip over caller save area - ; - mr r3,r2 ; mark from r2. Well Im not really sure - ; that this is necessary or even the right - ; thing to do - at least it doesnt harm... - ; According to Apples docs it points to - ; the direct data area, whatever that is... - bl L_GC_push_one$stub - mr r3,r13 ; mark from r13-r31 - bl L_GC_push_one$stub - mr r3,r14 - bl L_GC_push_one$stub - mr r3,r15 - bl L_GC_push_one$stub - mr r3,r16 - bl L_GC_push_one$stub - mr r3,r17 - bl L_GC_push_one$stub - mr r3,r18 - bl L_GC_push_one$stub - mr r3,r19 - bl L_GC_push_one$stub - mr r3,r20 - bl L_GC_push_one$stub - mr r3,r21 - bl L_GC_push_one$stub - mr r3,r22 - bl L_GC_push_one$stub - mr r3,r23 - bl L_GC_push_one$stub - mr r3,r24 - bl L_GC_push_one$stub - mr r3,r25 - bl L_GC_push_one$stub - mr r3,r26 - bl L_GC_push_one$stub - mr r3,r27 - bl L_GC_push_one$stub - mr r3,r28 - bl L_GC_push_one$stub - mr r3,r29 - bl L_GC_push_one$stub - mr r3,r30 - bl L_GC_push_one$stub - mr r3,r31 - bl L_GC_push_one$stub - ; EPILOG - lwz r0,spaceToSave8(r1) ; get return address back - mtlr r0 ; reset link register - addic r1,r1,spaceToSave ; restore stack pointer - blr - - .data - .picsymbol_stub - L_GC_push_one$stub: - .indirect_symbol _GC_push_one - mflr r0 - bcl 20,31,L0$_GC_push_one - L0$_GC_push_one: - mflr r11 - addis r11,r11,ha16(L_GC_push_one$lazy_ptr-L0$_GC_push_one) - mtlr r0 - lwz r12,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one)(r11) - mtctr r12 - addi r11,r11,lo16(L_GC_push_one$lazy_ptr-L0$_GC_push_one) - bctr - .data - .lazy_symbol_pointer - L_GC_push_one$lazy_ptr: - .indirect_symbol _GC_push_one - .long dyld_stub_binding_helper - .non_lazy_symbol_pointer - L_GC_push_one$non_lazy_ptr: - .indirect_symbol _GC_push_one - .long 0 - - - - --- 0 ---- diff -Nrc3pad gcc-3.3.3/boehm-gc/pthread_stop_world.c gcc-3.4.0/boehm-gc/pthread_stop_world.c *** gcc-3.3.3/boehm-gc/pthread_stop_world.c 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/pthread_stop_world.c 2003-07-28 03:46:09.000000000 +0000 *************** *** 0 **** --- 1,445 ---- + #include "private/pthread_support.h" + + #if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ + && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) \ + && !defined(GC_DARWIN_THREADS) && !defined(GC_AIX_THREADS) + + #include + #include + #include + #include + + #if DEBUG_THREADS + + #ifndef NSIG + # if defined(MAXSIG) + # define NSIG (MAXSIG+1) + # elif defined(_NSIG) + # define NSIG _NSIG + # elif defined(__SIGRTMAX) + # define NSIG (__SIGRTMAX+1) + # else + --> please fix it + # endif + #endif + + void GC_print_sig_mask() + { + sigset_t blocked; + int i; + + if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0) + ABORT("pthread_sigmask"); + GC_printf0("Blocked: "); + for (i = 1; i < NSIG; i++) { + if (sigismember(&blocked, i)) { GC_printf1("%ld ",(long) i); } + } + GC_printf0("\n"); + } + + #endif + + word GC_stop_count; /* Incremented at the beginning of GC_stop_world. */ + + #ifdef GC_OSF1_THREADS + GC_bool GC_retry_signals = TRUE; + #else + GC_bool GC_retry_signals = FALSE; + #endif + + /* + * We use signals to stop threads during GC. + * + * Suspended threads wait in signal handler for SIG_THR_RESTART. + * That's more portable than semaphores or condition variables. + * (We do use sem_post from a signal handler, but that should be portable.) + * + * The thread suspension signal SIG_SUSPEND is now defined in gc_priv.h. + * Note that we can't just stop a thread; we need it to save its stack + * pointer(s) and acknowledge. + */ + + #ifndef SIG_THR_RESTART + # if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) + # ifdef _SIGRTMIN + # define SIG_THR_RESTART _SIGRTMIN + 5 + # else + # define SIG_THR_RESTART SIGRTMIN + 5 + # endif + # else + # define SIG_THR_RESTART SIGXCPU + # endif + #endif + + sem_t GC_suspend_ack_sem; + + void GC_suspend_handler(int sig) + { + int dummy; + pthread_t my_thread = pthread_self(); + GC_thread me; + sigset_t mask; + # ifdef PARALLEL_MARK + word my_mark_no = GC_mark_no; + /* Marker can't proceed until we acknowledge. Thus this is */ + /* guaranteed to be the mark_no correspending to our */ + /* suspension, i.e. the marker can't have incremented it yet. */ + # endif + word my_stop_count = GC_stop_count; + + if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler"); + + #if DEBUG_THREADS + GC_printf1("Suspending 0x%lx\n", my_thread); + #endif + + me = GC_lookup_thread(my_thread); + /* The lookup here is safe, since I'm doing this on behalf */ + /* of a thread which holds the allocation lock in order */ + /* to stop the world. Thus concurrent modification of the */ + /* data structure is impossible. */ + if (me -> stop_info.last_stop_count == my_stop_count) { + /* Duplicate signal. OK if we are retrying. */ + if (!GC_retry_signals) { + WARN("Duplicate suspend signal in thread %lx\n", + pthread_self()); + } + return; + } + # ifdef SPARC + me -> stop_info.stack_ptr = (ptr_t)GC_save_regs_in_stack(); + # else + me -> stop_info.stack_ptr = (ptr_t)(&dummy); + # endif + # ifdef IA64 + me -> backing_store_ptr = (ptr_t)GC_save_regs_in_stack(); + # endif + + /* Tell the thread that wants to stop the world that this */ + /* 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; + + /* Wait until that thread tells us to restart by sending */ + /* this thread a SIG_THR_RESTART signal. */ + /* SIG_THR_RESTART should be masked at this point. Thus there */ + /* is no race. */ + if (sigfillset(&mask) != 0) ABORT("sigfillset() failed"); + if (sigdelset(&mask, SIG_THR_RESTART) != 0) ABORT("sigdelset() failed"); + # ifdef NO_SIGNALS + if (sigdelset(&mask, SIGINT) != 0) ABORT("sigdelset() failed"); + if (sigdelset(&mask, SIGQUIT) != 0) ABORT("sigdelset() failed"); + if (sigdelset(&mask, SIGTERM) != 0) ABORT("sigdelset() failed"); + if (sigdelset(&mask, SIGABRT) != 0) ABORT("sigdelset() failed"); + # endif + do { + me->stop_info.signal = 0; + sigsuspend(&mask); /* Wait for signal */ + } while (me->stop_info.signal != SIG_THR_RESTART); + /* If the RESTART signal gets lost, we can still lose. That should be */ + /* less likely than losing the SUSPEND signal, since we don't do much */ + /* between the sem_post and sigsuspend. */ + /* We'd need more handshaking to work around that, since we don't want */ + /* to accidentally leave a RESTART signal pending, thus causing us to */ + /* continue prematurely in a future round. */ + + #if DEBUG_THREADS + GC_printf1("Continuing 0x%lx\n", my_thread); + #endif + } + + void GC_restart_handler(int sig) + { + pthread_t my_thread = pthread_self(); + GC_thread me; + + if (sig != SIG_THR_RESTART) ABORT("Bad signal in suspend_handler"); + + /* Let the GC_suspend_handler() know that we got a SIG_THR_RESTART. */ + /* The lookup here is safe, since I'm doing this on behalf */ + /* of a thread which holds the allocation lock in order */ + /* to stop the world. Thus concurrent modification of the */ + /* data structure is impossible. */ + me = GC_lookup_thread(my_thread); + me->stop_info.signal = SIG_THR_RESTART; + + /* + ** Note: even if we didn't do anything useful here, + ** it would still be necessary to have a signal handler, + ** rather than ignoring the signals, otherwise + ** the signals will not be delivered at all, and + ** will thus not interrupt the sigsuspend() above. + */ + + #if DEBUG_THREADS + GC_printf1("In GC_restart_handler for 0x%lx\n", pthread_self()); + #endif + } + + # ifdef IA64 + # define IF_IA64(x) x + # else + # define IF_IA64(x) + # endif + /* We hold allocation lock. Should do exactly the right thing if the */ + /* world is stopped. Should not fail if it isn't. */ + void GC_push_all_stacks() + { + int i; + GC_thread p; + ptr_t lo, hi; + /* On IA64, we also need to scan the register backing store. */ + IF_IA64(ptr_t bs_lo; ptr_t bs_hi;) + pthread_t me = pthread_self(); + + if (!GC_thr_initialized) GC_thr_init(); + #if DEBUG_THREADS + GC_printf1("Pushing stacks from thread 0x%lx\n", (unsigned long) me); + #endif + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + if (p -> flags & FINISHED) continue; + if (pthread_equal(p -> id, me)) { + # ifdef SPARC + lo = (ptr_t)GC_save_regs_in_stack(); + # else + lo = GC_approx_sp(); + # endif + IF_IA64(bs_hi = (ptr_t)GC_save_regs_in_stack();) + } else { + lo = p -> stop_info.stack_ptr; + IF_IA64(bs_hi = p -> backing_store_ptr;) + } + if ((p -> flags & MAIN_THREAD) == 0) { + hi = p -> stack_end; + IF_IA64(bs_lo = p -> backing_store_end); + } else { + /* The original stack. */ + hi = GC_stackbottom; + IF_IA64(bs_lo = BACKING_STORE_BASE;) + } + #if DEBUG_THREADS + GC_printf3("Stack for thread 0x%lx = [%lx,%lx)\n", + (unsigned long) p -> id, + (unsigned long) lo, (unsigned long) hi); + #endif + if (0 == lo) ABORT("GC_push_all_stacks: sp not set!\n"); + # ifdef STACK_GROWS_UP + /* We got them backwards! */ + GC_push_all_stack(hi, lo); + # else + GC_push_all_stack(lo, hi); + # endif + # ifdef IA64 + if (pthread_equal(p -> id, me)) { + GC_push_all_eager(bs_lo, bs_hi); + } else { + GC_push_all_stack(bs_lo, bs_hi); + } + # endif + } + } + } + + /* There seems to be a very rare thread stopping problem. To help us */ + /* debug that, we save the ids of the stopping thread. */ + pthread_t GC_stopping_thread; + int GC_stopping_pid; + + /* We hold the allocation lock. Suspend all threads that might */ + /* still be running. Return the number of suspend signals that */ + /* were sent. */ + int GC_suspend_all() + { + int n_live_threads = 0; + int i; + GC_thread p; + int result; + pthread_t my_thread = pthread_self(); + + GC_stopping_thread = my_thread; /* debugging only. */ + GC_stopping_pid = getpid(); /* debugging only. */ + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + if (p -> id != my_thread) { + if (p -> flags & FINISHED) continue; + if (p -> stop_info.last_stop_count == GC_stop_count) continue; + if (p -> thread_blocked) /* Will wait */ continue; + n_live_threads++; + #if DEBUG_THREADS + GC_printf1("Sending suspend signal to 0x%lx\n", p -> id); + #endif + + result = pthread_kill(p -> id, SIG_SUSPEND); + switch(result) { + case ESRCH: + /* Not really there anymore. Possible? */ + n_live_threads--; + break; + case 0: + break; + default: + ABORT("pthread_kill failed"); + } + } + } + } + return n_live_threads; + } + + /* Caller holds allocation lock. */ + void GC_stop_world() + { + int i; + int n_live_threads; + int code; + + #if DEBUG_THREADS + GC_printf1("Stopping the world from 0x%lx\n", pthread_self()); + #endif + + /* Make sure all free list construction has stopped before we start. */ + /* No new construction can start, since free list construction is */ + /* required to acquire and release the GC lock before it starts, */ + /* and we have the lock. */ + # ifdef PARALLEL_MARK + GC_acquire_mark_lock(); + GC_ASSERT(GC_fl_builder_count == 0); + /* We should have previously waited for it to become zero. */ + # endif /* PARALLEL_MARK */ + ++GC_stop_count; + n_live_threads = GC_suspend_all(); + + if (GC_retry_signals) { + unsigned long wait_usecs = 0; /* Total wait since retry. */ + # define WAIT_UNIT 3000 + # define RETRY_INTERVAL 100000 + for (;;) { + int ack_count; + + sem_getvalue(&GC_suspend_ack_sem, &ack_count); + if (ack_count == n_live_threads) break; + if (wait_usecs > RETRY_INTERVAL) { + int newly_sent = GC_suspend_all(); + + # ifdef CONDPRINT + if (GC_print_stats) { + GC_printf1("Resent %ld signals after timeout\n", + newly_sent); + } + # endif + sem_getvalue(&GC_suspend_ack_sem, &ack_count); + if (newly_sent < n_live_threads - ack_count) { + WARN("Lost some threads during GC_stop_world?!\n",0); + n_live_threads = ack_count + newly_sent; + } + wait_usecs = 0; + } + usleep(WAIT_UNIT); + wait_usecs += WAIT_UNIT; + } + } + for (i = 0; i < n_live_threads; i++) { + if (0 != (code = sem_wait(&GC_suspend_ack_sem))) { + GC_err_printf1("Sem_wait returned %ld\n", (unsigned long)code); + ABORT("sem_wait for handler failed"); + } + } + # ifdef PARALLEL_MARK + GC_release_mark_lock(); + # endif + #if DEBUG_THREADS + GC_printf1("World stopped from 0x%lx\n", pthread_self()); + #endif + GC_stopping_thread = 0; /* debugging only */ + } + + /* Caller holds allocation lock, and has held it continuously since */ + /* the world stopped. */ + void GC_start_world() + { + pthread_t my_thread = pthread_self(); + register int i; + register GC_thread p; + register int n_live_threads = 0; + register int result; + + # if DEBUG_THREADS + GC_printf0("World starting\n"); + # endif + + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + if (p -> id != my_thread) { + if (p -> flags & FINISHED) continue; + if (p -> thread_blocked) continue; + n_live_threads++; + #if DEBUG_THREADS + GC_printf1("Sending restart signal to 0x%lx\n", p -> id); + #endif + + result = pthread_kill(p -> id, SIG_THR_RESTART); + switch(result) { + case ESRCH: + /* Not really there anymore. Possible? */ + n_live_threads--; + break; + case 0: + break; + default: + ABORT("pthread_kill failed"); + } + } + } + } + #if DEBUG_THREADS + GC_printf0("World started\n"); + #endif + } + + void GC_stop_init() { + struct sigaction act; + + if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0) + ABORT("sem_init failed"); + + act.sa_flags = SA_RESTART; + if (sigfillset(&act.sa_mask) != 0) { + ABORT("sigfillset() failed"); + } + # ifdef NO_SIGNALS + if (sigdelset(&act.sa_mask, SIGINT) != 0 + || sigdelset(&act.sa_mask, SIGQUIT != 0) + || sigdelset(&act.sa_mask, SIGABRT != 0) + || sigdelset(&act.sa_mask, SIGTERM != 0)) { + ABORT("sigdelset() failed"); + } + # endif + + /* SIG_THR_RESTART is unmasked by the handler when necessary. */ + act.sa_handler = GC_suspend_handler; + if (sigaction(SIG_SUSPEND, &act, NULL) != 0) { + ABORT("Cannot set SIG_SUSPEND handler"); + } + + act.sa_handler = GC_restart_handler; + if (sigaction(SIG_THR_RESTART, &act, NULL) != 0) { + ABORT("Cannot set SIG_THR_RESTART handler"); + } + + /* Check for GC_RETRY_SIGNALS. */ + if (0 != GETENV("GC_RETRY_SIGNALS")) { + GC_retry_signals = TRUE; + } + if (0 != GETENV("GC_NO_RETRY_SIGNALS")) { + GC_retry_signals = FALSE; + } + # ifdef CONDPRINT + if (GC_print_stats && GC_retry_signals) { + GC_printf0("Will retry suspend signal if necessary.\n"); + } + # endif + } + + #endif diff -Nrc3pad gcc-3.3.3/boehm-gc/pthread_support.c gcc-3.4.0/boehm-gc/pthread_support.c *** gcc-3.3.3/boehm-gc/pthread_support.c 1970-01-01 00:00:00.000000000 +0000 --- gcc-3.4.0/boehm-gc/pthread_support.c 2003-07-28 03:46:09.000000000 +0000 *************** *** 0 **** --- 1,1570 ---- + /* + * Copyright (c) 1994 by Xerox Corporation. All rights reserved. + * Copyright (c) 1996 by Silicon Graphics. All rights reserved. + * Copyright (c) 1998 by Fergus Henderson. All rights reserved. + * Copyright (c) 2000-2001 by Hewlett-Packard Company. All rights reserved. + * + * 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. + */ + /* + * Support code for LinuxThreads, the clone()-based kernel + * thread package for Linux which is included in libc6. + * + * This code relies on implementation details of LinuxThreads, + * (i.e. properties not guaranteed by the Pthread standard), + * though this version now does less of that than the other Pthreads + * support code. + * + * Note that there is a lot of code duplication between linux_threads.c + * and thread support for some of the other Posix platforms; any changes + * made here may need to be reflected there too. + */ + /* DG/UX ix86 support */ + /* + * 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 + */ + + /*#define DEBUG_THREADS 1*/ + /*#define GC_ASSERTIONS*/ + + # include "private/pthread_support.h" + + # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \ + && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS) \ + && !defined(GC_AIX_THREADS) + + # if defined(GC_HPUX_THREADS) && !defined(USE_PTHREAD_SPECIFIC) \ + && !defined(USE_HPUX_TLS) + # define USE_HPUX_TLS + # endif + + # if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \ + defined(GC_DARWIN_THREADS)) && !defined(USE_PTHREAD_SPECIFIC) + # define USE_PTHREAD_SPECIFIC + # endif + + # if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE) + # define _POSIX4A_DRAFT10_SOURCE 1 + # endif + + # if defined(GC_DGUX386_THREADS) && !defined(_USING_POSIX4A_DRAFT10) + # define _USING_POSIX4A_DRAFT10 1 + # endif + + # ifdef THREAD_LOCAL_ALLOC + # if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_HPUX_TLS) + # include "private/specific.h" + # endif + # if defined(USE_PTHREAD_SPECIFIC) + # define GC_getspecific pthread_getspecific + # define GC_setspecific pthread_setspecific + # define GC_key_create pthread_key_create + typedef pthread_key_t GC_key_t; + # endif + # if defined(USE_HPUX_TLS) + # define GC_getspecific(x) (x) + # define GC_setspecific(key, v) ((key) = (v), 0) + # define GC_key_create(key, d) 0 + typedef void * GC_key_t; + # endif + # endif + # include + # include + # include + # include + # include + # include + # include + # include + # include + # include + # include + + #if defined(GC_DARWIN_THREADS) + # include "private/darwin_semaphore.h" + #else + # include + #endif /* !GC_DARWIN_THREADS */ + + #if defined(GC_DARWIN_THREADS) + # include + #endif /* GC_DARWIN_THREADS */ + + + + #if defined(GC_DGUX386_THREADS) + # include + # include + /* sem_t is an uint in DG/UX */ + typedef unsigned int sem_t; + #endif /* GC_DGUX386_THREADS */ + + #ifndef __GNUC__ + # define __inline__ + #endif + + #ifdef GC_USE_LD_WRAP + # define WRAP_FUNC(f) __wrap_##f + # define REAL_FUNC(f) __real_##f + #else + # define WRAP_FUNC(f) GC_##f + # if !defined(GC_DGUX386_THREADS) + # define REAL_FUNC(f) f + # else /* GC_DGUX386_THREADS */ + # define REAL_FUNC(f) __d10_##f + # endif /* GC_DGUX386_THREADS */ + # undef pthread_create + # if !defined(GC_DARWIN_THREADS) + # undef pthread_sigmask + # endif + # undef pthread_join + # undef pthread_detach + # if defined(GC_OSF1_THREADS) && defined(_PTHREAD_USE_MANGLED_NAMES_) \ + && !defined(_PTHREAD_USE_PTDNAM_) + /* Restore the original mangled names on Tru64 UNIX. */ + # define pthread_create __pthread_create + # define pthread_join __pthread_join + # define pthread_detach __pthread_detach + # endif + #endif + + void GC_thr_init(); + + static GC_bool parallel_initialized = FALSE; + + void GC_init_parallel(); + + # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) + + /* We don't really support thread-local allocation with DBG_HDRS_ALL */ + + #ifdef USE_HPUX_TLS + __thread + #endif + GC_key_t GC_thread_key; + + static GC_bool keys_initialized; + + /* Recover the contents of the freelist array fl into the global one gfl.*/ + /* Note that the indexing scheme differs, in that gfl has finer size */ + /* resolution, even if not all entries are used. */ + /* We hold the allocator lock. */ + static void return_freelists(ptr_t *fl, ptr_t *gfl) + { + int i; + ptr_t q, *qptr; + size_t nwords; + + for (i = 1; i < NFREELISTS; ++i) { + nwords = i * (GRANULARITY/sizeof(word)); + qptr = fl + i; + q = *qptr; + if ((word)q >= HBLKSIZE) { + if (gfl[nwords] == 0) { + gfl[nwords] = q; + } else { + /* Concatenate: */ + for (; (word)q >= HBLKSIZE; qptr = &(obj_link(q)), q = *qptr); + GC_ASSERT(0 == q); + *qptr = gfl[nwords]; + gfl[nwords] = fl[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. */ + fl[i] = (ptr_t)HBLKSIZE; + } + } + + /* We statically allocate a single "size 0" object. It is linked to */ + /* itself, and is thus repeatedly reused for all size 0 allocation */ + /* requests. (Size 0 gcj allocation requests are incorrect, and */ + /* we arrange for those to fault asap.) */ + static ptr_t size_zero_object = (ptr_t)(&size_zero_object); + + /* Each thread structure must be initialized. */ + /* This call must be made from the new thread. */ + /* Caller holds allocation lock. */ + void GC_init_thread_local(GC_thread p) + { + int i; + + if (!keys_initialized) { + if (0 != GC_key_create(&GC_thread_key, 0)) { + ABORT("Failed to create key for local allocator"); + } + keys_initialized = TRUE; + } + if (0 != GC_setspecific(GC_thread_key, p)) { + ABORT("Failed to set thread specific allocation pointers"); + } + for (i = 1; i < NFREELISTS; ++i) { + p -> ptrfree_freelists[i] = (ptr_t)1; + p -> normal_freelists[i] = (ptr_t)1; + # ifdef GC_GCJ_SUPPORT + p -> gcj_freelists[i] = (ptr_t)1; + # endif + } + /* Set up the size 0 free lists. */ + p -> ptrfree_freelists[0] = (ptr_t)(&size_zero_object); + p -> normal_freelists[0] = (ptr_t)(&size_zero_object); + # ifdef GC_GCJ_SUPPORT + p -> gcj_freelists[0] = (ptr_t)(-1); + # endif + } + + #ifdef GC_GCJ_SUPPORT + extern ptr_t * GC_gcjobjfreelist; + #endif + + /* We hold the allocator lock. */ + void GC_destroy_thread_local(GC_thread p) + { + /* We currently only do this from the thread itself or from */ + /* the fork handler for a child process. */ + # ifndef HANDLE_FORK + GC_ASSERT(GC_getspecific(GC_thread_key) == (void *)p); + # endif + return_freelists(p -> ptrfree_freelists, GC_aobjfreelist); + return_freelists(p -> normal_freelists, GC_objfreelist); + # ifdef GC_GCJ_SUPPORT + return_freelists(p -> gcj_freelists, GC_gcjobjfreelist); + # endif + } + + extern GC_PTR GC_generic_malloc_many(); + + GC_PTR GC_local_malloc(size_t bytes) + { + if (EXPECT(!SMALL_ENOUGH(bytes),0)) { + return(GC_malloc(bytes)); + } else { + int index = INDEX_FROM_BYTES(bytes); + ptr_t * my_fl; + ptr_t my_entry; + # if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC) + GC_key_t k = GC_thread_key; + # endif + void * tsd; + + # if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC) + if (EXPECT(0 == k, 0)) { + /* This can happen if we get called when the world is */ + /* being initialized. Whether we can actually complete */ + /* the initialization then is unclear. */ + GC_init_parallel(); + k = GC_thread_key; + } + # endif + tsd = GC_getspecific(GC_thread_key); + # ifdef GC_ASSERTIONS + LOCK(); + GC_ASSERT(tsd == (void *)GC_lookup_thread(pthread_self())); + UNLOCK(); + # endif + my_fl = ((GC_thread)tsd) -> normal_freelists + index; + my_entry = *my_fl; + if (EXPECT((word)my_entry >= HBLKSIZE, 1)) { + ptr_t next = obj_link(my_entry); + GC_PTR result = (GC_PTR)my_entry; + *my_fl = next; + obj_link(my_entry) = 0; + PREFETCH_FOR_WRITE(next); + return result; + } else if ((word)my_entry - 1 < DIRECT_GRANULES) { + *my_fl = my_entry + index + 1; + return GC_malloc(bytes); + } else { + GC_generic_malloc_many(BYTES_FROM_INDEX(index), NORMAL, my_fl); + if (*my_fl == 0) return GC_oom_fn(bytes); + return GC_local_malloc(bytes); + } + } + } + + GC_PTR GC_local_malloc_atomic(size_t bytes) + { + if (EXPECT(!SMALL_ENOUGH(bytes), 0)) { + return(GC_malloc_atomic(bytes)); + } else { + int index = INDEX_FROM_BYTES(bytes); + ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key)) + -> ptrfree_freelists + index; + ptr_t my_entry = *my_fl; + + if (EXPECT((word)my_entry >= HBLKSIZE, 1)) { + GC_PTR result = (GC_PTR)my_entry; + *my_fl = obj_link(my_entry); + return result; + } else if ((word)my_entry - 1 < DIRECT_GRANULES) { + *my_fl = my_entry + index + 1; + return GC_malloc_atomic(bytes); + } else { + GC_generic_malloc_many(BYTES_FROM_INDEX(index), PTRFREE, my_fl); + /* *my_fl is updated while the collector is excluded; */ + /* the free list is always visible to the collector as */ + /* such. */ + if (*my_fl == 0) return GC_oom_fn(bytes); + return GC_local_malloc_atomic(bytes); + } + } + } + + #ifdef GC_GCJ_SUPPORT + + #include "include/gc_gcj.h" + + #ifdef GC_ASSERTIONS + extern GC_bool GC_gcj_malloc_initialized; + #endif + + extern int GC_gcj_kind; + + GC_PTR GC_local_gcj_malloc(size_t bytes, + void * ptr_to_struct_containing_descr) + { + GC_ASSERT(GC_gcj_malloc_initialized); + if (EXPECT(!SMALL_ENOUGH(bytes), 0)) { + return GC_gcj_malloc(bytes, ptr_to_struct_containing_descr); + } else { + int index = INDEX_FROM_BYTES(bytes); + ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key)) + -> gcj_freelists + index; + ptr_t my_entry = *my_fl; + if (EXPECT((word)my_entry >= HBLKSIZE, 1)) { + GC_PTR result = (GC_PTR)my_entry; + GC_ASSERT(!GC_incremental); + /* We assert that any concurrent marker will stop us. */ + /* Thus it is impossible for a mark procedure to see the */ + /* allocation of the next object, but to see this object */ + /* still containing a free list pointer. Otherwise the */ + /* marker might find a random "mark descriptor". */ + *(volatile ptr_t *)my_fl = obj_link(my_entry); + /* We must update the freelist before we store the pointer. */ + /* Otherwise a GC at this point would see a corrupted */ + /* free list. */ + /* A memory barrier is probably never needed, since the */ + /* action of stopping this thread will cause prior writes */ + /* to complete. */ + GC_ASSERT(((void * volatile *)result)[1] == 0); + *(void * volatile *)result = ptr_to_struct_containing_descr; + return result; + } else if ((word)my_entry - 1 < DIRECT_GRANULES) { + if (!GC_incremental) *my_fl = my_entry + index + 1; + /* In the incremental case, we always have to take this */ + /* path. Thus we leave the counter alone. */ + return GC_gcj_malloc(bytes, ptr_to_struct_containing_descr); + } else { + GC_generic_malloc_many(BYTES_FROM_INDEX(index), GC_gcj_kind, my_fl); + if (*my_fl == 0) return GC_oom_fn(bytes); + return GC_local_gcj_malloc(bytes, ptr_to_struct_containing_descr); + } + } + } + + #endif /* GC_GCJ_SUPPORT */ + + # else /* !THREAD_LOCAL_ALLOC && !DBG_HDRS_ALL */ + + # define GC_destroy_thread_local(t) + + # endif /* !THREAD_LOCAL_ALLOC */ + + #if 0 + /* + To make sure that we're using LinuxThreads and not some other thread + package, we generate a dummy reference to `pthread_kill_other_threads_np' + (was `__pthread_initial_thread_bos' but that disappeared), + which is a symbol defined in LinuxThreads, but (hopefully) not in other + thread packages. + + We no longer do this, since this code is now portable enough that it might + actually work for something else. + */ + void (*dummy_var_to_force_linux_threads)() = pthread_kill_other_threads_np; + #endif /* 0 */ + + long GC_nprocs = 1; /* Number of processors. We may not have */ + /* access to all of them, but this is as good */ + /* a guess as any ... */ + + #ifdef PARALLEL_MARK + + # ifndef MAX_MARKERS + # define MAX_MARKERS 16 + # endif + + static ptr_t marker_sp[MAX_MARKERS] = {0}; + + void * GC_mark_thread(void * id) + { + word my_mark_no = 0; + + marker_sp[(word)id] = GC_approx_sp(); + 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 */ + /* handler or from the GC lock acquisition code. Under Linux, it's */ + /* not safe to call it from a signal handler, since it uses mutexes */ + /* and condition variables. Since it is called only here, the */ + /* argument is unnecessary. */ + if (my_mark_no < GC_mark_no || my_mark_no > GC_mark_no + 2) { + /* resynchronize if we get far off, e.g. because GC_mark_no */ + /* wrapped. */ + my_mark_no = GC_mark_no; + } + # ifdef DEBUG_THREADS + GC_printf1("Starting mark helper for mark number %ld\n", my_mark_no); + # endif + GC_help_marker(my_mark_no); + } + } + + extern long GC_markers; /* Number of mark threads we would */ + /* like to have. Includes the */ + /* initiating thread. */ + + pthread_t GC_mark_threads[MAX_MARKERS]; + + #define PTHREAD_CREATE REAL_FUNC(pthread_create) + + static void start_mark_threads() + { + unsigned i; + pthread_attr_t attr; + + if (GC_markers > MAX_MARKERS) { + WARN("Limiting number of mark threads\n", 0); + GC_markers = MAX_MARKERS; + } + 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)) + { + size_t old_size; + int code; + + if (pthread_attr_getstacksize(&attr, &old_size) != 0) + ABORT("pthread_attr_getstacksize failed\n"); + if (old_size < MIN_STACK_SIZE) { + if (pthread_attr_setstacksize(&attr, MIN_STACK_SIZE) != 0) + ABORT("pthread_attr_setstacksize failed\n"); + } + } + # endif /* HPUX || GC_DGUX386_THREADS */ + # ifdef CONDPRINT + if (GC_print_stats) { + GC_printf1("Starting %ld marker threads\n", GC_markers - 1); + } + # endif + for (i = 0; i < GC_markers - 1; ++i) { + if (0 != PTHREAD_CREATE(GC_mark_threads + i, &attr, + GC_mark_thread, (void *)(word)i)) { + WARN("Marker thread creation failed, errno = %ld.\n", errno); + } + } + } + + #else /* !PARALLEL_MARK */ + + static __inline__ void start_mark_threads() + { + } + + #endif /* !PARALLEL_MARK */ + + /* Defining INSTALL_LOOPING_SEGV_HANDLER causes SIGSEGV and SIGBUS to */ + /* result in an infinite loop in a signal handler. This can be very */ + /* useful for debugging, since (as of RH7) gdb still seems to have */ + /* serious problems with threads. */ + #ifdef INSTALL_LOOPING_SEGV_HANDLER + void GC_looping_handler(int sig) + { + GC_printf3("Signal %ld in thread %lx, pid %ld\n", + sig, pthread_self(), getpid()); + for (;;); + } + #endif + + GC_bool GC_thr_initialized = FALSE; + + volatile GC_thread GC_threads[THREAD_TABLE_SZ]; + + void GC_push_thread_structures GC_PROTO((void)) + { + GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads)); + # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) + GC_push_all((ptr_t)(&GC_thread_key), + (ptr_t)(&GC_thread_key)+sizeof(&GC_thread_key)); + # endif + } + + #ifdef THREAD_LOCAL_ALLOC + /* We must explicitly mark ptrfree and gcj free lists, since the free */ + /* list links wouldn't otherwise be found. We also set them in the */ + /* normal free lists, since that involves touching less memory than if */ + /* we scanned them normally. */ + void GC_mark_thread_local_free_lists(void) + { + int i, j; + GC_thread p; + ptr_t q; + + for (i = 0; i < THREAD_TABLE_SZ; ++i) { + for (p = GC_threads[i]; 0 != p; p = p -> next) { + for (j = 1; j < NFREELISTS; ++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 + q = p -> gcj_freelists[j]; + if ((word)q > HBLKSIZE) GC_set_fl_marks(q); + # endif /* GC_GCJ_SUPPORT */ + } + } + } + } + #endif /* THREAD_LOCAL_ALLOC */ + + static struct GC_Thread_Rep first_thread; + + /* Add a thread to GC_threads. We assume it wasn't already there. */ + /* Caller holds allocation lock. */ + GC_thread GC_new_thread(pthread_t id) + { + int hv = ((word)id) % THREAD_TABLE_SZ; + GC_thread result; + static GC_bool first_thread_used = FALSE; + + if (!first_thread_used) { + result = &first_thread; + first_thread_used = TRUE; + } else { + result = (struct GC_Thread_Rep *) + GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL); + } + if (result == 0) return(0); + result -> id = id; + result -> next = GC_threads[hv]; + GC_threads[hv] = result; + GC_ASSERT(result -> flags == 0 && result -> thread_blocked == 0); + return(result); + } + + /* Delete a thread from GC_threads. We assume it is there. */ + /* (The code intentionally traps if it wasn't.) */ + /* Caller holds allocation lock. */ + void GC_delete_thread(pthread_t id) + { + int hv = ((word)id) % THREAD_TABLE_SZ; + register GC_thread p = GC_threads[hv]; + register GC_thread prev = 0; + + while (!pthread_equal(p -> id, id)) { + prev = p; + p = p -> next; + } + if (prev == 0) { + GC_threads[hv] = p -> next; + } else { + prev -> next = p -> next; + } + GC_INTERNAL_FREE(p); + } + + /* If a thread has been joined, but we have not yet */ + /* been notified, then there may be more than one thread */ + /* in the table with the same pthread id. */ + /* This is OK, but we need a way to delete a specific one. */ + void GC_delete_gc_thread(pthread_t id, GC_thread gc_id) + { + int hv = ((word)id) % THREAD_TABLE_SZ; + register GC_thread p = GC_threads[hv]; + register GC_thread prev = 0; + + while (p != gc_id) { + prev = p; + p = p -> next; + } + if (prev == 0) { + GC_threads[hv] = p -> next; + } else { + prev -> next = p -> next; + } + GC_INTERNAL_FREE(p); + } + + /* Return a GC_thread corresponding to a given thread_t. */ + /* Returns 0 if it's not there. */ + /* Caller holds allocation lock or otherwise inhibits */ + /* updates. */ + /* If there is more than one thread with the given id we */ + /* return the most recent one. */ + GC_thread GC_lookup_thread(pthread_t id) + { + int hv = ((word)id) % THREAD_TABLE_SZ; + register GC_thread p = GC_threads[hv]; + + while (p != 0 && !pthread_equal(p -> id, id)) p = p -> next; + return(p); + } + + #ifdef 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 */ + /* process after a fork(), since only the current thread */ + /* survives in the child. */ + void GC_remove_all_threads_but_me(void) + { + pthread_t self = pthread_self(); + int hv; + GC_thread p, next, me; + + for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) { + me = 0; + for (p = GC_threads[hv]; 0 != p; p = next) { + next = p -> next; + if (p -> id == self) { + me = p; + p -> next = 0; + } else { + # ifdef THREAD_LOCAL_ALLOC + if (!(p -> flags & FINISHED)) { + GC_destroy_thread_local(p); + } + # endif /* THREAD_LOCAL_ALLOC */ + if (p != &first_thread) GC_INTERNAL_FREE(p); + } + } + GC_threads[hv] = me; + } + } + #endif /* HANDLE_FORK */ + + #ifdef USE_PROC_FOR_LIBRARIES + int GC_segment_is_thread_stack(ptr_t lo, ptr_t hi) + { + int i; + GC_thread p; + + # ifdef PARALLEL_MARK + for (i = 0; i < GC_markers; ++i) { + if (marker_sp[i] > lo & marker_sp[i] < hi) return 1; + } + # endif + for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (p = GC_threads[i]; p != 0; p = p -> next) { + if (0 != p -> stack_end) { + # ifdef STACK_GROWS_UP + if (p -> stack_end >= lo && p -> stack_end < hi) return 1; + # else /* STACK_GROWS_DOWN */ + if (p -> stack_end > lo && p -> stack_end <= hi) return 1; + # endif + } + } + } + return 0; + } + #endif /* USE_PROC_FOR_LIBRARIES */ + + #ifdef GC_LINUX_THREADS + /* Return the number of processors, or i<= 0 if it can't be determined. */ + int GC_get_nprocs() + { + /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that */ + /* appears to be buggy in many cases. */ + /* We look for lines "cpu" in /proc/stat. */ + # define STAT_BUF_SIZE 4096 + # define STAT_READ read + /* If read is wrapped, this may need to be redefined to call */ + /* the real one. */ + char stat_buf[STAT_BUF_SIZE]; + int f; + word result = 1; + /* Some old kernels only have a single "cpu nnnn ..." */ + /* entry in /proc/stat. We identify those as */ + /* uniprocessors. */ + size_t i, len = 0; + + f = open("/proc/stat", O_RDONLY); + if (f < 0 || (len = STAT_READ(f, stat_buf, STAT_BUF_SIZE)) < 100) { + WARN("Couldn't read /proc/stat\n", 0); + return -1; + } + for (i = 0; i < len - 100; ++i) { + if (stat_buf[i] == '\n' && stat_buf[i+1] == 'c' + && stat_buf[i+2] == 'p' && stat_buf[i+3] == 'u') { + int cpu_no = atoi(stat_buf + i + 4); + if (cpu_no >= result) result = cpu_no + 1; + } + } + close(f); + return result; + } + #endif /* GC_LINUX_THREADS */ + + /* We hold the GC lock. Wait until an in-progress GC has finished. */ + /* Repeatedly RELEASES GC LOCK in order to wait. */ + /* If wait_for_all is true, then we exit with the GC lock held and no */ + /* collection in progress; otherwise we just wait for the current GC */ + /* to finish. */ + extern GC_bool GC_collection_in_progress(); + void GC_wait_for_gc_completion(GC_bool wait_for_all) + { + if (GC_incremental && GC_collection_in_progress()) { + int old_gc_no = GC_gc_no; + + /* Make sure that no part of our stack is still on the mark stack, */ + /* since it's about to be unmapped. */ + while (GC_incremental && GC_collection_in_progress() + && (wait_for_all || old_gc_no == GC_gc_no)) { + ENTER_GC(); + GC_collect_a_little_inner(1); + EXIT_GC(); + UNLOCK(); + sched_yield(); + LOCK(); + } + } + } + + #ifdef HANDLE_FORK + /* Procedures called before and after a fork. The goal here is to make */ + /* it safe to call GC_malloc() in a forked child. It's unclear that is */ + /* attainable, since the single UNIX spec seems to imply that one */ + /* should only call async-signal-safe functions, and we probably can't */ + /* quite guarantee that. But we give it our best shot. (That same */ + /* spec also implies that it's not safe to call the system malloc */ + /* between fork() and exec(). Thus we're doing no worse than it. */ + + /* Called before a fork() */ + void GC_fork_prepare_proc(void) + { + /* Acquire all relevant locks, so that after releasing the locks */ + /* the child will see a consistent state in which monitor */ + /* invariants hold. Unfortunately, we can't acquire libc locks */ + /* we might need, and there seems to be no guarantee that libc */ + /* must install a suitable fork handler. */ + /* Wait for an ongoing GC to finish, since we can't finish it in */ + /* the (one remaining thread in) the child. */ + LOCK(); + # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) + GC_wait_for_reclaim(); + # endif + GC_wait_for_gc_completion(TRUE); + # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) + GC_acquire_mark_lock(); + # endif + } + + /* Called in parent after a fork() */ + void GC_fork_parent_proc(void) + { + # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) + GC_release_mark_lock(); + # endif + UNLOCK(); + } + + /* Called in child after a fork() */ + void GC_fork_child_proc(void) + { + /* Clean up the thread table, so that just our thread is left. */ + # if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) + GC_release_mark_lock(); + # endif + GC_remove_all_threads_but_me(); + # ifdef PARALLEL_MARK + /* Turn off parallel marking in the child, since we are probably */ + /* just going to exec, and we would have to restart mark threads. */ + GC_markers = 1; + GC_parallel = FALSE; + # endif /* PARALLEL_MARK */ + UNLOCK(); + } + #endif /* HANDLE_FORK */ + + #if defined(GC_DGUX386_THREADS) + /* Return the number of processors, or i<= 0 if it can't be determined. */ + int GC_get_nprocs() + { + /* */ + int numCpus; + struct dg_sys_info_pm_info pm_sysinfo; + int status =0; + + status = dg_sys_info((long int *) &pm_sysinfo, + DG_SYS_INFO_PM_INFO_TYPE, DG_SYS_INFO_PM_CURRENT_VERSION); + if (status < 0) + /* set -1 for error */ + numCpus = -1; + else + /* Active CPUs */ + numCpus = pm_sysinfo.idle_vp_count; + + # ifdef DEBUG_THREADS + GC_printf1("Number of active CPUs in this system: %d\n", numCpus); + # endif + return(numCpus); + } + #endif /* GC_DGUX386_THREADS */ + + /* We hold the allocation lock. */ + void GC_thr_init() + { + # ifndef GC_DARWIN_THREADS + int dummy; + # endif + GC_thread t; + + if (GC_thr_initialized) return; + GC_thr_initialized = TRUE; + + # ifdef HANDLE_FORK + /* Prepare for a possible fork. */ + pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc, + GC_fork_child_proc); + # endif /* HANDLE_FORK */ + /* Add the initial thread, so we can stop it. */ + t = GC_new_thread(pthread_self()); + # ifdef GC_DARWIN_THREADS + t -> stop_info.mach_thread = mach_thread_self(); + # else + t -> stop_info.stack_ptr = (ptr_t)(&dummy); + # endif + t -> flags = DETACHED | MAIN_THREAD; + + GC_stop_init(); + + /* Set GC_nprocs. */ + { + char * nprocs_string = GETENV("GC_NPROCS"); + GC_nprocs = -1; + if (nprocs_string != NULL) GC_nprocs = atoi(nprocs_string); + } + if (GC_nprocs <= 0) { + # if defined(GC_HPUX_THREADS) + GC_nprocs = pthread_num_processors_np(); + # endif + # if defined(GC_OSF1_THREADS) + GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN); + if (GC_nprocs <= 0) GC_nprocs = 1; + # endif + # if defined(GC_FREEBSD_THREADS) + GC_nprocs = 1; + # endif + # if defined(GC_DARWIN_THREADS) + int ncpus = 1; + size_t len = sizeof(ncpus); + sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0); + GC_nprocs = ncpus; + # endif + # if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS) + GC_nprocs = GC_get_nprocs(); + # endif + } + if (GC_nprocs <= 0) { + WARN("GC_get_nprocs() returned %ld\n", GC_nprocs); + GC_nprocs = 2; + # ifdef PARALLEL_MARK + GC_markers = 1; + # endif + } else { + # ifdef PARALLEL_MARK + { + char * markers_string = GETENV("GC_MARKERS"); + if (markers_string != NULL) { + GC_markers = atoi(markers_string); + } else { + GC_markers = GC_nprocs; + } + } + # endif + } + # ifdef PARALLEL_MARK + # ifdef CONDPRINT + if (GC_print_stats) { + GC_printf2("Number of processors = %ld, " + "number of marker threads = %ld\n", GC_nprocs, GC_markers); + } + # endif + if (GC_markers == 1) { + GC_parallel = FALSE; + # ifdef CONDPRINT + if (GC_print_stats) { + GC_printf0("Single marker thread, turning off parallel marking\n"); + } + # endif + } else { + GC_parallel = TRUE; + /* Disable true incremental collection, but generational is OK. */ + GC_time_limit = GC_TIME_UNLIMITED; + } + # endif + } + + + /* Perform all initializations, including those that */ + /* may require allocation. */ + /* Called without allocation lock. */ + /* Must be called before a second thread is created. */ + /* Called without allocation lock. */ + void GC_init_parallel() + { + if (parallel_initialized) return; + parallel_initialized = TRUE; + + /* GC_init() calls us back, so set flag first. */ + if (!GC_is_initialized) GC_init(); + /* If we are using a parallel marker, start the helper threads. */ + # ifdef PARALLEL_MARK + if (GC_parallel) start_mark_threads(); + # endif + /* Initialize thread local free lists if used. */ + # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) + LOCK(); + GC_init_thread_local(GC_lookup_thread(pthread_self())); + UNLOCK(); + # endif + } + + + #if !defined(GC_DARWIN_THREADS) + int WRAP_FUNC(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset) + { + sigset_t fudged_set; + + if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) { + fudged_set = *set; + sigdelset(&fudged_set, SIG_SUSPEND); + set = &fudged_set; + } + return(REAL_FUNC(pthread_sigmask)(how, set, oset)); + } + #endif /* !GC_DARWIN_THREADS */ + + /* Wrappers for functions that are likely to block for an appreciable */ + /* length of time. Must be called in pairs, if at all. */ + /* Nothing much beyond the system call itself should be executed */ + /* between these. */ + + void GC_start_blocking(void) { + # define SP_SLOP 128 + GC_thread me; + LOCK(); + me = GC_lookup_thread(pthread_self()); + GC_ASSERT(!(me -> thread_blocked)); + # ifdef SPARC + me -> stop_info.stack_ptr = (ptr_t)GC_save_regs_in_stack(); + # else + # ifndef GC_DARWIN_THREADS + me -> stop_info.stack_ptr = (ptr_t)GC_approx_sp(); + # endif + # endif + # ifdef IA64 + me -> backing_store_ptr = (ptr_t)GC_save_regs_in_stack() + SP_SLOP; + # endif + /* Add some slop to the stack pointer, since the wrapped call may */ + /* end up pushing more callee-save registers. */ + # ifndef GC_DARWIN_THREADS + # ifdef STACK_GROWS_UP + me -> stop_info.stack_ptr += SP_SLOP; + # else + me -> stop_info.stack_ptr -= SP_SLOP; + # endif + # endif + me -> thread_blocked = TRUE; + UNLOCK(); + } + + void GC_end_blocking(void) { + GC_thread me; + LOCK(); /* This will block if the world is stopped. */ + me = GC_lookup_thread(pthread_self()); + GC_ASSERT(me -> thread_blocked); + me -> thread_blocked = FALSE; + UNLOCK(); + } + + #if defined(GC_DGUX386_THREADS) + #define __d10_sleep sleep + #endif /* GC_DGUX386_THREADS */ + + /* A wrapper for the standard C sleep function */ + int WRAP_FUNC(sleep) (unsigned int seconds) + { + int result; + + GC_start_blocking(); + result = REAL_FUNC(sleep)(seconds); + GC_end_blocking(); + return result; + } + + struct start_info { + void *(*start_routine)(void *); + void *arg; + word flags; + sem_t registered; /* 1 ==> in our thread table, but */ + /* parent hasn't yet noticed. */ + }; + + /* Called at thread exit. */ + /* Never called for main thread. That's OK, since it */ + /* results in at most a tiny one-time leak. And */ + /* linuxthreads doesn't reclaim the main threads */ + /* resources or id anyway. */ + void GC_thread_exit_proc(void *arg) + { + GC_thread me; + + LOCK(); + me = GC_lookup_thread(pthread_self()); + GC_destroy_thread_local(me); + if (me -> flags & DETACHED) { + GC_delete_thread(pthread_self()); + } else { + me -> flags |= FINISHED; + } + # if defined(THREAD_LOCAL_ALLOC) && !defined(USE_PTHREAD_SPECIFIC) \ + && !defined(USE_HPUX_TLS) && !defined(DBG_HDRS_ALL) + GC_remove_specific(GC_thread_key); + # endif + GC_wait_for_gc_completion(FALSE); + UNLOCK(); + } + + int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) + { + int result; + GC_thread thread_gc_id; + + LOCK(); + thread_gc_id = GC_lookup_thread(thread); + /* This is guaranteed to be the intended one, since the thread id */ + /* cant have been recycled by pthreads. */ + UNLOCK(); + result = REAL_FUNC(pthread_join)(thread, retval); + # if defined (GC_FREEBSD_THREADS) + /* On FreeBSD, the wrapped pthread_join() sometimes returns (what + appears to be) a spurious EINTR which caused the test and real code + to gratuitously fail. Having looked at system pthread library source + code, I see how this return code may be generated. In one path of + code, pthread_join() just returns the errno setting of the thread + being joined. This does not match the POSIX specification or the + local man pages thus I have taken the liberty to catch this one + spurious return value properly conditionalized on GC_FREEBSD_THREADS. */ + if (result == EINTR) result = 0; + # endif + if (result == 0) { + LOCK(); + /* Here the pthread thread id may have been recycled. */ + GC_delete_gc_thread(thread, thread_gc_id); + UNLOCK(); + } + return result; + } + + int + WRAP_FUNC(pthread_detach)(pthread_t thread) + { + int result; + GC_thread thread_gc_id; + + LOCK(); + thread_gc_id = GC_lookup_thread(thread); + UNLOCK(); + result = REAL_FUNC(pthread_detach)(thread); + if (result == 0) { + LOCK(); + thread_gc_id -> flags |= DETACHED; + /* Here the pthread thread id may have been recycled. */ + if (thread_gc_id -> flags & FINISHED) { + GC_delete_gc_thread(thread, thread_gc_id); + } + UNLOCK(); + } + return result; + } + + void * GC_start_routine(void * arg) + { + int dummy; + struct start_info * si = arg; + void * result; + GC_thread me; + pthread_t my_pthread; + void *(*start)(void *); + void *start_arg; + + my_pthread = pthread_self(); + # ifdef DEBUG_THREADS + GC_printf1("Starting thread 0x%lx\n", my_pthread); + GC_printf1("pid = %ld\n", (long) getpid()); + GC_printf1("sp = 0x%lx\n", (long) &arg); + # endif + LOCK(); + me = GC_new_thread(my_pthread); + #ifdef GC_DARWIN_THREADS + me -> stop_info.mach_thread = mach_thread_self(); + #else + me -> stop_info.stack_ptr = 0; + #endif + me -> flags = si -> flags; + /* me -> stack_end = GC_linux_stack_base(); -- currently (11/99) */ + /* doesn't work because the stack base in /proc/self/stat is the */ + /* one for the main thread. There is a strong argument that that's */ + /* a kernel bug, but a pervasive one. */ + # ifdef STACK_GROWS_DOWN + me -> stack_end = (ptr_t)(((word)(&dummy) + (GC_page_size - 1)) + & ~(GC_page_size - 1)); + # ifndef GC_DARWIN_THREADS + me -> stop_info.stack_ptr = me -> stack_end - 0x10; + # endif + /* Needs to be plausible, since an asynchronous stack mark */ + /* should not crash. */ + # else + me -> stack_end = (ptr_t)((word)(&dummy) & ~(GC_page_size - 1)); + me -> stop_info.stack_ptr = me -> stack_end + 0x10; + # endif + /* This is dubious, since we may be more than a page into the stack, */ + /* and hence skip some of it, though it's not clear that matters. */ + # ifdef IA64 + me -> backing_store_end = (ptr_t) + (GC_save_regs_in_stack() & ~(GC_page_size - 1)); + /* This is also < 100% convincing. We should also read this */ + /* from /proc, but the hook to do so isn't there yet. */ + # endif /* IA64 */ + UNLOCK(); + start = si -> start_routine; + # ifdef DEBUG_THREADS + GC_printf1("start_routine = 0x%lx\n", start); + # endif + start_arg = si -> arg; + sem_post(&(si -> registered)); /* Last action on si. */ + /* OK to deallocate. */ + pthread_cleanup_push(GC_thread_exit_proc, 0); + # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) + LOCK(); + GC_init_thread_local(me); + UNLOCK(); + # endif + result = (*start)(start_arg); + #if DEBUG_THREADS + GC_printf1("Finishing thread 0x%x\n", pthread_self()); + #endif + me -> status = result; + pthread_cleanup_pop(1); + /* Cleanup acquires lock, ensuring that we can't exit */ + /* while a collection that thinks we're alive is trying to stop */ + /* us. */ + return(result); + } + + int + WRAP_FUNC(pthread_create)(pthread_t *new_thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) + { + int result; + int detachstate; + word my_flags = 0; + struct start_info * si; + /* This is otherwise saved only in an area mmapped by the thread */ + /* library, which isn't visible to the collector. */ + + /* We resist the temptation to muck with the stack size here, */ + /* even if the default is unreasonably small. That's the client's */ + /* responsibility. */ + + LOCK(); + si = (struct start_info *)GC_INTERNAL_MALLOC(sizeof(struct start_info), + NORMAL); + UNLOCK(); + if (!parallel_initialized) GC_init_parallel(); + if (0 == si) return(ENOMEM); + sem_init(&(si -> registered), 0, 0); + si -> start_routine = start_routine; + si -> arg = arg; + LOCK(); + if (!GC_thr_initialized) GC_thr_init(); + # ifdef GC_ASSERTIONS + { + int stack_size; + if (NULL == attr) { + pthread_attr_t my_attr; + pthread_attr_init(&my_attr); + pthread_attr_getstacksize(&my_attr, &stack_size); + } else { + pthread_attr_getstacksize(attr, &stack_size); + } + GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word))); + /* Our threads may need to do some work for the GC. */ + /* Ridiculously small threads won't work, and they */ + /* probably wouldn't work anyway. */ + } + # endif + if (NULL == attr) { + detachstate = PTHREAD_CREATE_JOINABLE; + } else { + pthread_attr_getdetachstate(attr, &detachstate); + } + if (PTHREAD_CREATE_DETACHED == detachstate) my_flags |= DETACHED; + si -> flags = my_flags; + UNLOCK(); + # ifdef DEBUG_THREADS + GC_printf1("About to start new thread from thread 0x%X\n", + pthread_self()); + # endif + + result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, si); + + # ifdef DEBUG_THREADS + GC_printf1("Started thread 0x%X\n", *new_thread); + # endif + /* Wait until child has been added to the thread table. */ + /* This also ensures that we hold onto si until the child is done */ + /* with it. Thus it doesn't matter whether it is otherwise */ + /* visible to the collector. */ + if (0 == result) { + while (0 != sem_wait(&(si -> registered))) { + if (EINTR != errno) ABORT("sem_wait failed"); + } + } + sem_destroy(&(si -> registered)); + LOCK(); + GC_INTERNAL_FREE(si); + UNLOCK(); + + return(result); + } + + #ifdef GENERIC_COMPARE_AND_SWAP + pthread_mutex_t GC_compare_and_swap_lock = PTHREAD_MUTEX_INITIALIZER; + + GC_bool GC_compare_and_exchange(volatile GC_word *addr, + GC_word old, GC_word new_val) + { + GC_bool result; + pthread_mutex_lock(&GC_compare_and_swap_lock); + if (*addr == old) { + *addr = new_val; + result = TRUE; + } else { + result = FALSE; + } + pthread_mutex_unlock(&GC_compare_and_swap_lock); + return result; + } + + GC_word GC_atomic_add(volatile GC_word *addr, GC_word how_much) + { + GC_word old; + pthread_mutex_lock(&GC_compare_and_swap_lock); + old = *addr; + *addr = old + how_much; + pthread_mutex_unlock(&GC_compare_and_swap_lock); + return old; + } + + #endif /* GENERIC_COMPARE_AND_SWAP */ + /* Spend a few cycles in a way that can't introduce contention with */ + /* othre threads. */ + void GC_pause() + { + int i; + # ifndef __GNUC__ + volatile word dummy = 0; + # endif + + for (i = 0; i < 10; ++i) { + # ifdef __GNUC__ + __asm__ __volatile__ (" " : : : "memory"); + # else + /* Something that's unlikely to be optimized away. */ + GC_noop(++dummy); + # endif + } + } + + #define SPIN_MAX 1024 /* Maximum number of calls to GC_pause before */ + /* give up. */ + + VOLATILE GC_bool GC_collecting = 0; + /* A hint that we're in the collector and */ + /* holding the allocation lock for an */ + /* extended period. */ + + #if !defined(USE_SPIN_LOCK) || defined(PARALLEL_MARK) + /* If we don't want to use the below spinlock implementation, either */ + /* because we don't have a GC_test_and_set implementation, or because */ + /* we don't want to risk sleeping, we can still try spinning on */ + /* pthread_mutex_trylock for a while. This appears to be very */ + /* beneficial in many cases. */ + /* I suspect that under high contention this is nearly always better */ + /* than the spin lock. But it's a bit slower on a uniprocessor. */ + /* Hence we still default to the spin lock. */ + /* This is also used to acquire the mark lock for the parallel */ + /* marker. */ + + /* Here we use a strict exponential backoff scheme. I don't know */ + /* whether that's better or worse than the above. We eventually */ + /* yield by calling pthread_mutex_lock(); it never makes sense to */ + /* explicitly sleep. */ + + void GC_generic_lock(pthread_mutex_t * lock) + { + #ifndef NO_PTHREAD_TRYLOCK + unsigned pause_length = 1; + unsigned i; + + if (0 == pthread_mutex_trylock(lock)) return; + for (; pause_length <= SPIN_MAX; pause_length <<= 1) { + for (i = 0; i < pause_length; ++i) { + GC_pause(); + } + switch(pthread_mutex_trylock(lock)) { + case 0: + return; + case EBUSY: + break; + default: + ABORT("Unexpected error from pthread_mutex_trylock"); + } + } + #endif /* !NO_PTHREAD_TRYLOCK */ + pthread_mutex_lock(lock); + } + + #endif /* !USE_SPIN_LOCK || PARALLEL_MARK */ + + #if defined(USE_SPIN_LOCK) + + /* Reasonably fast spin locks. Basically the same implementation */ + /* as STL alloc.h. This isn't really the right way to do this. */ + /* but until the POSIX scheduling mess gets straightened out ... */ + + volatile unsigned int GC_allocate_lock = 0; + + + void GC_lock() + { + # define low_spin_max 30 /* spin cycles if we suspect uniprocessor */ + # define high_spin_max SPIN_MAX /* spin cycles for multiprocessor */ + static unsigned spin_max = low_spin_max; + unsigned my_spin_max; + static unsigned last_spins = 0; + unsigned my_last_spins; + int i; + + if (!GC_test_and_set(&GC_allocate_lock)) { + return; + } + my_spin_max = spin_max; + my_last_spins = last_spins; + for (i = 0; i < my_spin_max; i++) { + if (GC_collecting || GC_nprocs == 1) goto yield; + if (i < my_last_spins/2 || GC_allocate_lock) { + GC_pause(); + continue; + } + if (!GC_test_and_set(&GC_allocate_lock)) { + /* + * got it! + * Spinning worked. Thus we're probably not being scheduled + * against the other process with which we were contending. + * Thus it makes sense to spin longer the next time. + */ + last_spins = i; + spin_max = high_spin_max; + return; + } + } + /* We are probably being scheduled against the other process. Sleep. */ + spin_max = low_spin_max; + yield: + for (i = 0;; ++i) { + if (!GC_test_and_set(&GC_allocate_lock)) { + return; + } + # 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. */ + /* (Under 2.4, this happens only for real-time */ + /* processes.) We want to minimize both behaviors */ + /* here. */ + if (i < SLEEP_THRESHOLD) { + sched_yield(); + } else { + struct timespec ts; + + if (i > 24) i = 24; + /* Don't wait for more than about 15msecs, even */ + /* under extreme contention. */ + ts.tv_sec = 0; + ts.tv_nsec = 1 << i; + nanosleep(&ts, 0); + } + } + } + + #else /* !USE_SPINLOCK */ + void GC_lock() + { + #ifndef NO_PTHREAD_TRYLOCK + if (1 == GC_nprocs || GC_collecting) { + pthread_mutex_lock(&GC_allocate_ml); + } else { + GC_generic_lock(&GC_allocate_ml); + } + #else /* !NO_PTHREAD_TRYLOCK */ + pthread_mutex_lock(&GC_allocate_ml); + #endif /* !NO_PTHREAD_TRYLOCK */ + } + + #endif /* !USE_SPINLOCK */ + + #if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) + + #ifdef GC_ASSERTIONS + pthread_t GC_mark_lock_holder = NO_THREAD; + #endif + + #if 0 + /* Ugly workaround for a linux threads bug in the final versions */ + /* of glibc2.1. Pthread_mutex_trylock sets the mutex owner */ + /* field even when it fails to acquire the mutex. This causes */ + /* pthread_cond_wait to die. Remove for glibc2.2. */ + /* According to the man page, we should use */ + /* PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, but that isn't actually */ + /* defined. */ + static pthread_mutex_t mark_mutex = + {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, {0, 0}}; + #else + static pthread_mutex_t mark_mutex = PTHREAD_MUTEX_INITIALIZER; + #endif + + static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER; + + void GC_acquire_mark_lock() + { + /* + if (pthread_mutex_lock(&mark_mutex) != 0) { + ABORT("pthread_mutex_lock failed"); + } + */ + GC_generic_lock(&mark_mutex); + # ifdef GC_ASSERTIONS + GC_mark_lock_holder = pthread_self(); + # endif + } + + void GC_release_mark_lock() + { + GC_ASSERT(GC_mark_lock_holder == pthread_self()); + # ifdef GC_ASSERTIONS + GC_mark_lock_holder = NO_THREAD; + # endif + if (pthread_mutex_unlock(&mark_mutex) != 0) { + ABORT("pthread_mutex_unlock failed"); + } + } + + /* Collector must wait for a freelist builders for 2 reasons: */ + /* 1) Mark bits may still be getting examined without lock. */ + /* 2) Partial free lists referenced only by locals may not be scanned */ + /* correctly, e.g. if they contain "pointer-free" objects, since the */ + /* free-list link may be ignored. */ + void GC_wait_builder() + { + GC_ASSERT(GC_mark_lock_holder == pthread_self()); + # ifdef GC_ASSERTIONS + GC_mark_lock_holder = NO_THREAD; + # endif + if (pthread_cond_wait(&builder_cv, &mark_mutex) != 0) { + ABORT("pthread_cond_wait failed"); + } + GC_ASSERT(GC_mark_lock_holder == NO_THREAD); + # ifdef GC_ASSERTIONS + GC_mark_lock_holder = pthread_self(); + # endif + } + + void GC_wait_for_reclaim() + { + GC_acquire_mark_lock(); + while (GC_fl_builder_count > 0) { + GC_wait_builder(); + } + GC_release_mark_lock(); + } + + void GC_notify_all_builder() + { + GC_ASSERT(GC_mark_lock_holder == pthread_self()); + if (pthread_cond_broadcast(&builder_cv) != 0) { + ABORT("pthread_cond_broadcast failed"); + } + } + + #endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */ + + #ifdef PARALLEL_MARK + + static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER; + + void GC_wait_marker() + { + GC_ASSERT(GC_mark_lock_holder == pthread_self()); + # ifdef GC_ASSERTIONS + GC_mark_lock_holder = NO_THREAD; + # endif + if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) { + ABORT("pthread_cond_wait failed"); + } + GC_ASSERT(GC_mark_lock_holder == NO_THREAD); + # ifdef GC_ASSERTIONS + GC_mark_lock_holder = pthread_self(); + # endif + } + + void GC_notify_all_marker() + { + if (pthread_cond_broadcast(&mark_cv) != 0) { + ABORT("pthread_cond_broadcast failed"); + } + } + + #endif /* PARALLEL_MARK */ + + # endif /* GC_LINUX_THREADS and friends */ + diff -Nrc3pad gcc-3.3.3/boehm-gc/ptr_chck.c gcc-3.4.0/boehm-gc/ptr_chck.c *** gcc-3.3.3/boehm-gc/ptr_chck.c 2001-08-17 18:30:46.000000000 +0000 --- gcc-3.4.0/boehm-gc/ptr_chck.c 2003-07-28 04:18:20.000000000 +0000 *************** void (*GC_same_obj_print_proc) GC_PROTO( *** 79,85 **** return(p); } sz = WORDS_TO_BYTES(hhdr -> hb_sz); ! if (sz > WORDS_TO_BYTES(MAXOBJSZ)) { base = (ptr_t)HBLKPTR(p); limit = base + sz; if ((ptr_t)p >= limit) { --- 79,85 ---- return(p); } sz = WORDS_TO_BYTES(hhdr -> hb_sz); ! if (sz > MAXOBJBYTES) { base = (ptr_t)HBLKPTR(p); limit = base + sz; if ((ptr_t)p >= limit) { *************** void (*GC_is_valid_displacement_print_pr *** 165,171 **** pdispl = HBLKDISPL(p); map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl); if (map_entry == OBJ_INVALID ! || sz > MAXOBJSZ && (ptr_t)p >= (ptr_t)h + sz) { goto fail; } return(p); --- 165,171 ---- pdispl = HBLKDISPL(p); map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl); if (map_entry == OBJ_INVALID ! || sz > MAXOBJBYTES && (ptr_t)p >= (ptr_t)h + sz) { goto fail; } return(p); diff -Nrc3pad gcc-3.3.3/boehm-gc/reclaim.c gcc-3.4.0/boehm-gc/reclaim.c *** gcc-3.3.3/boehm-gc/reclaim.c 2002-03-29 22:52:12.000000000 +0000 --- gcc-3.4.0/boehm-gc/reclaim.c 2003-07-28 04:18:20.000000000 +0000 *************** signed_word GC_mem_found = 0; *** 27,49 **** /* nonzero. */ #endif /* PARALLEL_MARK */ ! static void report_leak(p, sz) ! ptr_t p; ! word sz; { ! if (HDR(p) -> hb_obj_kind == PTRFREE) { ! GC_err_printf0("Leaked atomic object at "); ! } else { ! GC_err_printf0("Leaked composite object at "); } - GC_print_heap_obj(p); - GC_err_printf0("\n"); } # define FOUND_FREE(hblk, word_no) \ { \ ! report_leak((ptr_t)hblk + WORDS_TO_BYTES(word_no), \ ! HDR(hblk) -> hb_sz); \ } /* --- 27,87 ---- /* nonzero. */ #endif /* PARALLEL_MARK */ ! /* We defer printing of leaked objects until we're done with the GC */ ! /* cycle, since the routine for printing objects needs to run outside */ ! /* the collector, e.g. without the allocation lock. */ ! #define MAX_LEAKED 40 ! ptr_t GC_leaked[MAX_LEAKED]; ! unsigned GC_n_leaked = 0; ! ! GC_bool GC_have_errors = FALSE; ! ! void GC_add_leaked(leaked) ! ptr_t leaked; { ! if (GC_n_leaked < MAX_LEAKED) { ! GC_have_errors = TRUE; ! GC_leaked[GC_n_leaked++] = leaked; ! /* Make sure it's not reclaimed this cycle */ ! GC_set_mark_bit(leaked); } } + static GC_bool printing_errors = FALSE; + /* Print all objects on the list after printing any smashed objs. */ + /* Clear both lists. */ + void GC_print_all_errors () + { + unsigned i; + + LOCK(); + if (printing_errors) { + UNLOCK(); + return; + } + printing_errors = TRUE; + UNLOCK(); + if (GC_debugging_started) GC_print_all_smashed(); + for (i = 0; i < GC_n_leaked; ++i) { + ptr_t p = GC_leaked[i]; + if (HDR(p) -> hb_obj_kind == PTRFREE) { + GC_err_printf0("Leaked atomic object at "); + } else { + GC_err_printf0("Leaked composite object at "); + } + GC_print_heap_obj(p); + GC_err_printf0("\n"); + GC_free(p); + GC_leaked[i] = 0; + } + GC_n_leaked = 0; + printing_errors = FALSE; + } + + # define FOUND_FREE(hblk, word_no) \ { \ ! GC_add_leaked((ptr_t)hblk + WORDS_TO_BYTES(word_no)); \ } /* *************** void GC_print_block_list() *** 866,872 **** * Clear *flp. * This must be done before dropping a list of free gcj-style objects, * since may otherwise end up with dangling "descriptor" pointers. ! * It may help for other pointer-containg objects. */ void GC_clear_fl_links(flp) ptr_t *flp; --- 904,910 ---- * Clear *flp. * This must be done before dropping a list of free gcj-style objects, * since may otherwise end up with dangling "descriptor" pointers. ! * It may help for other pointer-containing objects. */ void GC_clear_fl_links(flp) ptr_t *flp; diff -Nrc3pad gcc-3.3.3/boehm-gc/solaris_pthreads.c gcc-3.4.0/boehm-gc/solaris_pthreads.c *** gcc-3.3.3/boehm-gc/solaris_pthreads.c 2002-02-12 04:37:53.000000000 +0000 --- gcc-3.4.0/boehm-gc/solaris_pthreads.c 2003-07-28 04:18:21.000000000 +0000 *************** *** 13,21 **** /* * Support code for Solaris threads. Provides functionality we wish Sun * had provided. Relies on some information we probably shouldn't rely on. ! * Modified Peter C. for Solaris Posix Threads. */ - /* Boehm, September 14, 1994 4:44 pm PDT */ # if defined(GC_SOLARIS_PTHREADS) # include "private/gc_priv.h" --- 13,20 ---- /* * Support code for Solaris threads. Provides functionality we wish Sun * had provided. Relies on some information we probably shouldn't rely on. ! * Modified by Peter C. for Solaris Posix Threads. */ # if defined(GC_SOLARIS_PTHREADS) # include "private/gc_priv.h" diff -Nrc3pad gcc-3.3.3/boehm-gc/solaris_threads.c gcc-3.4.0/boehm-gc/solaris_threads.c *** gcc-3.3.3/boehm-gc/solaris_threads.c 2002-02-12 04:37:53.000000000 +0000 --- gcc-3.4.0/boehm-gc/solaris_threads.c 2003-07-28 04:18:21.000000000 +0000 *************** *** 37,42 **** --- 37,46 ---- # include # include + #ifdef HANDLE_FORK + --> Not yet supported. Try porting the code from linux_threads.c. + #endif + /* * This is the default size of the LWP arrays. If there are more LWPs * than this when a stop-the-world GC happens, set_max_lwps will be *************** static void restart_all_lwps() *** 361,367 **** sizeof (prgregset_t)) != 0) { int j; ! for(j = 0; j < NGREG; j++) { GC_printf3("%i: %x -> %x\n", j, GC_lwp_registers[i][j], --- 365,371 ---- sizeof (prgregset_t)) != 0) { int j; ! for(j = 0; j < NPRGREG; j++) { GC_printf3("%i: %x -> %x\n", j, GC_lwp_registers[i][j], *************** int GC_thr_suspend(thread_t target_threa *** 821,827 **** if (result == 0) { t = GC_lookup_thread(target_thread); if (t == 0) ABORT("thread unknown to GC"); ! t -> flags |= SUSPENDED; } UNLOCK(); return(result); --- 825,831 ---- if (result == 0) { t = GC_lookup_thread(target_thread); if (t == 0) ABORT("thread unknown to GC"); ! t -> flags |= SUSPNDED; } UNLOCK(); return(result); *************** int GC_thr_continue(thread_t target_thre *** 837,843 **** if (result == 0) { t = GC_lookup_thread(target_thread); if (t == 0) ABORT("thread unknown to GC"); ! t -> flags &= ~SUSPENDED; } UNLOCK(); return(result); --- 841,847 ---- if (result == 0) { t = GC_lookup_thread(target_thread); if (t == 0) ABORT("thread unknown to GC"); ! t -> flags &= ~SUSPNDED; } UNLOCK(); return(result); *************** GC_thr_create(void *stack_base, size_t s *** 923,929 **** my_flags |= CLIENT_OWNS_STACK; } if (flags & THR_DETACHED) my_flags |= DETACHED; ! if (flags & THR_SUSPENDED) my_flags |= SUSPENDED; result = thr_create(stack, stack_size, start_routine, arg, flags & ~THR_DETACHED, &my_new_thread); if (result == 0) { --- 927,933 ---- my_flags |= CLIENT_OWNS_STACK; } if (flags & THR_DETACHED) my_flags |= DETACHED; ! if (flags & THR_SUSPENDED) my_flags |= SUSPNDED; result = thr_create(stack, stack_size, start_routine, arg, flags & ~THR_DETACHED, &my_new_thread); if (result == 0) { diff -Nrc3pad gcc-3.3.3/boehm-gc/sparc_mach_dep.S gcc-3.4.0/boehm-gc/sparc_mach_dep.S *** gcc-3.3.3/boehm-gc/sparc_mach_dep.S 2002-02-15 00:09:29.000000000 +0000 --- gcc-3.4.0/boehm-gc/sparc_mach_dep.S 2003-07-28 04:18:21.000000000 +0000 *************** loop: *** 37,43 **** stx %g0,[%o3] ! *(long *)p = 0 cmp %o3,%o1 bgu,pt %xcc, loop ! if (p > limit) goto loop ! add %o3,-8,%o3 ! p -= 8 (delay slot) retl mov %o2,%sp ! Restore sp., delay slot #else /* 32 bit SPARC */ --- 37,43 ---- stx %g0,[%o3] ! *(long *)p = 0 cmp %o3,%o1 bgu,pt %xcc, loop ! if (p > limit) goto loop ! add %o3,-8,%o3 ! p -= 8 (delay slot) retl mov %o2,%sp ! Restore sp., delay slot #else /* 32 bit SPARC */ diff -Nrc3pad gcc-3.3.3/boehm-gc/tests/test.c gcc-3.4.0/boehm-gc/tests/test.c *** gcc-3.3.3/boehm-gc/tests/test.c 2002-02-12 04:37:57.000000000 +0000 --- gcc-3.4.0/boehm-gc/tests/test.c 2003-07-28 04:18:23.000000000 +0000 *************** *** 43,49 **** # include "gc_local_alloc.h" # endif # include "private/gc_priv.h" /* For output, locking, MIN_WORDS, */ ! /* and some statistics. */ # include "private/gcconfig.h" # if defined(MSWIN32) || defined(MSWINCE) --- 43,49 ---- # include "gc_local_alloc.h" # endif # include "private/gc_priv.h" /* For output, locking, MIN_WORDS, */ ! /* and some statistics. */ # include "private/gcconfig.h" # if defined(MSWIN32) || defined(MSWINCE) *************** *** 68,81 **** # include # endif ! # ifdef GC_WIN32_THREADS ! # ifndef MSWINCE ! # include ! # define GC_CreateThread(a,b,c,d,e,f) ((HANDLE) _beginthreadex(a,b,c,d,e,f)) ! # endif static CRITICAL_SECTION incr_cs; # endif /* Allocation Statistics */ int stubborn_count = 0; --- 68,81 ---- # include # endif ! # if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) static CRITICAL_SECTION incr_cs; # endif + #ifdef __STDC__ + # include + #endif + /* Allocation Statistics */ int stubborn_count = 0; *************** sexpr y; *** 205,244 **** } # endif - sexpr small_cons (x, y) - sexpr x; - sexpr y; - { - register sexpr r; - - collectable_count++; - r = (sexpr) GC_MALLOC(sizeof(struct SEXPR)); - if (r == 0) { - (void)GC_printf0("Out of memory\n"); - exit(1); - } - r -> sexpr_car = x; - r -> sexpr_cdr = y; - return(r); - } - - sexpr small_cons_uncollectable (x, y) - sexpr x; - sexpr y; - { - register sexpr r; - - uncollectable_count++; - r = (sexpr) GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR)); - if (r == 0) { - (void)GC_printf0("Out of memory\n"); - exit(1); - } - r -> sexpr_car = x; - r -> sexpr_cdr = (sexpr)(~(unsigned long)y); - return(r); - } - #ifdef GC_GCJ_SUPPORT #include "gc_mark.h" --- 205,210 ---- *************** struct GC_ms_entry * fake_gcj_mark_proc( *** 279,284 **** --- 245,337 ---- return(mark_stack_ptr); } + #endif /* GC_GCJ_SUPPORT */ + + #ifdef THREAD_LOCAL_ALLOC + + #undef GC_REDIRECT_TO_LOCAL + #include "gc_local_alloc.h" + + sexpr local_cons (x, y) + sexpr x; + sexpr y; + { + register sexpr r; + register int *p; + register int my_extra = extra_count; + static int my_random = 0; + + collectable_count++; + r = (sexpr) GC_LOCAL_MALLOC(sizeof(struct SEXPR) + my_extra); + # ifdef GC_GCJ_SUPPORT + if (collectable_count % 2 == 0) { + r = (sexpr) GC_LOCAL_GCJ_MALLOC(sizeof(struct SEXPR) + sizeof(GC_word) + my_extra, + &gcj_class_struct1); + r = (sexpr) ((GC_word *)r + 1); + } + # endif + if (r == 0) { + (void)GC_printf0("Out of memory\n"); + exit(1); + } + for (p = (int *)r; + ((char *)p) < ((char *)r) + my_extra + sizeof(struct SEXPR); p++) { + if (*p) { + (void)GC_printf1("Found nonzero at 0x%lx (local) - allocator is broken\n", + (unsigned long)p); + FAIL; + } + *p = 13; + } + r -> sexpr_car = x; + r -> sexpr_cdr = y; + my_extra++; + if ( my_extra >= 5000 || my_extra == 200 && ++my_random % 37 != 0) { + extra_count = 0; + } else { + extra_count = my_extra; + } + return(r); + } + #endif /* THREAD_LOCAL_ALLOC */ + + sexpr small_cons (x, y) + sexpr x; + sexpr y; + { + register sexpr r; + + collectable_count++; + r = (sexpr) GC_MALLOC(sizeof(struct SEXPR)); + if (r == 0) { + (void)GC_printf0("Out of memory\n"); + exit(1); + } + r -> sexpr_car = x; + r -> sexpr_cdr = y; + return(r); + } + + sexpr small_cons_uncollectable (x, y) + sexpr x; + sexpr y; + { + register sexpr r; + + uncollectable_count++; + r = (sexpr) GC_MALLOC_UNCOLLECTABLE(sizeof(struct SEXPR)); + if (r == 0) { + (void)GC_printf0("Out of memory\n"); + exit(1); + } + r -> sexpr_car = x; + r -> sexpr_cdr = (sexpr)(~(unsigned long)y); + return(r); + } + + #ifdef GC_GCJ_SUPPORT + + sexpr gcj_cons(x, y) sexpr x; sexpr y; *************** sexpr x, y; *** 323,328 **** --- 376,384 ---- sexpr reverse(x) sexpr x; { + # ifdef TEST_WITH_SYSTEM_MALLOC + malloc(100000); + # endif return( reverse1(x, nil) ); } *************** int low, up; *** 365,370 **** --- 421,455 ---- } #endif /* GC_GCJ_SUPPORT */ + #ifdef THREAD_LOCAL_ALLOC + /* Return reverse(x) concatenated with y */ + sexpr local_reverse1(x, y) + sexpr x, y; + { + if (is_nil(x)) { + return(y); + } else { + return( local_reverse1(cdr(x), local_cons(car(x), y)) ); + } + } + + sexpr local_reverse(x) + sexpr x; + { + return( local_reverse1(x, nil) ); + } + + sexpr local_ints(low, up) + int low, up; + { + if (low > up) { + return(nil); + } else { + return(local_cons(local_cons(INT_TO_SEXPR(low), nil), local_ints(low+1, up))); + } + } + #endif /* THREAD_LOCAL_ALLOC */ + /* To check uncollectable allocation we build lists with disguised cdr */ /* pointers, and make sure they don't go away. */ sexpr uncollectable_ints(low, up) *************** sexpr x; *** 435,459 **** } } - /* Try to force a to be strangely aligned */ - struct { - char dummy; - sexpr aa; - } A; - #define a A.aa - /* * A tiny list reversal test to check thread creation. */ #ifdef THREADS ! # ifdef GC_WIN32_THREADS ! unsigned __stdcall tiny_reverse_test(void * arg) # else void * tiny_reverse_test(void * arg) # endif { ! check_ints(reverse(reverse(ints(1,10))), 1, 10); return 0; } --- 520,543 ---- } } /* * A tiny list reversal test to check thread creation. */ #ifdef THREADS ! # if defined(GC_WIN32_THREADS) && !defined(CYGWIN32) ! DWORD __stdcall tiny_reverse_test(void * arg) # else void * tiny_reverse_test(void * arg) # endif { ! int i; ! for (i = 0; i < 5; ++i) { ! check_ints(reverse(reverse(ints(1,10))), 1, 10); ! # ifdef THREAD_LOCAL_ALLOC ! check_ints(local_reverse(local_reverse(local_ints(1,10))), 1, 10); ! # endif ! } return 0; } *************** struct { *** 477,483 **** # elif defined(GC_WIN32_THREADS) void fork_a_thread() { ! unsigned thread_id; HANDLE h; h = GC_CreateThread(NULL, 0, tiny_reverse_test, 0, 0, &thread_id); if (h == (HANDLE)NULL) { --- 561,567 ---- # elif defined(GC_WIN32_THREADS) void fork_a_thread() { ! DWORD thread_id; HANDLE h; h = GC_CreateThread(NULL, 0, tiny_reverse_test, 0, 0, &thread_id); if (h == (HANDLE)NULL) { *************** struct { *** 506,511 **** --- 590,602 ---- #endif + /* Try to force a to be strangely aligned */ + struct { + char dummy; + sexpr aa; + } A; + #define a A.aa + /* * Repeatedly reverse lists built out of very different sized cons cells. * Check that we didn't lose anything. *************** void reverse_test() *** 563,569 **** h = (sexpr *)GC_REALLOC((GC_PTR)h, 2000 * sizeof(sexpr)); # ifdef GC_GCJ_SUPPORT h[1999] = gcj_ints(1,200); ! h[1999] = gcj_reverse(h[1999]); # else h[1999] = ints(1,200); # endif --- 654,662 ---- h = (sexpr *)GC_REALLOC((GC_PTR)h, 2000 * sizeof(sexpr)); # ifdef GC_GCJ_SUPPORT h[1999] = gcj_ints(1,200); ! for (i = 0; i < 51; ++i) ! h[1999] = gcj_reverse(h[1999]); ! /* Leave it as the reveresed list for now. */ # else h[1999] = ints(1,200); # endif *************** void reverse_test() *** 594,599 **** --- 687,695 ---- /* 49 integers. Thus this is thread safe without locks, */ /* assuming atomic pointer assignments. */ a = reverse(reverse(a)); + # ifdef THREAD_LOCAL_ALLOC + a = local_reverse(local_reverse(a)); + # endif # if !defined(AT_END) && !defined(THREADS) /* This is not thread safe, since realloc explicitly deallocates */ if (i & 1) { *************** void reverse_test() *** 621,626 **** --- 717,724 ---- b = c = 0; } + #undef a + /* * The rest of this builds balanced binary trees, checks that they don't * disappear, and tests finalization. *************** VOLATILE int dropped_something = 0; *** 655,669 **** # if defined(GC_PTHREADS) static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&incr_lock); ! # endif ! # ifdef GC_WIN32_THREADS ! EnterCriticalSection(&incr_cs); # endif if ((int)(GC_word)client_data != t -> level) { (void)GC_printf0("Wrong finalization data - collector is broken\n"); FAIL; } finalized_count++; # ifdef PCR PCR_ThCrSec_ExitSys(); # endif --- 753,769 ---- # if defined(GC_PTHREADS) static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&incr_lock); ! # else ! # ifdef GC_WIN32_THREADS ! EnterCriticalSection(&incr_cs); ! # endif # endif if ((int)(GC_word)client_data != t -> level) { (void)GC_printf0("Wrong finalization data - collector is broken\n"); FAIL; } finalized_count++; + t -> level = -1; /* detect duplicate finalization immediately */ # ifdef PCR PCR_ThCrSec_ExitSys(); # endif *************** VOLATILE int dropped_something = 0; *** 672,680 **** # endif # if defined(GC_PTHREADS) pthread_mutex_unlock(&incr_lock); ! # endif ! # ifdef GC_WIN32_THREADS ! LeaveCriticalSection(&incr_cs); # endif } --- 772,781 ---- # endif # if defined(GC_PTHREADS) pthread_mutex_unlock(&incr_lock); ! # else ! # ifdef GC_WIN32_THREADS ! LeaveCriticalSection(&incr_cs); ! # endif # endif } *************** int n; *** 746,754 **** # if defined(GC_PTHREADS) static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&incr_lock); ! # endif ! # ifdef GC_WIN32_THREADS ! EnterCriticalSection(&incr_cs); # endif /* Losing a count here causes erroneous report of failure. */ finalizable_count++; --- 847,856 ---- # if defined(GC_PTHREADS) static pthread_mutex_t incr_lock = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&incr_lock); ! # else ! # ifdef GC_WIN32_THREADS ! EnterCriticalSection(&incr_cs); ! # endif # endif /* Losing a count here causes erroneous report of failure. */ finalizable_count++; *************** int n; *** 761,769 **** # endif # if defined(GC_PTHREADS) pthread_mutex_unlock(&incr_lock); ! # endif ! # ifdef GC_WIN32_THREADS ! LeaveCriticalSection(&incr_cs); # endif } --- 863,872 ---- # endif # if defined(GC_PTHREADS) pthread_mutex_unlock(&incr_lock); ! # else ! # ifdef GC_WIN32_THREADS ! LeaveCriticalSection(&incr_cs); ! # endif # endif } *************** void fail_proc1(GC_PTR x) *** 1068,1073 **** --- 1171,1195 ---- fail_count++; } + static void uniq(void *p, ...) { + va_list a; + void *q[100]; + int n = 0, i, j; + q[n++] = p; + va_start(a,p); + for (;(q[n] = va_arg(a,void *));n++) ; + va_end(a); + for (i=0; i 4) { ! max_heap_sz = 15000000; } else { max_heap_sz = 11000000; } --- 1361,1367 ---- } # else if (sizeof(char *) > 4) { ! max_heap_sz = 19000000; } else { max_heap_sz = 11000000; } *************** void check_heap_stats() *** 1212,1218 **** # ifdef SAVE_CALL_CHAIN max_heap_sz *= 3; # ifdef SAVE_CALL_COUNT ! max_heap_sz *= SAVE_CALL_COUNT/4; # endif # endif # endif --- 1371,1377 ---- # ifdef SAVE_CALL_CHAIN max_heap_sz *= 3; # ifdef SAVE_CALL_COUNT ! max_heap_sz += max_heap_sz * SAVE_CALL_COUNT/4; # endif # endif # endif *************** void SetMinimumStack(long minSize) *** 1327,1332 **** --- 1486,1495 ---- # endif n_tests = 0; + #if defined(__APPLE__) && defined(__MACH__) + GC_INIT(); + #endif + # if defined(DJGPP) /* No good way to determine stack base from library; do it */ /* manually on this platform. */ *************** void SetMinimumStack(long minSize) *** 1340,1352 **** # endif GC_INIT(); /* Only needed if gc is dynamic library. */ (void) GC_set_warn_proc(warn_proc); ! # if (defined(MPROTECT_VDB) || defined(PROC_VDB)) && !defined(MAKE_BACK_GRAPH) GC_enable_incremental(); (void) GC_printf0("Switched to incremental mode\n"); # if defined(MPROTECT_VDB) (void)GC_printf0("Emulating dirty bits with mprotect/signals\n"); # else (void)GC_printf0("Reading dirty bits from /proc\n"); # endif # endif run_one_test(); --- 1503,1520 ---- # endif GC_INIT(); /* Only needed if gc is dynamic library. */ (void) GC_set_warn_proc(warn_proc); ! # if (defined(MPROTECT_VDB) || defined(PROC_VDB)) \ ! && !defined(MAKE_BACK_GRAPH) GC_enable_incremental(); (void) GC_printf0("Switched to incremental mode\n"); # if defined(MPROTECT_VDB) (void)GC_printf0("Emulating dirty bits with mprotect/signals\n"); # else + # ifdef PROC_VDB (void)GC_printf0("Reading dirty bits from /proc\n"); + # else + (void)GC_printf0("Using DEFAULT_VDB dirty bit implementation\n"); + # endif # endif # endif run_one_test(); *************** void SetMinimumStack(long minSize) *** 1378,1386 **** } # endif ! #ifdef GC_WIN32_THREADS ! unsigned __stdcall thr_run_one_test(void *arg) { run_one_test(); return 0; --- 1546,1554 ---- } # endif ! #if defined(GC_WIN32_THREADS) && !defined(CYGWIN32) ! DWORD __stdcall thr_run_one_test(void *arg) { run_one_test(); return 0; *************** LRESULT CALLBACK window_proc(HWND hwnd, *** 1412,1418 **** return ret; } ! unsigned __stdcall thr_window(void *arg) { WNDCLASS win_class = { CS_NOCLOSE, --- 1580,1586 ---- return ret; } ! DWORD __stdcall thr_window(void *arg) { WNDCLASS win_class = { CS_NOCLOSE, *************** int APIENTRY WinMain(HINSTANCE instance, *** 1474,1483 **** # ifdef MSWINCE HANDLE win_thr_h; # endif ! unsigned thread_id; # if 0 GC_enable_incremental(); # endif InitializeCriticalSection(&incr_cs); (void) GC_set_warn_proc(warn_proc); # ifdef MSWINCE --- 1642,1652 ---- # ifdef MSWINCE HANDLE win_thr_h; # endif ! DWORD thread_id; # if 0 GC_enable_incremental(); # endif + GC_init(); InitializeCriticalSection(&incr_cs); (void) GC_set_warn_proc(warn_proc); # ifdef MSWINCE *************** main() *** 1625,1639 **** (void)GC_printf0("pthread_default_stacksize_np failed.\n"); } # endif /* GC_HPUX_THREADS */ pthread_attr_init(&attr); ! # if defined(GC_IRIX_THREADS) || defined(GC_FREEBSD_THREADS) pthread_attr_setstacksize(&attr, 1000000); # endif n_tests = 0; ! # if defined(MPROTECT_VDB) && !defined(PARALLEL_MARK) &&!defined(REDIRECT_MALLOC) && !defined(MAKE_BACK_GRAPH) GC_enable_incremental(); (void) GC_printf0("Switched to incremental mode\n"); ! (void) GC_printf0("Emulating dirty bits with mprotect/signals\n"); # endif (void) GC_set_warn_proc(warn_proc); if ((code = pthread_key_create(&fl_key, 0)) != 0) { --- 1794,1823 ---- (void)GC_printf0("pthread_default_stacksize_np failed.\n"); } # endif /* GC_HPUX_THREADS */ + # if defined(__APPLE__) && defined(__MACH__) + GC_INIT(); + # endif + pthread_attr_init(&attr); ! # if defined(GC_IRIX_THREADS) || defined(GC_FREEBSD_THREADS) \ ! || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS) pthread_attr_setstacksize(&attr, 1000000); # endif n_tests = 0; ! # if (defined(MPROTECT_VDB)) \ ! && !defined(PARALLEL_MARK) &&!defined(REDIRECT_MALLOC) \ ! && !defined(MAKE_BACK_GRAPH) GC_enable_incremental(); (void) GC_printf0("Switched to incremental mode\n"); ! # if defined(MPROTECT_VDB) ! (void)GC_printf0("Emulating dirty bits with mprotect/signals\n"); ! # else ! # ifdef PROC_VDB ! (void)GC_printf0("Reading dirty bits from /proc\n"); ! # else ! (void)GC_printf0("Using DEFAULT_VDB dirty bit implementation\n"); ! # endif ! # endif # endif (void) GC_set_warn_proc(warn_proc); if ((code = pthread_key_create(&fl_key, 0)) != 0) { diff -Nrc3pad gcc-3.3.3/boehm-gc/tests/test_cpp.cc gcc-3.4.0/boehm-gc/tests/test_cpp.cc *** gcc-3.3.3/boehm-gc/tests/test_cpp.cc 2001-08-17 18:30:51.000000000 +0000 --- gcc-3.4.0/boehm-gc/tests/test_cpp.cc 2003-07-28 04:18:23.000000000 +0000 *************** few minutes to complete. *** 28,34 **** #include #include #include ! #ifdef __GNUC__ # include "new_gc_alloc.h" #else # include "gc_alloc.h" --- 28,37 ---- #include #include #include ! #define USE_STD_ALLOCATOR ! #ifdef USE_STD_ALLOCATOR ! # include "gc_allocator.h" ! #elif __GNUC__ # include "new_gc_alloc.h" #else # include "gc_alloc.h" *************** int APIENTRY WinMain( *** 189,213 **** # endif #endif # if defined(MACOS) // MacOS char* argv_[] = {"test_cpp", "10"}; // doesn't argv = argv_; // have a argc = sizeof(argv_)/sizeof(argv_[0]); // commandline # endif int i, iters, n; ! # if !defined(MACOS) # ifdef __GNUC__ ! int *x = (int *)gc_alloc::allocate(sizeof(int)); # else ! int *x = (int *)alloc::allocate(sizeof(int)); # endif ! ! *x = 29; ! x -= 3; # endif if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) { ! GC_printf0( "usage: test_cpp number-of-iterations\n" ); ! exit( 1 );} for (iters = 1; iters <= n; iters++) { GC_printf1( "Starting iteration %d\n", iters ); --- 192,223 ---- # endif #endif + GC_init(); + # if defined(MACOS) // MacOS char* argv_[] = {"test_cpp", "10"}; // doesn't argv = argv_; // have a argc = sizeof(argv_)/sizeof(argv_[0]); // commandline # endif int i, iters, n; ! # ifdef USE_STD_ALLOCATOR ! int *x = gc_allocator().allocate(1); ! int **xptr = traceable_allocator().allocate(1); ! # else # ifdef __GNUC__ ! int *x = (int *)gc_alloc::allocate(sizeof(int)); # else ! int *x = (int *)alloc::allocate(sizeof(int)); # endif ! # endif ! *x = 29; ! # ifdef USE_STD_ALLOCATOR ! *xptr = x; ! x = 0; # endif if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) { ! GC_printf0( "usage: test_cpp number-of-iterations\nAssuming 10 iters\n" ); ! n = 10;} for (iters = 1; iters <= n; iters++) { GC_printf1( "Starting iteration %d\n", iters ); *************** int APIENTRY WinMain( *** 268,276 **** D::Test(); F::Test();} ! # if !defined(__GNUC__) && !defined(MACOS) ! my_assert (29 == x[3]); # endif GC_printf0( "The test appears to have succeeded.\n" ); return( 0 );} --- 278,287 ---- D::Test(); F::Test();} ! # ifdef USE_STD_ALLOCATOR ! x = *xptr; # endif + my_assert (29 == x[0]); GC_printf0( "The test appears to have succeeded.\n" ); return( 0 );} diff -Nrc3pad gcc-3.3.3/boehm-gc/threadlibs.c gcc-3.4.0/boehm-gc/threadlibs.c *** gcc-3.3.3/boehm-gc/threadlibs.c 2002-02-12 04:37:53.000000000 +0000 --- gcc-3.4.0/boehm-gc/threadlibs.c 2003-07-28 04:18:21.000000000 +0000 *************** *** 4,16 **** int main() { # if defined(GC_USE_LD_WRAP) ! printf("-Wl,--wrap -Wl,read -Wl,--wrap -Wl,dlopen " "-Wl,--wrap -Wl,pthread_create -Wl,--wrap -Wl,pthread_join " "-Wl,--wrap -Wl,pthread_detach " "-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,sleep\n"); # endif # if defined(GC_LINUX_THREADS) || defined(GC_IRIX_THREADS) \ ! || defined(GC_FREEBSD_THREADS) || defined(GC_SOLARIS_PTHREADS) printf("-lpthread\n"); # endif # if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) --- 4,17 ---- int main() { # if defined(GC_USE_LD_WRAP) ! printf("-Wl,--wrap -Wl,dlopen " "-Wl,--wrap -Wl,pthread_create -Wl,--wrap -Wl,pthread_join " "-Wl,--wrap -Wl,pthread_detach " "-Wl,--wrap -Wl,pthread_sigmask -Wl,--wrap -Wl,sleep\n"); # endif # if defined(GC_LINUX_THREADS) || defined(GC_IRIX_THREADS) \ ! || defined(GC_FREEBSD_THREADS) || defined(GC_SOLARIS_PTHREADS) \ ! || defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS) printf("-lpthread\n"); # endif # if defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) *************** int main() *** 19,24 **** --- 20,36 ---- # if defined(GC_SOLARIS_THREADS) && !defined(GC_SOLARIS_PTHREADS) printf("-lthread -ldl\n"); # endif + # if defined(GC_WIN32_THREADS) && defined(CYGWIN32) + printf("-lpthread\n"); + # endif + # if defined(GC_OSF1_THREADS) + printf("-pthread -lrt"); /* DOB: must be -pthread, not -lpthread */ + # endif + /* You need GCC 3.0.3 to build this one! */ + /* DG/UX native gcc doesnt know what "-pthread" is */ + # if defined(GC_DGUX386_THREADS) + printf("-ldl -pthread\n"); + # endif return 0; } diff -Nrc3pad gcc-3.3.3/boehm-gc/typd_mlc.c gcc-3.4.0/boehm-gc/typd_mlc.c *** gcc-3.3.3/boehm-gc/typd_mlc.c 2001-08-17 18:30:46.000000000 +0000 --- gcc-3.4.0/boehm-gc/typd_mlc.c 2003-07-28 04:18:21.000000000 +0000 *************** void GC_init_explicit_typing() *** 437,442 **** --- 437,443 ---- for (; bm != 0; bm >>= 1, current_p++) { if (bm & 1) { current = *current_p; + FIXUP_POINTER(current); if ((ptr_t)current >= least_ha && (ptr_t)current <= greatest_ha) { PUSH_CONTENTS((ptr_t)current, mark_stack_ptr, mark_stack_limit, current_p, exit1); *************** DCL_LOCK_STATE; *** 674,682 **** if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) { FASTUNLOCK(); op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind); ! if (0 == op) return(0); # ifdef MERGE_SIZES ! lw = GC_size_map[lb]; /* May have been uninitialized. */ # endif } else { *opp = obj_link(op); --- 675,683 ---- if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) { FASTUNLOCK(); op = (ptr_t)GENERAL_MALLOC((word)lb, GC_explicit_kind); ! if (0 == op) return 0; # ifdef MERGE_SIZES ! lw = GC_size_map[lb]; /* May have been uninitialized. */ # endif } else { *opp = obj_link(op); *************** DCL_LOCK_STATE; *** 720,726 **** FASTUNLOCK(); op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind); # ifdef MERGE_SIZES ! lw = GC_size_map[lb]; /* May have been uninitialized. */ # endif } else { *opp = obj_link(op); --- 721,727 ---- FASTUNLOCK(); op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind); # ifdef MERGE_SIZES ! lw = GC_size_map[lb]; /* May have been uninitialized. */ # endif } else { *opp = obj_link(op); diff -Nrc3pad gcc-3.3.3/boehm-gc/version.h gcc-3.4.0/boehm-gc/version.h *** gcc-3.3.3/boehm-gc/version.h 2002-02-12 04:37:53.000000000 +0000 --- gcc-3.4.0/boehm-gc/version.h 2003-07-28 04:18:21.000000000 +0000 *************** *** 1,11 **** ! #define GC_VERSION_MAJOR 6 ! #define GC_VERSION_MINOR 1 ! #define GC_ALPHA_VERSION 3 # define GC_NOT_ALPHA 0xff #ifndef GC_NO_VERSION_VAR ! unsigned GC_version = ((GC_VERSION_MAJOR << 16) | (GC_VERSION_MINOR << 8) | GC_ALPHA_VERSION); #endif /* GC_NO_VERSION_VAR */ --- 1,30 ---- ! /* The version here should match that in configure/configure.in */ ! /* Eventually this one may become unnecessary. For now we need */ ! /* it to keep the old-style build process working. */ ! #define GC_TMP_VERSION_MAJOR 6 ! #define GC_TMP_VERSION_MINOR 3 ! #define GC_TMP_ALPHA_VERSION 1 + #ifndef GC_NOT_ALPHA # define GC_NOT_ALPHA 0xff + #endif + + #if defined(GC_VERSION_MAJOR) + # if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR || \ + GC_TMP_VERSION_MINOR != GC_VERSION_MINOR || \ + defined(GC_ALPHA_VERSION) != (GC_TMP_ALPHA_VERSION != GC_NOT_ALPHA) || \ + defined(GC_ALPHA_VERSION) && GC_TMP_ALPHA_VERSION != GC_ALPHA_VERSION + # error Inconsistent version info. Check version.h and configure.in. + # endif + #else + # define GC_VERSION_MAJOR GC_TMP_VERSION_MAJOR + # define GC_VERSION_MINOR GC_TMP_VERSION_MINOR + # define GC_ALPHA_VERSION GC_TMP_ALPHA_VERSION + #endif + #ifndef GC_NO_VERSION_VAR ! unsigned GC_version = ((GC_VERSION_MAJOR << 16) | (GC_VERSION_MINOR << 8) | GC_TMP_ALPHA_VERSION); #endif /* GC_NO_VERSION_VAR */ diff -Nrc3pad gcc-3.3.3/boehm-gc/win32_threads.c gcc-3.4.0/boehm-gc/win32_threads.c *** gcc-3.3.3/boehm-gc/win32_threads.c 2003-04-28 20:55:07.000000000 +0000 --- gcc-3.4.0/boehm-gc/win32_threads.c 2003-10-03 18:43:06.000000000 +0000 *************** *** 1,34 **** ! #if defined(GC_WIN32_THREADS) #include "private/gc_priv.h" - - #if 0 - #define STRICT #include #endif ! #define MAX_THREADS 64 ! struct thread_entry { ! LONG in_use; DWORD id; HANDLE handle; ! void *stack; /* The cold end of the stack. */ /* 0 ==> entry not valid. */ ! /* !in_use ==> stack == 0 */ ! CONTEXT context; GC_bool suspended; }; volatile GC_bool GC_please_stop = FALSE; ! volatile struct thread_entry thread_table[MAX_THREADS]; void GC_push_thread_structures GC_PROTO((void)) { /* Unlike the other threads implementations, the thread table here */ /* contains no pointers to the collectable heap. Thus we have */ /* no private structures we need to preserve. */ } void GC_stop_world() --- 1,234 ---- ! #if defined(GC_WIN32_THREADS) #include "private/gc_priv.h" #include + + #ifdef CYGWIN32 + # include + + /* Cygwin-specific forward decls */ + # undef pthread_create + # undef pthread_sigmask + # undef pthread_join + # undef dlopen + + # define DEBUG_CYGWIN_THREADS 0 + + void * GC_start_routine(void * arg); + void GC_thread_exit_proc(void *arg); + #endif ! /* The type of the first argument to InterlockedExchange. */ ! /* Documented to be LONG volatile *, but at least gcc likes */ ! /* this better. */ ! typedef LONG * IE_t; ! #ifndef MAX_THREADS ! # define MAX_THREADS 256 ! /* FIXME: */ ! /* Things may get quite slow for large numbers of threads, */ ! /* since we look them up with sequential search. */ ! #endif ! ! GC_bool GC_thr_initialized = FALSE; ! ! DWORD GC_main_thread = 0; ! ! struct GC_thread_Rep { ! LONG in_use; /* Updated without lock. */ ! /* We assert that unused */ ! /* entries have invalid ids of */ ! /* zero and zero stack fields. */ DWORD id; HANDLE handle; ! ptr_t stack_base; /* The cold end of the stack. */ /* 0 ==> entry not valid. */ ! /* !in_use ==> stack_base == 0 */ GC_bool suspended; + + # ifdef CYGWIN32 + void *status; /* hold exit value until join in case it's a pointer */ + pthread_t pthread_id; + short flags; /* Protected by GC lock. */ + # define FINISHED 1 /* Thread has exited. */ + # define DETACHED 2 /* Thread is intended to be detached. */ + # endif }; + typedef volatile struct GC_thread_Rep * GC_thread; + + /* + * We generally assume that volatile ==> memory ordering, at least among + * volatiles. + */ + volatile GC_bool GC_please_stop = FALSE; ! volatile struct GC_thread_Rep thread_table[MAX_THREADS]; ! ! volatile LONG GC_max_thread_index = 0; /* Largest index in thread_table */ ! /* that was ever used. */ ! ! extern LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info); ! ! /* ! * This may be called from DllMain, and hence operates under unusual ! * constraints. ! */ ! static GC_thread GC_new_thread(void) { ! int i; ! /* It appears to be unsafe to acquire a lock here, since this */ ! /* code is apparently not preeemptible on some systems. */ ! /* (This is based on complaints, not on Microsoft's official */ ! /* documentation, which says this should perform "only simple */ ! /* initialization tasks".) */ ! /* Hence we make do with nonblocking synchronization. */ ! ! /* The following should be a noop according to the win32 */ ! /* documentation. There is empirical evidence that it */ ! /* isn't. - HB */ ! # if defined(MPROTECT_VDB) ! if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler); ! # endif ! /* cast away volatile qualifier */ ! for (i = 0; InterlockedExchange((IE_t)&thread_table[i].in_use,1) != 0; i++) { ! /* Compare-and-swap would make this cleaner, but that's not */ ! /* supported before Windows 98 and NT 4.0. In Windows 2000, */ ! /* InterlockedExchange is supposed to be replaced by */ ! /* InterlockedExchangePointer, but that's not really what I */ ! /* want here. */ ! if (i == MAX_THREADS - 1) ! ABORT("too many threads"); ! } ! /* Update GC_max_thread_index if necessary. The following is safe, */ ! /* and unlike CompareExchange-based solutions seems to work on all */ ! /* Windows95 and later platforms. */ ! /* Unfortunately, GC_max_thread_index may be temporarily out of */ ! /* bounds, so readers have to compensate. */ ! while (i > GC_max_thread_index) { ! InterlockedIncrement((IE_t)&GC_max_thread_index); ! } ! if (GC_max_thread_index >= MAX_THREADS) { ! /* We overshot due to simultaneous increments. */ ! /* Setting it to MAX_THREADS-1 is always safe. */ ! GC_max_thread_index = MAX_THREADS - 1; ! } ! ! # ifdef CYGWIN32 ! thread_table[i].pthread_id = pthread_self(); ! # endif ! if (!DuplicateHandle(GetCurrentProcess(), ! GetCurrentThread(), ! GetCurrentProcess(), ! (HANDLE*)&thread_table[i].handle, ! 0, ! 0, ! DUPLICATE_SAME_ACCESS)) { ! DWORD last_error = GetLastError(); ! GC_printf1("Last error code: %lx\n", last_error); ! ABORT("DuplicateHandle failed"); ! } ! thread_table[i].stack_base = GC_get_stack_base(); ! /* Up until this point, GC_psuh_all_stacks considers this thread */ ! /* invalid. */ ! if (thread_table[i].stack_base == NULL) ! ABORT("Failed to find stack base in GC_new_thread"); ! /* Up until this point, this entry is viewed as reserved but invalid */ ! /* by GC_delete_thread. */ ! thread_table[i].id = GetCurrentThreadId(); ! /* If this thread is being created while we are trying to stop */ ! /* the world, wait here. Hopefully this can't happen on any */ ! /* systems that don't allow us to block here. */ ! while (GC_please_stop) Sleep(20); ! return thread_table + i; ! } ! ! /* ! * GC_max_thread_index may temporarily be larger than MAX_THREADS. ! * To avoid subscript errors, we check on access. ! */ ! #ifdef __GNUC__ ! __inline__ ! #endif ! LONG GC_get_max_thread_index() ! { ! LONG my_max = GC_max_thread_index; ! ! if (my_max >= MAX_THREADS) return MAX_THREADS-1; ! return my_max; ! } ! ! /* This is intended to be lock-free, though that */ ! /* assumes that the CloseHandle becomes visible before the */ ! /* in_use assignment. */ ! static void GC_delete_gc_thread(GC_thread thr) ! { ! CloseHandle(thr->handle); ! /* cast away volatile qualifier */ ! thr->stack_base = 0; ! thr->id = 0; ! # ifdef CYGWIN32 ! thr->pthread_id = 0; ! # endif /* CYGWIN32 */ ! thr->in_use = FALSE; ! } ! ! static void GC_delete_thread(DWORD thread_id) { ! int i; ! LONG my_max = GC_get_max_thread_index(); ! ! for (i = 0; ! i <= my_max && ! (!thread_table[i].in_use || thread_table[i].id != thread_id); ! /* Must still be in_use, since nobody else can store our thread_id. */ ! i++) {} ! if (i > my_max) { ! WARN("Removing nonexisiting thread %ld\n", (GC_word)thread_id); ! } else { ! GC_delete_gc_thread(thread_table+i); ! } ! } ! ! ! #ifdef CYGWIN32 ! ! /* Return a GC_thread corresponding to a given pthread_t. */ ! /* Returns 0 if it's not there. */ ! /* We assume that this is only called for pthread ids that */ ! /* have not yet terminated or are still joinable. */ ! static GC_thread GC_lookup_thread(pthread_t id) ! { ! int i; ! LONG my_max = GC_get_max_thread_index(); ! ! for (i = 0; ! i <= my_max && ! (!thread_table[i].in_use || thread_table[i].pthread_id != id ! || !thread_table[i].in_use); ! /* Must still be in_use, since nobody else can store our thread_id. */ ! i++); ! if (i > my_max) return 0; ! return thread_table + i; ! } ! ! #endif /* CYGWIN32 */ void GC_push_thread_structures GC_PROTO((void)) { /* Unlike the other threads implementations, the thread table here */ /* contains no pointers to the collectable heap. Thus we have */ /* no private structures we need to preserve. */ + # ifdef CYGWIN32 + { int i; /* pthreads may keep a pointer in the thread exit value */ + LONG my_max = GC_get_max_thread_index(); + + for (i = 0; i <= my_max; i++) + if (thread_table[i].in_use) + GC_push_all((ptr_t)&(thread_table[i].status), + (ptr_t)(&(thread_table[i].status)+1)); + } + # endif } void GC_stop_world() *************** void GC_stop_world() *** 36,44 **** DWORD thread_id = GetCurrentThreadId(); int i; GC_please_stop = TRUE; ! for (i = 0; i < MAX_THREADS; i++) ! if (thread_table[i].stack != 0 && thread_table[i].id != thread_id) { # ifdef MSWINCE /* SuspendThread will fail if thread is running kernel code */ --- 236,246 ---- DWORD thread_id = GetCurrentThreadId(); int i; + if (!GC_thr_initialized) ABORT("GC_stop_world() called before GC_thr_init()"); + GC_please_stop = TRUE; ! for (i = 0; i <= GC_get_max_thread_index(); i++) ! if (thread_table[i].stack_base != 0 && thread_table[i].id != thread_id) { # ifdef MSWINCE /* SuspendThread will fail if thread is running kernel code */ *************** void GC_stop_world() *** 53,63 **** DWORD exitCode; if (GetExitCodeThread(thread_table[i].handle,&exitCode) && exitCode != STILL_ACTIVE) { ! thread_table[i].stack = 0; thread_table[i].in_use = FALSE; CloseHandle(thread_table[i].handle); ! BZERO((void *)(&thread_table[i].context), sizeof(CONTEXT)); ! continue; } if (SuspendThread(thread_table[i].handle) == (DWORD)-1) ABORT("SuspendThread failed"); --- 255,268 ---- DWORD exitCode; if (GetExitCodeThread(thread_table[i].handle,&exitCode) && exitCode != STILL_ACTIVE) { ! thread_table[i].stack_base = 0; /* prevent stack from being pushed */ ! # ifndef CYGWIN32 ! /* this breaks pthread_join on Cygwin, which is guaranteed to */ ! /* only see user pthreads */ thread_table[i].in_use = FALSE; CloseHandle(thread_table[i].handle); ! # endif ! continue; } if (SuspendThread(thread_table[i].handle) == (DWORD)-1) ABORT("SuspendThread failed"); *************** void GC_start_world() *** 70,77 **** { DWORD thread_id = GetCurrentThreadId(); int i; ! for (i = 0; i < MAX_THREADS; i++) ! if (thread_table[i].stack != 0 && thread_table[i].suspended && thread_table[i].id != thread_id) { if (ResumeThread(thread_table[i].handle) == (DWORD)-1) ABORT("ResumeThread failed"); --- 275,284 ---- { DWORD thread_id = GetCurrentThreadId(); int i; ! LONG my_max = GC_get_max_thread_index(); ! ! for (i = 0; i <= my_max; i++) ! if (thread_table[i].stack_base != 0 && thread_table[i].suspended && thread_table[i].id != thread_id) { if (ResumeThread(thread_table[i].handle) == (DWORD)-1) ABORT("ResumeThread failed"); *************** ptr_t GC_current_stackbottom() *** 87,95 **** { DWORD thread_id = GetCurrentThreadId(); int i; ! for (i = 0; i < MAX_THREADS; i++) ! if (thread_table[i].stack && thread_table[i].id == thread_id) ! return thread_table[i].stack; ABORT("no thread table entry for current thread"); } # ifdef _MSC_VER --- 294,304 ---- { DWORD thread_id = GetCurrentThreadId(); int i; ! LONG my_max = GC_get_max_thread_index(); ! ! for (i = 0; i <= my_max; i++) ! if (thread_table[i].stack_base && thread_table[i].id == thread_id) ! return thread_table[i].stack_base; ABORT("no thread table entry for current thread"); } # ifdef _MSC_VER *************** ptr_t GC_current_stackbottom() *** 100,109 **** /* The VirtualQuery calls below won't work properly on WinCE, but */ /* since each stack is restricted to an aligned 64K region of */ /* virtual memory we can just take the next lowest multiple of 64K. */ ! # define GC_get_lo_stack_addr(s) \ ((ptr_t)(((DWORD)(s) - 1) & 0xFFFF0000)) # else ! static ptr_t GC_get_lo_stack_addr(ptr_t s) { ptr_t bottom; MEMORY_BASIC_INFORMATION info; --- 309,318 ---- /* The VirtualQuery calls below won't work properly on WinCE, but */ /* since each stack is restricted to an aligned 64K region of */ /* virtual memory we can just take the next lowest multiple of 64K. */ ! # define GC_get_stack_min(s) \ ((ptr_t)(((DWORD)(s) - 1) & 0xFFFF0000)) # else ! static ptr_t GC_get_stack_min(ptr_t s) { ptr_t bottom; MEMORY_BASIC_INFORMATION info; *************** ptr_t GC_current_stackbottom() *** 120,316 **** void GC_push_all_stacks() { DWORD thread_id = GetCurrentThreadId(); int i; ! for (i = 0; i < MAX_THREADS; i++) ! if (thread_table[i].stack) { ! ptr_t bottom = GC_get_lo_stack_addr(thread_table[i].stack); ! if (thread_table[i].id == thread_id) ! GC_push_all_stack((ptr_t)&i, thread_table[i].stack); ! else { ! thread_table[i].context.ContextFlags ! = (CONTEXT_INTEGER|CONTEXT_CONTROL); ! if (!GetThreadContext(thread_table[i].handle, ! /* cast away volatile qualifier */ ! (LPCONTEXT)&thread_table[i].context)) ABORT("GetThreadContext failed"); ! # ifdef I386 ! GC_push_one ((word) thread_table[i].context.Edi); ! GC_push_one ((word) thread_table[i].context.Esi); ! GC_push_one ((word) thread_table[i].context.Ebp); ! GC_push_one ((word) thread_table[i].context.Ebx); ! GC_push_one ((word) thread_table[i].context.Edx); ! GC_push_one ((word) thread_table[i].context.Ecx); ! GC_push_one ((word) thread_table[i].context.Eax); ! if (thread_table[i].context.Esp >= (DWORD)thread_table[i].stack ! || thread_table[i].context.Esp < (DWORD)bottom) { ! WARN("Thread stack pointer 0x%lx out of range, pushing everything", ! thread_table[i].context.Esp); ! GC_push_all_stack((char *) bottom, thread_table[i].stack); ! } else { ! GC_push_all_stack((char *) thread_table[i].context.Esp, ! thread_table[i].stack); ! } ! # else ! # ifdef ARM32 ! if (thread_table[i].context.Sp >= (DWORD)thread_table[i].stack ! || thread_table[i].context.Sp < (DWORD)bottom) ! ABORT("Thread stack pointer out of range"); ! GC_push_one ((word) thread_table[i].context.R0); ! GC_push_one ((word) thread_table[i].context.R1); ! GC_push_one ((word) thread_table[i].context.R2); ! GC_push_one ((word) thread_table[i].context.R3); ! GC_push_one ((word) thread_table[i].context.R4); ! GC_push_one ((word) thread_table[i].context.R5); ! GC_push_one ((word) thread_table[i].context.R6); ! GC_push_one ((word) thread_table[i].context.R7); ! GC_push_one ((word) thread_table[i].context.R8); ! GC_push_one ((word) thread_table[i].context.R9); ! GC_push_one ((word) thread_table[i].context.R10); ! GC_push_one ((word) thread_table[i].context.R11); ! GC_push_one ((word) thread_table[i].context.R12); ! GC_push_all_stack((char *) thread_table[i].context.Sp, ! thread_table[i].stack); ! # else ! # ifdef SHx ! if (thread_table[i].context.R15 >= (DWORD)thread_table[i].stack ! || thread_table[i].context.R15 < (DWORD)bottom) ! ABORT("Thread stack pointer out of range"); ! GC_push_one ((word) thread_table[i].context.R0); ! GC_push_one ((word) thread_table[i].context.R1); ! GC_push_one ((word) thread_table[i].context.R2); ! GC_push_one ((word) thread_table[i].context.R3); ! GC_push_one ((word) thread_table[i].context.R4); ! GC_push_one ((word) thread_table[i].context.R5); ! GC_push_one ((word) thread_table[i].context.R6); ! GC_push_one ((word) thread_table[i].context.R7); ! GC_push_one ((word) thread_table[i].context.R8); ! GC_push_one ((word) thread_table[i].context.R9); ! GC_push_one ((word) thread_table[i].context.R10); ! GC_push_one ((word) thread_table[i].context.R11); ! GC_push_one ((word) thread_table[i].context.R12); ! GC_push_one ((word) thread_table[i].context.R13); ! GC_push_one ((word) thread_table[i].context.R14); ! GC_push_all_stack((char *) thread_table[i].context.R15, ! thread_table[i].stack); # else ! # ifdef MIPS ! if (thread_table[i].context.IntSp >= (DWORD)thread_table[i].stack ! || thread_table[i].context.IntSp < (DWORD)bottom) ! ABORT("Thread stack pointer out of range"); ! GC_push_one ((word) thread_table[i].context.IntAt); ! GC_push_one ((word) thread_table[i].context.IntV0); ! GC_push_one ((word) thread_table[i].context.IntV1); ! GC_push_one ((word) thread_table[i].context.IntA0); ! GC_push_one ((word) thread_table[i].context.IntA1); ! GC_push_one ((word) thread_table[i].context.IntA2); ! GC_push_one ((word) thread_table[i].context.IntA3); ! GC_push_one ((word) thread_table[i].context.IntT0); ! GC_push_one ((word) thread_table[i].context.IntT1); ! GC_push_one ((word) thread_table[i].context.IntT2); ! GC_push_one ((word) thread_table[i].context.IntT3); ! GC_push_one ((word) thread_table[i].context.IntT4); ! GC_push_one ((word) thread_table[i].context.IntT5); ! GC_push_one ((word) thread_table[i].context.IntT6); ! GC_push_one ((word) thread_table[i].context.IntT7); ! GC_push_one ((word) thread_table[i].context.IntS0); ! GC_push_one ((word) thread_table[i].context.IntS1); ! GC_push_one ((word) thread_table[i].context.IntS2); ! GC_push_one ((word) thread_table[i].context.IntS3); ! GC_push_one ((word) thread_table[i].context.IntS4); ! GC_push_one ((word) thread_table[i].context.IntS5); ! GC_push_one ((word) thread_table[i].context.IntS6); ! GC_push_one ((word) thread_table[i].context.IntS7); ! GC_push_one ((word) thread_table[i].context.IntT8); ! GC_push_one ((word) thread_table[i].context.IntT9); ! GC_push_one ((word) thread_table[i].context.IntK0); ! GC_push_one ((word) thread_table[i].context.IntK1); ! GC_push_one ((word) thread_table[i].context.IntS8); ! GC_push_all_stack((char *) thread_table[i].context.IntSp, ! thread_table[i].stack); ! # else ! # ifdef PPC ! if (thread_table[i].context.Gpr1 >= (DWORD)thread_table[i].stack ! || thread_table[i].context.Gpr1 < (DWORD)bottom) ! ABORT("Thread stack pointer out of range"); ! GC_push_one ((word) thread_table[i].context.Gpr0); ! /* Gpr1 is stack pointer */ ! /* Gpr2 is global pointer */ ! GC_push_one ((word) thread_table[i].context.Gpr3); ! GC_push_one ((word) thread_table[i].context.Gpr4); ! GC_push_one ((word) thread_table[i].context.Gpr5); ! GC_push_one ((word) thread_table[i].context.Gpr6); ! GC_push_one ((word) thread_table[i].context.Gpr7); ! GC_push_one ((word) thread_table[i].context.Gpr8); ! GC_push_one ((word) thread_table[i].context.Gpr9); ! GC_push_one ((word) thread_table[i].context.Gpr10); ! GC_push_one ((word) thread_table[i].context.Gpr11); ! GC_push_one ((word) thread_table[i].context.Gpr12); ! /* Gpr13 is reserved for the kernel */ ! GC_push_one ((word) thread_table[i].context.Gpr14); ! GC_push_one ((word) thread_table[i].context.Gpr15); ! GC_push_one ((word) thread_table[i].context.Gpr16); ! GC_push_one ((word) thread_table[i].context.Gpr17); ! GC_push_one ((word) thread_table[i].context.Gpr18); ! GC_push_one ((word) thread_table[i].context.Gpr19); ! GC_push_one ((word) thread_table[i].context.Gpr20); ! GC_push_one ((word) thread_table[i].context.Gpr21); ! GC_push_one ((word) thread_table[i].context.Gpr22); ! GC_push_one ((word) thread_table[i].context.Gpr23); ! GC_push_one ((word) thread_table[i].context.Gpr24); ! GC_push_one ((word) thread_table[i].context.Gpr25); ! GC_push_one ((word) thread_table[i].context.Gpr26); ! GC_push_one ((word) thread_table[i].context.Gpr27); ! GC_push_one ((word) thread_table[i].context.Gpr28); ! GC_push_one ((word) thread_table[i].context.Gpr29); ! GC_push_one ((word) thread_table[i].context.Gpr30); ! GC_push_one ((word) thread_table[i].context.Gpr31); ! GC_push_all_stack((char *) thread_table[i].context.Gpr1, ! thread_table[i].stack); ! # else ! # ifdef ALPHA ! if (thread_table[i].context.IntSp >= (DWORD)thread_table[i].stack ! || thread_table[i].context.IntSp < (DWORD)bottom) ! ABORT("Thread stack pointer out of range"); ! GC_push_one ((word) thread_table[i].context.IntV0); ! GC_push_one ((word) thread_table[i].context.IntT0); ! GC_push_one ((word) thread_table[i].context.IntT1); ! GC_push_one ((word) thread_table[i].context.IntT2); ! GC_push_one ((word) thread_table[i].context.IntT3); ! GC_push_one ((word) thread_table[i].context.IntT4); ! GC_push_one ((word) thread_table[i].context.IntT5); ! GC_push_one ((word) thread_table[i].context.IntT6); ! GC_push_one ((word) thread_table[i].context.IntT7); ! GC_push_one ((word) thread_table[i].context.IntS0); ! GC_push_one ((word) thread_table[i].context.IntS1); ! GC_push_one ((word) thread_table[i].context.IntS2); ! GC_push_one ((word) thread_table[i].context.IntS3); ! GC_push_one ((word) thread_table[i].context.IntS4); ! GC_push_one ((word) thread_table[i].context.IntS5); ! GC_push_one ((word) thread_table[i].context.IntFp); ! GC_push_one ((word) thread_table[i].context.IntA0); ! GC_push_one ((word) thread_table[i].context.IntA1); ! GC_push_one ((word) thread_table[i].context.IntA2); ! GC_push_one ((word) thread_table[i].context.IntA3); ! GC_push_one ((word) thread_table[i].context.IntA4); ! GC_push_one ((word) thread_table[i].context.IntA5); ! GC_push_one ((word) thread_table[i].context.IntT8); ! GC_push_one ((word) thread_table[i].context.IntT9); ! GC_push_one ((word) thread_table[i].context.IntT10); ! GC_push_one ((word) thread_table[i].context.IntT11); ! GC_push_one ((word) thread_table[i].context.IntT12); ! GC_push_one ((word) thread_table[i].context.IntAt); ! GC_push_all_stack((char *) thread_table[i].context.IntSp, ! thread_table[i].stack); ! # else ! --> architecture not supported ! # endif /* !ALPHA */ ! # endif /* !PPC */ ! # endif /* !MIPS */ ! # endif /* !SHx */ ! # endif /* !ARM32 */ ! # endif /* !I386 */ } } } void GC_get_next_stack(char *start, char **lo, char **hi) --- 329,404 ---- void GC_push_all_stacks() { DWORD thread_id = GetCurrentThreadId(); + GC_bool found_me = FALSE; int i; ! int dummy; ! ptr_t sp, stack_min; ! GC_thread thread; ! LONG my_max = GC_get_max_thread_index(); ! ! for (i = 0; i <= my_max; i++) { ! thread = thread_table + i; ! if (thread -> in_use && thread -> stack_base) { ! if (thread -> id == thread_id) { ! sp = (ptr_t) &dummy; ! found_me = TRUE; ! } else { ! CONTEXT context; ! context.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL; ! if (!GetThreadContext(thread_table[i].handle, &context)) ABORT("GetThreadContext failed"); ! ! /* Push all registers that might point into the heap. Frame */ ! /* pointer registers are included in case client code was */ ! /* compiled with the 'omit frame pointer' optimisation. */ ! # define PUSH1(reg) GC_push_one((word)context.reg) ! # define PUSH2(r1,r2) PUSH1(r1), PUSH1(r2) ! # define PUSH4(r1,r2,r3,r4) PUSH2(r1,r2), PUSH2(r3,r4) ! # if defined(I386) ! PUSH4(Edi,Esi,Ebx,Edx), PUSH2(Ecx,Eax), PUSH1(Ebp); ! sp = (ptr_t)context.Esp; ! # elif defined(ARM32) ! PUSH4(R0,R1,R2,R3),PUSH4(R4,R5,R6,R7),PUSH4(R8,R9,R10,R11),PUSH1(R12); ! sp = (ptr_t)context.Sp; ! # elif defined(SHx) ! PUSH4(R0,R1,R2,R3), PUSH4(R4,R5,R6,R7), PUSH4(R8,R9,R10,R11); ! PUSH2(R12,R13), PUSH1(R14); ! sp = (ptr_t)context.R15; ! # elif defined(MIPS) ! PUSH4(IntAt,IntV0,IntV1,IntA0), PUSH4(IntA1,IntA2,IntA3,IntT0); ! PUSH4(IntT1,IntT2,IntT3,IntT4), PUSH4(IntT5,IntT6,IntT7,IntS0); ! PUSH4(IntS1,IntS2,IntS3,IntS4), PUSH4(IntS5,IntS6,IntS7,IntT8); ! PUSH4(IntT9,IntK0,IntK1,IntS8); ! sp = (ptr_t)context.IntSp; ! # elif defined(PPC) ! PUSH4(Gpr0, Gpr3, Gpr4, Gpr5), PUSH4(Gpr6, Gpr7, Gpr8, Gpr9); ! PUSH4(Gpr10,Gpr11,Gpr12,Gpr14), PUSH4(Gpr15,Gpr16,Gpr17,Gpr18); ! PUSH4(Gpr19,Gpr20,Gpr21,Gpr22), PUSH4(Gpr23,Gpr24,Gpr25,Gpr26); ! PUSH4(Gpr27,Gpr28,Gpr29,Gpr30), PUSH1(Gpr31); ! sp = (ptr_t)context.Gpr1; ! # elif defined(ALPHA) ! PUSH4(IntV0,IntT0,IntT1,IntT2), PUSH4(IntT3,IntT4,IntT5,IntT6); ! PUSH4(IntT7,IntS0,IntS1,IntS2), PUSH4(IntS3,IntS4,IntS5,IntFp); ! PUSH4(IntA0,IntA1,IntA2,IntA3), PUSH4(IntA4,IntA5,IntT8,IntT9); ! PUSH4(IntT10,IntT11,IntT12,IntAt); ! sp = (ptr_t)context.IntSp; # else ! # error "architecture is not supported" ! # endif ! } ! ! stack_min = GC_get_stack_min(thread->stack_base); ! ! if (sp >= stack_min && sp < thread->stack_base) ! GC_push_all_stack(sp, thread->stack_base); ! else { ! WARN("Thread stack pointer 0x%lx out of range, pushing everything\n", ! (unsigned long)sp); ! GC_push_all_stack(stack_min, thread->stack_base); } } + } + if (!found_me) ABORT("Collecting from unknown thread."); } void GC_get_next_stack(char *start, char **lo, char **hi) *************** void GC_get_next_stack(char *start, char *** 318,326 **** int i; # define ADDR_LIMIT (char *)(-1L) char * current_min = ADDR_LIMIT; ! ! for (i = 0; i < MAX_THREADS; i++) { ! char * s = (char *)thread_table[i].stack; if (0 != s && s > start && s < current_min) { current_min = s; --- 406,415 ---- int i; # define ADDR_LIMIT (char *)(-1L) char * current_min = ADDR_LIMIT; ! LONG my_max = GC_get_max_thread_index(); ! ! for (i = 0; i <= my_max; i++) { ! char * s = (char *)thread_table[i].stack_base; if (0 != s && s > start && s < current_min) { current_min = s; *************** void GC_get_next_stack(char *start, char *** 331,343 **** *lo = ADDR_LIMIT; return; } ! *lo = GC_get_lo_stack_addr(current_min); if (*lo < start) *lo = start; } ! #if !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL)) ! HANDLE WINAPI GC_CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ) --- 420,436 ---- *lo = ADDR_LIMIT; return; } ! *lo = GC_get_stack_min(current_min); if (*lo < start) *lo = start; } ! #if !defined(CYGWIN32) ! #if !defined(MSWINCE) && defined(GC_DLL) ! ! /* We register threads from DllMain */ ! ! GC_API HANDLE WINAPI GC_CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ) *************** HANDLE WINAPI GC_CreateThread( *** 346,432 **** lpParameter, dwCreationFlags, lpThreadId); } ! #else /* !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL)) */ typedef struct { - HANDLE child_ready_h, parent_ready_h; - volatile struct thread_entry * entry; LPTHREAD_START_ROUTINE start; LPVOID param; } thread_args; ! DWORD WINAPI thread_start(LPVOID arg); ! HANDLE WINAPI GC_CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ) { HANDLE thread_h = NULL; - HANDLE child_ready_h, parent_ready_h; ! int i; ! thread_args args; ! /* allocate thread slot */ ! LOCK(); ! for (i = 0; i != MAX_THREADS && thread_table[i].in_use; i++) ! ; ! if (i != MAX_THREADS) { ! thread_table[i].in_use = TRUE; } - UNLOCK(); - - if (i != MAX_THREADS) { - - /* create unnamed unsignalled events */ - if (child_ready_h = CreateEvent(NULL, FALSE, FALSE, NULL)) { - if (parent_ready_h = CreateEvent(NULL, FALSE, FALSE, NULL)) { - - /* set up thread arguments */ - args.child_ready_h = child_ready_h; - args.parent_ready_h = parent_ready_h; - args.entry = &thread_table[i]; - args.start = lpStartAddress; - args.param = lpParameter; - - thread_h = CreateThread(lpThreadAttributes, - dwStackSize, thread_start, - &args, - dwCreationFlags & ~CREATE_SUSPENDED, - lpThreadId); - - if (thread_h) { ! /* fill in ID and handle; tell child this is done */ ! thread_table[i].id = *lpThreadId; ! thread_table[i].handle = thread_h; ! SetEvent (parent_ready_h); ! ! /* wait for child to fill in stack and copy args */ ! WaitForSingleObject (child_ready_h, INFINITE); ! ! /* suspend the child if requested */ ! if (dwCreationFlags & CREATE_SUSPENDED) ! SuspendThread (thread_h); ! ! /* let child call given function now (or when resumed) */ ! SetEvent (parent_ready_h); ! ! } else { ! CloseHandle (parent_ready_h); ! } ! } ! } ! ! CloseHandle (child_ready_h); ! ! if (thread_h == NULL) ! thread_table[i].in_use = FALSE; ! } else { /* no thread slot found */ ! SetLastError (ERROR_TOO_MANY_TCBS); ! } return thread_h; } --- 439,483 ---- lpParameter, dwCreationFlags, lpThreadId); } ! #else /* defined(MSWINCE) || !defined(GC_DLL)) */ ! ! /* We have no DllMain to take care of new threads. Thus we */ ! /* must properly intercept thread creation. */ typedef struct { LPTHREAD_START_ROUTINE start; LPVOID param; } thread_args; ! static DWORD WINAPI thread_start(LPVOID arg); ! GC_API HANDLE WINAPI GC_CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ) { HANDLE thread_h = NULL; ! thread_args *args; ! if (!GC_is_initialized) GC_init(); ! /* make sure GC is initialized (i.e. main thread is attached) */ ! ! args = GC_malloc_uncollectable(sizeof(thread_args)); ! /* Handed off to and deallocated by child thread. */ ! if (0 == args) { ! SetLastError(ERROR_NOT_ENOUGH_MEMORY); ! return NULL; } ! /* set up thread arguments */ ! args -> start = lpStartAddress; ! args -> param = lpParameter; ! thread_h = CreateThread(lpThreadAttributes, ! dwStackSize, thread_start, ! args, dwCreationFlags, ! lpThreadId); return thread_h; } *************** HANDLE WINAPI GC_CreateThread( *** 434,452 **** static DWORD WINAPI thread_start(LPVOID arg) { DWORD ret = 0; ! thread_args args = *(thread_args *)arg; ! ! /* wait for parent to fill in ID and handle */ ! WaitForSingleObject (args.parent_ready_h, INFINITE); ! ResetEvent (args.parent_ready_h); ! ! /* fill in stack; tell parent this is done */ ! args.entry->stack = GC_get_stack_base(); ! SetEvent (args.child_ready_h); ! /* wait for parent to tell us to go (in case it needs to suspend us) */ ! WaitForSingleObject (args.parent_ready_h, INFINITE); ! CloseHandle (args.parent_ready_h); /* Clear the thread entry even if we exit with an exception. */ /* This is probably pointless, since an uncaught exception is */ --- 485,493 ---- static DWORD WINAPI thread_start(LPVOID arg) { DWORD ret = 0; ! thread_args *args = (thread_args *)arg; ! GC_new_thread(); /* Clear the thread entry even if we exit with an exception. */ /* This is probably pointless, since an uncaught exception is */ *************** static DWORD WINAPI thread_start(LPVOID *** 454,476 **** #ifndef __GNUC__ __try { #endif /* __GNUC__ */ ! ret = args.start (args.param); #ifndef __GNUC__ } __finally { #endif /* __GNUC__ */ ! LOCK(); ! args.entry->stack = 0; ! args.entry->in_use = FALSE; ! /* cast away volatile qualifier */ ! BZERO((void *) &args.entry->context, sizeof(CONTEXT)); ! UNLOCK(); #ifndef __GNUC__ } #endif /* __GNUC__ */ return ret; } ! #endif /* !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL)) */ #ifdef MSWINCE --- 495,515 ---- #ifndef __GNUC__ __try { #endif /* __GNUC__ */ ! ret = args->start (args->param); #ifndef __GNUC__ } __finally { #endif /* __GNUC__ */ ! GC_free(args); ! GC_delete_thread(GetCurrentThreadId()); #ifndef __GNUC__ } #endif /* __GNUC__ */ return ret; } ! #endif /* !defined(MSWINCE) && !(defined(__MINGW32__) && !defined(_DLL)) */ ! ! #endif /* !CYGWIN32 */ #ifdef MSWINCE *************** int WINAPI WinMain(HINSTANCE hInstance, *** 495,501 **** DWORD thread_id; /* initialize everything */ - InitializeCriticalSection(&GC_allocate_ml); GC_init(); /* start the main thread */ --- 534,539 ---- *************** DWORD WINAPI main_thread_start(LPVOID ar *** 525,630 **** # else /* !MSWINCE */ ! LONG WINAPI GC_write_fault_handler(struct _EXCEPTION_POINTERS *exc_info); ! #ifdef GC_DLL /* ! * This isn't generally safe, since DllMain is not premptible. ! * If another thread holds the lock while this runs we're in trouble. * Pontus Rydin suggests wrapping the thread start routine instead. */ BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved) { switch (reason) { case DLL_PROCESS_ATTACH: - InitializeCriticalSection(&GC_allocate_ml); GC_init(); /* Force initialization before thread attach. */ /* fall through */ case DLL_THREAD_ATTACH: ! { ! int i; ! /* It appears to be unsafe to acquire a lock here, since this */ ! /* code is apparently not preeemptible on some systems. */ ! /* (This is based on complaints, not on Microsoft's official */ ! /* documentation, which says this should perform "only simple */ ! /* inititalization tasks".) */ ! /* Hence we make do with nonblocking synchronization. */ ! ! /* The following should be a noop according to the win32 */ ! /* documentation. There is empirical evidence that it */ ! /* isn't. - HB */ ! # ifdef MPROTECT_VDB ! if (GC_incremental) SetUnhandledExceptionFilter(GC_write_fault_handler); ! # endif ! ! for (i = 0; ! /* cast away volatile qualifier */ ! InterlockedExchange((LPLONG) &thread_table[i].in_use, 1) != 0; ! i++) { ! /* Compare-and-swap would make this cleaner, but that's not */ ! /* supported before Windows 98 and NT 4.0. In Windows 2000, */ ! /* InterlockedExchange is supposed to be replaced by */ ! /* InterlockedExchangePointer, but that's not really what I */ ! /* want here. */ ! if (i == MAX_THREADS - 1) ! ABORT("too many threads"); ! } ! thread_table[i].id = GetCurrentThreadId(); ! if (!DuplicateHandle(GetCurrentProcess(), ! GetCurrentThread(), ! GetCurrentProcess(), ! /* cast away volatile qualifier */ ! (HANDLE *) &thread_table[i].handle, ! 0, ! 0, ! DUPLICATE_SAME_ACCESS)) { ! DWORD last_error = GetLastError(); ! GC_printf1("Last error code: %lx\n", last_error); ! ABORT("DuplicateHandle failed"); ! } ! thread_table[i].stack = GC_get_stack_base(); ! /* If this thread is being created while we are trying to stop */ ! /* the world, wait here. Hopefully this can't happen on any */ ! /* systems that don't allow us to block here. */ ! while (GC_please_stop) Sleep(20); ! } break; case DLL_THREAD_DETACH: ! { ! int i; ! DWORD thread_id = GetCurrentThreadId(); ! LOCK(); ! for (i = 0; ! i < MAX_THREADS && ! (thread_table[i].stack == 0 || thread_table[i].id != thread_id); ! i++) {} ! if (i >= MAX_THREADS) { ! WARN("thread %ld not found on detach", (GC_word)thread_id); ! } else { ! thread_table[i].stack = 0; ! thread_table[i].in_use = FALSE; ! CloseHandle(thread_table[i].handle); ! /* cast away volatile qualifier */ ! BZERO((void *) &thread_table[i].context, sizeof(CONTEXT)); ! } ! UNLOCK(); ! } break; case DLL_PROCESS_DETACH: { int i; LOCK(); ! for (i = 0; i < MAX_THREADS; ++i) { if (thread_table[i].in_use) ! { ! thread_table[i].stack = 0; ! thread_table[i].in_use = FALSE; ! CloseHandle(thread_table[i].handle); ! BZERO((void *) &thread_table[i].context, sizeof(CONTEXT)); ! } } UNLOCK(); --- 563,780 ---- # else /* !MSWINCE */ ! /* Called by GC_init() - we hold the allocation lock. */ ! void GC_thr_init() { ! if (GC_thr_initialized) return; ! GC_main_thread = GetCurrentThreadId(); ! GC_thr_initialized = TRUE; ! /* Add the initial thread, so we can stop it. */ ! GC_new_thread(); ! } ! ! #ifdef CYGWIN32 ! ! struct start_info { ! void *(*start_routine)(void *); ! void *arg; ! GC_bool detached; ! }; ! ! int GC_pthread_join(pthread_t pthread_id, void **retval) { ! int result; ! int i; ! GC_thread me; ! ! # if DEBUG_CYGWIN_THREADS ! GC_printf3("thread 0x%x(0x%x) is joining thread 0x%x.\n", ! (int)pthread_self(), GetCurrentThreadId(), (int)pthread_id); ! # endif ! ! /* Thread being joined might not have registered itself yet. */ ! /* After the join,thread id may have been recycled. */ ! /* FIXME: It would be better if this worked more like */ ! /* pthread_support.c. */ ! ! while ((me = GC_lookup_thread(pthread_id)) == 0) Sleep(10); ! ! result = pthread_join(pthread_id, retval); ! ! GC_delete_gc_thread(me); ! ! # if DEBUG_CYGWIN_THREADS ! GC_printf3("thread 0x%x(0x%x) completed join with thread 0x%x.\n", ! (int)pthread_self(), GetCurrentThreadId(), (int)pthread_id); ! # endif ! ! return result; ! } ! ! /* Cygwin-pthreads calls CreateThread internally, but it's not ! * easily interceptible by us.. ! * so intercept pthread_create instead ! */ ! int ! GC_pthread_create(pthread_t *new_thread, ! const pthread_attr_t *attr, ! void *(*start_routine)(void *), void *arg) { ! int result; ! struct start_info * si; ! ! if (!GC_is_initialized) GC_init(); ! /* make sure GC is initialized (i.e. main thread is attached) */ ! ! /* This is otherwise saved only in an area mmapped by the thread */ ! /* library, which isn't visible to the collector. */ ! si = GC_malloc_uncollectable(sizeof(struct start_info)); ! if (0 == si) return(EAGAIN); ! ! si -> start_routine = start_routine; ! si -> arg = arg; ! if (attr != 0 && ! pthread_attr_getdetachstate(attr, &si->detached) ! == PTHREAD_CREATE_DETACHED) { ! si->detached = TRUE; ! } ! ! # if DEBUG_CYGWIN_THREADS ! GC_printf2("About to create a thread from 0x%x(0x%x)\n", ! (int)pthread_self(), GetCurrentThreadId); ! # endif ! result = pthread_create(new_thread, attr, GC_start_routine, si); ! ! if (result) { /* failure */ ! GC_free(si); ! } ! ! return(result); ! } ! ! void * GC_start_routine(void * arg) ! { ! struct start_info * si = arg; ! void * result; ! void *(*start)(void *); ! void *start_arg; ! pthread_t pthread_id; ! GC_thread me; ! GC_bool detached; ! int i; ! ! # if DEBUG_CYGWIN_THREADS ! GC_printf2("thread 0x%x(0x%x) starting...\n",(int)pthread_self(), ! GetCurrentThreadId()); ! # endif ! ! /* If a GC occurs before the thread is registered, that GC will */ ! /* ignore this thread. That's fine, since it will block trying to */ ! /* acquire the allocation lock, and won't yet hold interesting */ ! /* pointers. */ ! LOCK(); ! /* We register the thread here instead of in the parent, so that */ ! /* we don't need to hold the allocation lock during pthread_create. */ ! me = GC_new_thread(); ! UNLOCK(); ! ! start = si -> start_routine; ! start_arg = si -> arg; ! if (si-> detached) me -> flags |= DETACHED; ! me -> pthread_id = pthread_id = pthread_self(); ! ! GC_free(si); /* was allocated uncollectable */ ! ! pthread_cleanup_push(GC_thread_exit_proc, (void *)me); ! result = (*start)(start_arg); ! me -> status = result; ! pthread_cleanup_pop(0); ! ! # if DEBUG_CYGWIN_THREADS ! GC_printf2("thread 0x%x(0x%x) returned from start routine.\n", ! (int)pthread_self(),GetCurrentThreadId()); ! # endif ! ! return(result); ! } ! ! void GC_thread_exit_proc(void *arg) ! { ! GC_thread me = (GC_thread)arg; ! int i; ! ! # if DEBUG_CYGWIN_THREADS ! GC_printf2("thread 0x%x(0x%x) called pthread_exit().\n", ! (int)pthread_self(),GetCurrentThreadId()); ! # endif ! ! LOCK(); ! if (me -> flags & DETACHED) { ! GC_delete_thread(GetCurrentThreadId()); ! } else { ! /* deallocate it as part of join */ ! me -> flags |= FINISHED; ! } ! UNLOCK(); ! } ! ! /* nothing required here... */ ! int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) { ! return pthread_sigmask(how, set, oset); ! } ! ! int GC_pthread_detach(pthread_t thread) ! { ! int result; ! GC_thread thread_gc_id; ! ! LOCK(); ! thread_gc_id = GC_lookup_thread(thread); ! UNLOCK(); ! result = pthread_detach(thread); ! if (result == 0) { ! LOCK(); ! thread_gc_id -> flags |= DETACHED; ! /* Here the pthread thread id may have been recycled. */ ! if (thread_gc_id -> flags & FINISHED) { ! GC_delete_gc_thread(thread_gc_id); ! } ! UNLOCK(); ! } ! return result; ! } ! ! #else /* !CYGWIN32 */ /* ! * We avoid acquiring locks here, since this doesn't seem to be preemptable. * Pontus Rydin suggests wrapping the thread start routine instead. */ + #ifdef GC_DLL BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved) { switch (reason) { case DLL_PROCESS_ATTACH: GC_init(); /* Force initialization before thread attach. */ /* fall through */ case DLL_THREAD_ATTACH: ! GC_ASSERT(GC_thr_initialized); ! if (GC_main_thread != GetCurrentThreadId()) { ! GC_new_thread(); ! } /* o.w. we already did it during GC_thr_init(), called by GC_init() */ break; + case DLL_THREAD_DETACH: ! GC_delete_thread(GetCurrentThreadId()); break; + case DLL_PROCESS_DETACH: { int i; LOCK(); ! for (i = 0; i <= GC_get_max_thread_index(); ++i) { if (thread_table[i].in_use) ! GC_delete_gc_thread(thread_table + i); } UNLOCK(); *************** BOOL WINAPI DllMain(HINSTANCE inst, ULON *** 636,643 **** } return TRUE; } ! ! # endif /* GC_DLL */ # endif /* !MSWINCE */ --- 786,793 ---- } return TRUE; } ! #endif /* GC_DLL */ ! #endif /* !CYGWIN32 */ # endif /* !MSWINCE */ diff -Nrc3pad gcc-3.3.3/.brik gcc-3.4.0/.brik *** gcc-3.3.3/.brik 2004-02-14 21:25:40.000000000 +0000 --- gcc-3.4.0/.brik 2004-04-19 03:12:56.000000000 +0000 *************** *** 3,2943 **** # CRC-32 filename # ------ -------- ! 2864072627b ./.cvsignore ! 454904501b ./BUGS ! 2171125041b ./COPYING ! 508743035b ./COPYING.LIB ! 3759805510b ./ChangeLog ! 1351330966b ./FAQ ! 2229468985b ./INSTALL/README ! 2873940805b ./INSTALL/binaries.html ! 2824636383b ./INSTALL/build.html ! 65998970b ./INSTALL/configure.html ! 2768939892b ./INSTALL/download.html ! 3285738462b ./INSTALL/finalinstall.html ! 1676470193b ./INSTALL/gfdl.html ! 2051725251b ./INSTALL/index.html ! 3273734043b ./INSTALL/old.html ! 975149080b ./INSTALL/specific.html ! 1887949984b ./INSTALL/test.html ! 387185131b ./MAINTAINERS ! 459788085b ./Makefile.def ! 673596399b ./Makefile.in ! 1638614068b ./Makefile.tpl ! 3697693037b ./README ! 3286946454b ./README.SCO ! 655018850b ./boehm-gc/AmigaOS.c ! 2411687152b ./boehm-gc/BCC_MAKEFILE ! 3243278359b ./boehm-gc/ChangeLog ! 3428452570b ./boehm-gc/EMX_MAKEFILE ! 145946109b ./boehm-gc/MacOS.c ! 591574792b ./boehm-gc/MacProjects.sit.hqx ! 3338272940b ./boehm-gc/Mac_files/MacOS_Test_config.h ! 537693184b ./boehm-gc/Mac_files/MacOS_config.h ! 789649079b ./boehm-gc/Mac_files/dataend.c ! 3520138091b ./boehm-gc/Mac_files/datastart.c ! 2647418481b ./boehm-gc/Makefile.DLLs ! 2938168783b ./boehm-gc/Makefile.am ! 3148936110b ./boehm-gc/Makefile.direct ! 3806813747b ./boehm-gc/Makefile.dist ! 87051491b ./boehm-gc/Makefile.dj ! 3291187154b ./boehm-gc/Makefile.in ! 3941839401b ./boehm-gc/NT_MAKEFILE ! 3607948475b ./boehm-gc/NT_THREADS_MAKEFILE ! 3289014202b ./boehm-gc/OS2_MAKEFILE ! 2438519321b ./boehm-gc/PCR-Makefile ! 2956367466b ./boehm-gc/SMakefile.amiga ! 205379550b ./boehm-gc/WCC_MAKEFILE 1177862404b ./boehm-gc/acinclude.m4 1236612374b ./boehm-gc/aclocal.m4 971051254b ./boehm-gc/add_gc_prefix.c ! 2056900000b ./boehm-gc/allchblk.c ! 33265057b ./boehm-gc/alloc.c ! 1198071641b ./boehm-gc/alpha_mach_dep.s ! 3099799990b ./boehm-gc/backgraph.c 394605993b ./boehm-gc/blacklst.c 971406525b ./boehm-gc/callprocs 2542310219b ./boehm-gc/checksums.c ! 1272640704b ./boehm-gc/config.guess ! 4182969326b ./boehm-gc/config.sub ! 2350970747b ./boehm-gc/configure 4265937088b ./boehm-gc/configure.host ! 725430640b ./boehm-gc/configure.in ! 3430717956b ./boehm-gc/cord/cordbscs.c ! 473686535b ./boehm-gc/cord/cordprnt.c 1796537586b ./boehm-gc/cord/cordtest.c 3610557498b ./boehm-gc/cord/cordxtra.c 1399512076b ./boehm-gc/cord/de.c 3493089115b ./boehm-gc/cord/de_cmds.h 2226183422b ./boehm-gc/cord/de_win.ICO 2296745137b ./boehm-gc/cord/de_win.RC ! 1274913051b ./boehm-gc/cord/de_win.c ! 1969645283b ./boehm-gc/cord/de_win.h ! 3479570773b ./boehm-gc/dbg_mlc.c 4155306217b ./boehm-gc/digimars.mak ! 1852147885b ./boehm-gc/doc/README ! 2912965872b ./boehm-gc/doc/README.Mac ! 3192387476b ./boehm-gc/doc/README.MacOSX ! 1009764294b ./boehm-gc/doc/README.OS2 1398938057b ./boehm-gc/doc/README.amiga 3968038895b ./boehm-gc/doc/README.autoconf ! 609394135b ./boehm-gc/doc/README.changes 124254120b ./boehm-gc/doc/README.contributors 2337143875b ./boehm-gc/doc/README.cords 2101980206b ./boehm-gc/doc/README.dj ! 1564073111b ./boehm-gc/doc/README.environment ! 1544667036b ./boehm-gc/doc/README.ews4800 2032435380b ./boehm-gc/doc/README.hp ! 261398962b ./boehm-gc/doc/README.linux ! 3651372180b ./boehm-gc/doc/README.macros 3249391671b ./boehm-gc/doc/README.rs6000 2157435131b ./boehm-gc/doc/README.sgi 2210572734b ./boehm-gc/doc/README.solaris2 1044770375b ./boehm-gc/doc/README.uts ! 3162142981b ./boehm-gc/doc/README.win32 ! 602673483b ./boehm-gc/doc/barrett_diagram ! 2134574438b ./boehm-gc/doc/debugging.html ! 2587456343b ./boehm-gc/doc/gc.man ! 4112273729b ./boehm-gc/doc/gcdescr.html ! 1244216301b ./boehm-gc/doc/tree.html ! 414780111b ./boehm-gc/dyn_load.c ! 110360283b ./boehm-gc/finalize.c ! 3607948475b ./boehm-gc/gc.mak ! 3449835837b ./boehm-gc/gc_cpp.cc 231223753b ./boehm-gc/gc_cpp.cpp - 145159317b ./boehm-gc/gc_dlopen.c 3458300802b ./boehm-gc/gcc_support.c ! 4111426693b ./boehm-gc/gcj_mlc.c 3106502053b ./boehm-gc/gcname.c 1644234138b ./boehm-gc/headers.c 1596485799b ./boehm-gc/hpux_test_and_clear.s 1676909184b ./boehm-gc/ia64_save_regs_in_stack.s ! 3582080946b ./boehm-gc/if_mach.c 387600055b ./boehm-gc/if_not_there.c - 1222266555b ./boehm-gc/include/Makefile.am - 2340206284b ./boehm-gc/include/Makefile.in 3897882033b ./boehm-gc/include/cord.h 214150158b ./boehm-gc/include/ec.h ! 61666144b ./boehm-gc/include/gc.h 2874534410b ./boehm-gc/include/gc_alloc.h 1922524680b ./boehm-gc/include/gc_amiga_redirects.h 3531915622b ./boehm-gc/include/gc_backptr.h ! 1564499082b ./boehm-gc/include/gc_cpp.h 2080667503b ./boehm-gc/include/gc_gcj.h 30043067b ./boehm-gc/include/gc_inl.h 601682422b ./boehm-gc/include/gc_inline.h ! 2851726125b ./boehm-gc/include/gc_local_alloc.h ! 3323450216b ./boehm-gc/include/gc_mark.h ! 4062216651b ./boehm-gc/include/gc_pthread_redirects.h ! 3286861254b ./boehm-gc/include/gc_typed.h 2246764458b ./boehm-gc/include/javaxfc.h 4237951566b ./boehm-gc/include/leak_detector.h ! 3792791209b ./boehm-gc/include/new_gc_alloc.h 1547838704b ./boehm-gc/include/private/cord_pos.h ! 902196938b ./boehm-gc/include/private/dbg_mlc.h ! 1215170430b ./boehm-gc/include/private/gc_hdrs.h ! 3411375301b ./boehm-gc/include/private/gc_locks.h ! 583510369b ./boehm-gc/include/private/gc_pmark.h ! 1990877525b ./boehm-gc/include/private/gc_priv.h ! 3820561693b ./boehm-gc/include/private/gcconfig.h ! 2686914147b ./boehm-gc/include/private/solaris_threads.h ! 3935909412b ./boehm-gc/include/private/specific.h 2262051120b ./boehm-gc/include/weakpointer.h 4171599065b ./boehm-gc/install-sh - 175500712b ./boehm-gc/irix_threads.c 1133052236b ./boehm-gc/libtool.m4 - 3899988461b ./boehm-gc/linux_threads.c 604657675b ./boehm-gc/ltconfig 3301916719b ./boehm-gc/ltmain.sh ! 1572371745b ./boehm-gc/mach_dep.c ! 4270565414b ./boehm-gc/malloc.c ! 3656007348b ./boehm-gc/mallocx.c ! 2488176063b ./boehm-gc/mark.c ! 2210067257b ./boehm-gc/mark_rts.c ! 2792262463b ./boehm-gc/mips_sgi_mach_dep.S 447949782b ./boehm-gc/mips_ultrix_mach_dep.s ! 3319150875b ./boehm-gc/misc.c 4236112450b ./boehm-gc/mkinstalldirs 2583630088b ./boehm-gc/new_hblk.c 1361724709b ./boehm-gc/obj_map.c ! 2236606828b ./boehm-gc/os_dep.c 600864111b ./boehm-gc/pc_excludes 735852084b ./boehm-gc/pcr_interface.c ! 811834911b ./boehm-gc/powerpc_macosx_mach_dep.s ! 105828241b ./boehm-gc/ptr_chck.c 3988382907b ./boehm-gc/real_malloc.c ! 2946495074b ./boehm-gc/reclaim.c 2737439630b ./boehm-gc/rs6000_mach_dep.s 636267038b ./boehm-gc/setjmp_t.c ! 751650501b ./boehm-gc/solaris_pthreads.c ! 275051372b ./boehm-gc/solaris_threads.c ! 1425695416b ./boehm-gc/sparc_mach_dep.S 551455534b ./boehm-gc/sparc_netbsd_mach_dep.s 293721320b ./boehm-gc/sparc_sunos4_mach_dep.s 3072675593b ./boehm-gc/specific.c 644387711b ./boehm-gc/stubborn.c 1440779450b ./boehm-gc/tests/leak_test.c ! 1742599416b ./boehm-gc/tests/test.c ! 3630296235b ./boehm-gc/tests/test_cpp.cc 14580047b ./boehm-gc/tests/thread_leak_test.c 1499257362b ./boehm-gc/tests/trace_test.c ! 3287937987b ./boehm-gc/threadlibs.c ! 2467355438b ./boehm-gc/typd_mlc.c ! 332085760b ./boehm-gc/version.h ! 62682092b ./boehm-gc/win32_threads.c ! 1119116469b ./bugs.html ! 71055409b ./config-ml.in ! 3794184949b ./config.guess ! 2016379063b ./config.if ! 537897852b ./config.sub ! 2651333699b ./config/ChangeLog ! 430854799b ./config/acinclude.m4 ! 636889995b ./config/mh-a68bsd ! 1442196770b ./config/mh-aix386 ! 3252332438b ./config/mh-apollo68 3478341494b ./config/mh-armpic ! 902614684b ./config/mh-cxux ! 3020282061b ./config/mh-cygwin 2617404501b ./config/mh-decstation ! 973727842b ./config/mh-delta88 ! 4185392584b ./config/mh-dgux ! 3317035055b ./config/mh-dgux386 3870705974b ./config/mh-djgpp 3478341494b ./config/mh-elfalphapic - 4145550551b ./config/mh-hp300 - 1335785638b ./config/mh-hpux - 1335785638b ./config/mh-hpux8 3478341494b ./config/mh-i370pic 3265825290b ./config/mh-ia64pic ! 3591401365b ./config/mh-interix ! 1185833176b ./config/mh-irix5 ! 3858294385b ./config/mh-irix6 ! 982405557b ./config/mh-lynxrs6k 3265825290b ./config/mh-m68kpic 2677046369b ./config/mh-mingw32 ! 2709332972b ./config/mh-ncr3000 ! 1441615720b ./config/mh-ncrsvr43 ! 4162364663b ./config/mh-necv4 ! 1335785638b ./config/mh-openedition 3478341494b ./config/mh-papic 3478341494b ./config/mh-ppcpic - 633311229b ./config/mh-riscos 3265825290b ./config/mh-s390pic ! 2299205241b ./config/mh-sco ! 612532950b ./config/mh-solaris 1399222241b ./config/mh-sparcpic ! 1335785638b ./config/mh-sysv ! 1114762032b ./config/mh-sysv4 ! 1114762032b ./config/mh-sysv5 3265825290b ./config/mh-x86pic ! 2474610656b ./config/mt-aix43 3955224621b ./config/mt-alphaieee 1487563357b ./config/mt-d30v 3571760336b ./config/mt-linux 2548851201b ./config/mt-netware 971016637b ./config/mt-ospace ! 787786243b ./config/mt-v810 2659154290b ./config/mt-wince ! 4143692422b ./configure ! 4078400456b ./configure.in ! 1869491039b ./contrib/ChangeLog ! 1948950130b ./contrib/analyze_brprob ! 550196746b ./contrib/compare_tests 2828387446b ./contrib/convert_to_f2c 2929939770b ./contrib/convert_to_g2c 2025073358b ./contrib/download_f2c - 4190705069b ./contrib/gcc_build - 515992328b ./contrib/gcc_update 1336632236b ./contrib/gccbug.el ! 752127234b ./contrib/gennews 4256039795b ./contrib/index-prop 3683285493b ./contrib/newcvsroot ! 3406928738b ./contrib/paranoia.cc ! 1172428181b ./contrib/regression/ChangeLog ! 1757898889b ./contrib/regression/README ! 3661855799b ./contrib/regression/btest-gcc.sh 1435553453b ./contrib/regression/objs-gcc.sh 3103378580b ./contrib/regression/site.exp ! 3168894978b ./contrib/test_installed ! 2176599191b ./contrib/test_summary ! 1581263438b ./contrib/texi2pod.pl 4228623080b ./contrib/warn_summary 1764901825b ./faq.html ! 3707811223b ./fastjar/.cvsignore 1005262133b ./fastjar/AUTHORS 1745615150b ./fastjar/CHANGES 1396100520b ./fastjar/COPYING - 513215636b ./fastjar/ChangeLog - 2770615802b ./fastjar/INSTALL - 1805291518b ./fastjar/Makefile.am - 2841639681b ./fastjar/Makefile.in - 4038493440b ./fastjar/NEWS - 3943963407b ./fastjar/README - 54199525b ./fastjar/acinclude.m4 - 1369101675b ./fastjar/aclocal.m4 - 3743222129b ./fastjar/compress.c - 1169302702b ./fastjar/compress.h - 1117462681b ./fastjar/config.h.in - 2619265826b ./fastjar/configure - 3663315504b ./fastjar/configure.in 2553867110b ./fastjar/dostime.c 446939748b ./fastjar/dostime.h ! 2011191902b ./fastjar/fastjar.info 3589129523b ./fastjar/fastjar.texi ! 2140953762b ./fastjar/grepjar.1 2331671736b ./fastjar/install-defs.sh.in ! 1178077958b ./fastjar/install-sh ! 715748854b ./fastjar/jar.1 ! 2281221680b ./fastjar/jargrep.c 4062871816b ./fastjar/jargrep.h ! 2905933595b ./fastjar/jartool.c ! 2754304773b ./fastjar/jartool.h ! 990942143b ./fastjar/missing ! 1455437353b ./fastjar/mkinstalldirs ! 1315168235b ./fastjar/pushback.c 302085493b ./fastjar/pushback.h ! 216805921b ./fastjar/stamp-h.in ! 3071504729b ./fastjar/zipfile.h ! 1308782881b ./gcc/.cvsignore 2215240433b ./gcc/ABOUT-GCC-NLS ! 1413896246b ./gcc/ABOUT-NLS ! 2171125041b ./gcc/COPYING ! 508743035b ./gcc/COPYING.LIB ! 1746505507b ./gcc/ChangeLog ! 4112479902b ./gcc/ChangeLog.0 ! 3216066841b ./gcc/ChangeLog.1 ! 2323556130b ./gcc/ChangeLog.2 ! 3176640938b ./gcc/ChangeLog.3 ! 3015000601b ./gcc/ChangeLog.4 ! 4176743933b ./gcc/ChangeLog.5 ! 2548364434b ./gcc/ChangeLog.6 ! 1208082050b ./gcc/ChangeLog.7 ! 3235050590b ./gcc/ChangeLog.lib ! 2146007539b ./gcc/FSFChangeLog ! 2696443822b ./gcc/FSFChangeLog.10 ! 1302016933b ./gcc/FSFChangeLog.11 ! 3016546082b ./gcc/LANGUAGES ! 27665921b ./gcc/Makefile.in ! 515860724b ./gcc/NEWS ! 1799560872b ./gcc/ONEWS ! 2799003008b ./gcc/README-fixinc ! 756162762b ./gcc/README.Portability ! 1084935625b ./gcc/SERVICE ! 3729933059b ./gcc/acconfig.h ! 4067360570b ./gcc/aclocal.m4 ! 1423685038b ./gcc/ada/.cvsignore ! 3476755371b ./gcc/ada/1aexcept.adb ! 3022880533b ./gcc/ada/1aexcept.ads ! 2251433832b ./gcc/ada/1ic.ads ! 2191440237b ./gcc/ada/1ssecsta.adb ! 3514856157b ./gcc/ada/1ssecsta.ads ! 2511614379b ./gcc/ada/31soccon.ads ! 2020092279b ./gcc/ada/31soliop.ads ! 3802531266b ./gcc/ada/3asoccon.ads ! 4123202520b ./gcc/ada/3bsoccon.ads ! 3416531203b ./gcc/ada/3gsoccon.ads ! 3090342421b ./gcc/ada/3hsoccon.ads ! 861860510b ./gcc/ada/3ssoccon.ads ! 308347220b ./gcc/ada/3ssoliop.ads ! 2994673654b ./gcc/ada/3wsoccon.ads ! 607155891b ./gcc/ada/3wsocthi.adb ! 1316989620b ./gcc/ada/3wsocthi.ads ! 2811630886b ./gcc/ada/3wsoliop.ads ! 3864072001b ./gcc/ada/41intnam.ads ! 2130062026b ./gcc/ada/42intnam.ads ! 1221639557b ./gcc/ada/4aintnam.ads ! 1910436245b ./gcc/ada/4cintnam.ads ! 4134156609b ./gcc/ada/4dintnam.ads ! 2161733301b ./gcc/ada/4gintnam.ads ! 2224568272b ./gcc/ada/4hexcpol.adb ! 3599917665b ./gcc/ada/4hintnam.ads ! 633311103b ./gcc/ada/4lintnam.ads ! 22907278b ./gcc/ada/4mintnam.ads ! 2380472125b ./gcc/ada/4nintnam.ads ! 2857640960b ./gcc/ada/4ointnam.ads ! 659028582b ./gcc/ada/4onumaux.ads ! 1205711724b ./gcc/ada/4pintnam.ads ! 266939468b ./gcc/ada/4rintnam.ads ! 1762126051b ./gcc/ada/4sintnam.ads ! 2689159715b ./gcc/ada/4uintnam.ads ! 3611799279b ./gcc/ada/4vcaldel.adb ! 1212475634b ./gcc/ada/4vcalend.adb ! 722160584b ./gcc/ada/4vcalend.ads ! 182300439b ./gcc/ada/4vintnam.ads ! 3439856379b ./gcc/ada/4wcalend.adb ! 3094215319b ./gcc/ada/4wexcpol.adb ! 1159845327b ./gcc/ada/4wintnam.ads ! 85261513b ./gcc/ada/4zintnam.ads ! 3990942683b ./gcc/ada/4znumaux.ads ! 57100311b ./gcc/ada/4zsytaco.adb ! 1764501342b ./gcc/ada/4zsytaco.ads ! 2272920092b ./gcc/ada/51osinte.adb ! 1182798516b ./gcc/ada/51osinte.ads ! 3394379261b ./gcc/ada/52osinte.adb ! 416671034b ./gcc/ada/52osinte.ads ! 599905569b ./gcc/ada/52system.ads ! 1251038631b ./gcc/ada/53osinte.ads ! 2237974254b ./gcc/ada/54osinte.ads ! 1661726289b ./gcc/ada/5amastop.adb ! 3544698408b ./gcc/ada/5aosinte.adb ! 330606401b ./gcc/ada/5aosinte.ads ! 629299312b ./gcc/ada/5asystem.ads ! 2253927375b ./gcc/ada/5ataprop.adb ! 3785085609b ./gcc/ada/5atasinf.ads ! 445098646b ./gcc/ada/5ataspri.ads ! 3641787791b ./gcc/ada/5atpopsp.adb ! 3748211331b ./gcc/ada/5avxwork.ads ! 661930325b ./gcc/ada/5bosinte.adb ! 1183030227b ./gcc/ada/5bosinte.ads ! 95390389b ./gcc/ada/5bsystem.ads ! 3224075607b ./gcc/ada/5cosinte.ads ! 4067756523b ./gcc/ada/5dosinte.ads ! 4135155439b ./gcc/ada/5esystem.ads ! 3652564674b ./gcc/ada/5etpopse.adb ! 1407971971b ./gcc/ada/5fintman.adb ! 314025962b ./gcc/ada/5fosinte.ads ! 1561948410b ./gcc/ada/5fsystem.ads ! 2111090904b ./gcc/ada/5ftaprop.adb ! 1649270527b ./gcc/ada/5ftasinf.ads ! 4111312302b ./gcc/ada/5ginterr.adb ! 761494860b ./gcc/ada/5gintman.adb ! 2283439580b ./gcc/ada/5gmastop.adb ! 1273904975b ./gcc/ada/5gosinte.ads ! 1531447747b ./gcc/ada/5gproinf.adb ! 3992132528b ./gcc/ada/5gproinf.ads ! 2235216399b ./gcc/ada/5gsystem.ads ! 1074614971b ./gcc/ada/5gtaprop.adb ! 1216045678b ./gcc/ada/5gtasinf.adb ! 3051684560b ./gcc/ada/5gtasinf.ads ! 3228485956b ./gcc/ada/5gtpgetc.adb ! 1482105014b ./gcc/ada/5hosinte.adb ! 1138790463b ./gcc/ada/5hosinte.ads ! 3569104699b ./gcc/ada/5hparame.ads ! 3381576196b ./gcc/ada/5hsystem.ads ! 114481475b ./gcc/ada/5htaprop.adb ! 3985737607b ./gcc/ada/5htaspri.ads ! 1553633295b ./gcc/ada/5htraceb.adb ! 2354742934b ./gcc/ada/5iosinte.adb ! 341515731b ./gcc/ada/5iosinte.ads ! 4036108862b ./gcc/ada/5itaprop.adb ! 4209017149b ./gcc/ada/5itaspri.ads ! 3966701624b ./gcc/ada/5ksystem.ads ! 3469221755b ./gcc/ada/5kvxwork.ads ! 3333477404b ./gcc/ada/5lintman.adb ! 1002365908b ./gcc/ada/5lml-tgt.adb ! 159446570b ./gcc/ada/5losinte.ads ! 1136027948b ./gcc/ada/5lsystem.ads ! 2342382232b ./gcc/ada/5mosinte.ads ! 22175694b ./gcc/ada/5mvxwork.ads ! 820176851b ./gcc/ada/5ninmaop.adb ! 4204498933b ./gcc/ada/5nintman.adb ! 2307667247b ./gcc/ada/5nosinte.ads ! 1892616891b ./gcc/ada/5ntaprop.adb ! 1061474137b ./gcc/ada/5ntaspri.ads ! 4159557428b ./gcc/ada/5ointerr.adb ! 2159809007b ./gcc/ada/5omastop.adb ! 2019722547b ./gcc/ada/5oosinte.adb ! 94579548b ./gcc/ada/5oosinte.ads ! 3323151699b ./gcc/ada/5oosprim.adb ! 2375843411b ./gcc/ada/5oparame.adb ! 2813458373b ./gcc/ada/5osystem.ads ! 2064827163b ./gcc/ada/5otaprop.adb ! 2138761055b ./gcc/ada/5otaspri.ads ! 2126899975b ./gcc/ada/5posinte.ads ! 2287957803b ./gcc/ada/5posprim.adb ! 1181457253b ./gcc/ada/5pvxwork.ads ! 3743871039b ./gcc/ada/5qosinte.adb ! 52457731b ./gcc/ada/5qosinte.ads ! 1856329556b ./gcc/ada/5qstache.adb ! 1445919716b ./gcc/ada/5qtaprop.adb ! 2692969247b ./gcc/ada/5qtaspri.ads ! 1707765400b ./gcc/ada/5rosinte.adb ! 2024826220b ./gcc/ada/5rosinte.ads ! 54965811b ./gcc/ada/5rparame.adb ! 3957530165b ./gcc/ada/5rtpopsp.adb ! 1163200540b ./gcc/ada/5sintman.adb ! 3949337666b ./gcc/ada/5sosinte.adb ! 1560000859b ./gcc/ada/5sosinte.ads ! 146106406b ./gcc/ada/5sparame.adb ! 1305585189b ./gcc/ada/5ssystem.ads ! 3053269312b ./gcc/ada/5staprop.adb ! 4287558200b ./gcc/ada/5stasinf.adb ! 1101504362b ./gcc/ada/5stasinf.ads ! 691335402b ./gcc/ada/5staspri.ads ! 573438545b ./gcc/ada/5stpopse.adb ! 977723408b ./gcc/ada/5svxwork.ads ! 743181067b ./gcc/ada/5tosinte.ads ! 2291292459b ./gcc/ada/5uintman.adb ! 3471670416b ./gcc/ada/5uosinte.ads ! 1533466448b ./gcc/ada/5vasthan.adb ! 3181558064b ./gcc/ada/5vinmaop.adb ! 3986890387b ./gcc/ada/5vinterr.adb ! 4078156268b ./gcc/ada/5vintman.adb ! 117987244b ./gcc/ada/5vintman.ads ! 2067712643b ./gcc/ada/5vmastop.adb ! 395438714b ./gcc/ada/5vosinte.adb ! 2613021316b ./gcc/ada/5vosinte.ads ! 605174273b ./gcc/ada/5vosprim.adb ! 4255936643b ./gcc/ada/5vosprim.ads ! 4240903667b ./gcc/ada/5vparame.ads ! 3058807267b ./gcc/ada/5vsystem.ads ! 4029181318b ./gcc/ada/5vtaprop.adb ! 2532709981b ./gcc/ada/5vtaspri.ads ! 780199412b ./gcc/ada/5vtpopde.adb ! 4102009234b ./gcc/ada/5vtpopde.ads ! 2631128977b ./gcc/ada/5vvaflop.adb ! 4262337775b ./gcc/ada/5wgloloc.adb ! 2249394845b ./gcc/ada/5wintman.adb ! 2751463374b ./gcc/ada/5wmemory.adb ! 3616990531b ./gcc/ada/5wosinte.ads ! 1659711983b ./gcc/ada/5wosprim.adb ! 4283152297b ./gcc/ada/5wsystem.ads ! 1729829229b ./gcc/ada/5wtaprop.adb ! 1012802673b ./gcc/ada/5wtaspri.ads ! 2341478693b ./gcc/ada/5ysystem.ads ! 1967108827b ./gcc/ada/5zinterr.adb ! 2196483459b ./gcc/ada/5zintman.adb ! 1055330755b ./gcc/ada/5zosinte.adb ! 2446599206b ./gcc/ada/5zosinte.ads ! 3662233131b ./gcc/ada/5zosprim.adb ! 1348382967b ./gcc/ada/5zsystem.ads ! 3159175742b ./gcc/ada/5ztaprop.adb ! 2102065511b ./gcc/ada/6vcpp.adb ! 2689894027b ./gcc/ada/6vcstrea.adb ! 3306533281b ./gcc/ada/6vinterf.ads ! 694204948b ./gcc/ada/7sinmaop.adb ! 2049788032b ./gcc/ada/7sintman.adb ! 476691739b ./gcc/ada/7sosinte.adb ! 3965227943b ./gcc/ada/7sosprim.adb ! 1997910804b ./gcc/ada/7staprop.adb ! 1764982560b ./gcc/ada/7staspri.ads ! 1493206491b ./gcc/ada/7stpopsp.adb ! 1740285994b ./gcc/ada/7straceb.adb ! 1363857210b ./gcc/ada/86numaux.adb ! 4053303068b ./gcc/ada/86numaux.ads ! 3760778950b ./gcc/ada/9drpc.adb ! 998495436b ./gcc/ada/ChangeLog ! 1311661804b ./gcc/ada/Make-lang.in ! 4249262083b ./gcc/ada/Makefile.adalib ! 3255053300b ./gcc/ada/Makefile.in ! 2280800531b ./gcc/ada/a-astaco.adb ! 3259280671b ./gcc/ada/a-astaco.ads ! 367890918b ./gcc/ada/a-caldel.adb ! 2850927655b ./gcc/ada/a-caldel.ads ! 2264463076b ./gcc/ada/a-calend.adb ! 3705096499b ./gcc/ada/a-calend.ads ! 2432115721b ./gcc/ada/a-chahan.adb ! 2062715973b ./gcc/ada/a-chahan.ads ! 2585470398b ./gcc/ada/a-charac.ads ! 475906449b ./gcc/ada/a-chlat1.ads ! 1016788241b ./gcc/ada/a-chlat9.ads ! 474399754b ./gcc/ada/a-colien.adb ! 2019585318b ./gcc/ada/a-colien.ads ! 446719574b ./gcc/ada/a-colire.adb ! 3911502658b ./gcc/ada/a-colire.ads ! 4208260302b ./gcc/ada/a-comlin.adb ! 2676889573b ./gcc/ada/a-comlin.ads ! 2671391885b ./gcc/ada/a-cwila1.ads ! 3799548269b ./gcc/ada/a-cwila9.ads ! 2562885096b ./gcc/ada/a-decima.adb ! 3964508631b ./gcc/ada/a-decima.ads ! 4162793785b ./gcc/ada/a-diocst.adb ! 3798368130b ./gcc/ada/a-diocst.ads ! 1037920363b ./gcc/ada/a-direio.adb ! 1125839799b ./gcc/ada/a-direio.ads ! 1891718240b ./gcc/ada/a-dynpri.adb ! 1228228526b ./gcc/ada/a-dynpri.ads ! 2515816420b ./gcc/ada/a-einuoc.adb ! 1361226149b ./gcc/ada/a-einuoc.ads ! 289090565b ./gcc/ada/a-except.adb ! 1373330010b ./gcc/ada/a-except.ads ! 2635307314b ./gcc/ada/a-excpol.adb ! 1476905781b ./gcc/ada/a-exctra.adb ! 3119338693b ./gcc/ada/a-exctra.ads ! 3314908396b ./gcc/ada/a-filico.adb ! 1154496649b ./gcc/ada/a-filico.ads ! 3900641047b ./gcc/ada/a-finali.adb ! 3971104804b ./gcc/ada/a-finali.ads ! 4084067249b ./gcc/ada/a-flteio.ads ! 2838243354b ./gcc/ada/a-fwteio.ads ! 2553750682b ./gcc/ada/a-inteio.ads ! 2112216622b ./gcc/ada/a-interr.adb ! 3711128136b ./gcc/ada/a-interr.ads ! 2252700482b ./gcc/ada/a-intnam.ads ! 3783787070b ./gcc/ada/a-intsig.adb ! 3753195216b ./gcc/ada/a-intsig.ads ! 4260440302b ./gcc/ada/a-ioexce.ads ! 1320750593b ./gcc/ada/a-iwteio.ads ! 3184637491b ./gcc/ada/a-lfteio.ads ! 3399197938b ./gcc/ada/a-lfwtio.ads ! 4181349523b ./gcc/ada/a-liteio.ads ! 4061818571b ./gcc/ada/a-liwtio.ads ! 2391273921b ./gcc/ada/a-llftio.ads ! 589145108b ./gcc/ada/a-llfwti.ads ! 733828438b ./gcc/ada/a-llitio.ads ! 2019981437b ./gcc/ada/a-lliwti.ads ! 4202114661b ./gcc/ada/a-ncelfu.ads ! 2982795424b ./gcc/ada/a-ngcefu.adb ! 2417195295b ./gcc/ada/a-ngcefu.ads ! 3422153681b ./gcc/ada/a-ngcoty.adb ! 2702884127b ./gcc/ada/a-ngcoty.ads ! 1264432570b ./gcc/ada/a-ngelfu.adb ! 4251236541b ./gcc/ada/a-ngelfu.ads ! 311918519b ./gcc/ada/a-nlcefu.ads ! 4262096075b ./gcc/ada/a-nlcoty.ads ! 1836187080b ./gcc/ada/a-nlelfu.ads ! 2034585729b ./gcc/ada/a-nllcef.ads ! 1706106687b ./gcc/ada/a-nllcty.ads ! 1710244911b ./gcc/ada/a-nllefu.ads ! 660173792b ./gcc/ada/a-nscefu.ads ! 2693186813b ./gcc/ada/a-nscoty.ads ! 414125373b ./gcc/ada/a-nselfu.ads ! 1771932863b ./gcc/ada/a-nucoty.ads ! 2830452418b ./gcc/ada/a-nudira.adb ! 2698500475b ./gcc/ada/a-nudira.ads ! 1941470210b ./gcc/ada/a-nuelfu.ads ! 578585452b ./gcc/ada/a-nuflra.adb ! 562766691b ./gcc/ada/a-nuflra.ads ! 3306765590b ./gcc/ada/a-numaux.ads ! 615971690b ./gcc/ada/a-numeri.ads ! 2251853720b ./gcc/ada/a-reatim.adb ! 3420934441b ./gcc/ada/a-reatim.ads ! 2422313336b ./gcc/ada/a-retide.adb ! 2786353850b ./gcc/ada/a-retide.ads ! 915291874b ./gcc/ada/a-sequio.adb ! 2781518414b ./gcc/ada/a-sequio.ads ! 1028548096b ./gcc/ada/a-sfteio.ads ! 756561237b ./gcc/ada/a-sfwtio.ads ! 2149334054b ./gcc/ada/a-siocst.adb ! 1013973588b ./gcc/ada/a-siocst.ads ! 1542052045b ./gcc/ada/a-siteio.ads ! 898470063b ./gcc/ada/a-siwtio.ads ! 2664255451b ./gcc/ada/a-ssicst.adb ! 3968217970b ./gcc/ada/a-ssicst.ads ! 2040244723b ./gcc/ada/a-ssitio.ads ! 3856185038b ./gcc/ada/a-ssiwti.ads ! 3843904384b ./gcc/ada/a-stmaco.ads ! 2558304413b ./gcc/ada/a-storio.adb ! 2039645547b ./gcc/ada/a-storio.ads ! 2545807360b ./gcc/ada/a-strbou.adb ! 1649576447b ./gcc/ada/a-strbou.ads ! 4189169864b ./gcc/ada/a-stream.ads ! 312272500b ./gcc/ada/a-strfix.adb ! 1836795891b ./gcc/ada/a-strfix.ads ! 452191775b ./gcc/ada/a-string.ads ! 3440162100b ./gcc/ada/a-strmap.adb ! 2813601661b ./gcc/ada/a-strmap.ads ! 2242083134b ./gcc/ada/a-strsea.adb ! 1087128520b ./gcc/ada/a-strsea.ads ! 2129652476b ./gcc/ada/a-strunb.adb ! 1086280505b ./gcc/ada/a-strunb.ads ! 3244198764b ./gcc/ada/a-ststio.adb ! 1434597636b ./gcc/ada/a-ststio.ads ! 3563861726b ./gcc/ada/a-stunau.adb ! 1904848935b ./gcc/ada/a-stunau.ads ! 847226371b ./gcc/ada/a-stwibo.adb ! 3765473566b ./gcc/ada/a-stwibo.ads ! 1000480915b ./gcc/ada/a-stwifi.adb ! 920074266b ./gcc/ada/a-stwifi.ads ! 1758378198b ./gcc/ada/a-stwima.adb ! 388329618b ./gcc/ada/a-stwima.ads ! 2111278285b ./gcc/ada/a-stwise.adb ! 489428799b ./gcc/ada/a-stwise.ads ! 931863816b ./gcc/ada/a-stwiun.adb ! 163835538b ./gcc/ada/a-stwiun.ads ! 1312891822b ./gcc/ada/a-suteio.adb ! 985067551b ./gcc/ada/a-suteio.ads ! 1525903292b ./gcc/ada/a-swmwco.ads ! 1588030610b ./gcc/ada/a-swuwti.adb ! 3037851063b ./gcc/ada/a-swuwti.ads ! 1272213971b ./gcc/ada/a-sytaco.adb ! 1711371162b ./gcc/ada/a-sytaco.ads ! 2802470452b ./gcc/ada/a-tags.adb ! 1139968956b ./gcc/ada/a-tags.ads ! 1682735148b ./gcc/ada/a-tasatt.adb ! 2506460027b ./gcc/ada/a-tasatt.ads ! 1017733066b ./gcc/ada/a-taside.adb ! 449278150b ./gcc/ada/a-taside.ads ! 2262767398b ./gcc/ada/a-teioed.adb ! 942283074b ./gcc/ada/a-teioed.ads ! 4268790192b ./gcc/ada/a-textio.adb ! 2542210919b ./gcc/ada/a-textio.ads ! 955977038b ./gcc/ada/a-ticoau.adb ! 2276027850b ./gcc/ada/a-ticoau.ads ! 3483744171b ./gcc/ada/a-ticoio.adb ! 665665210b ./gcc/ada/a-ticoio.ads ! 1248666345b ./gcc/ada/a-tideau.adb ! 4051134505b ./gcc/ada/a-tideau.ads ! 702405015b ./gcc/ada/a-tideio.adb ! 2372089939b ./gcc/ada/a-tideio.ads ! 3343604978b ./gcc/ada/a-tienau.adb ! 1925813485b ./gcc/ada/a-tienau.ads ! 3960488072b ./gcc/ada/a-tienio.adb ! 2111373475b ./gcc/ada/a-tienio.ads ! 3736901273b ./gcc/ada/a-tifiio.adb ! 629253286b ./gcc/ada/a-tifiio.ads ! 677807166b ./gcc/ada/a-tiflau.adb ! 1615304674b ./gcc/ada/a-tiflau.ads ! 2814224774b ./gcc/ada/a-tiflio.adb ! 1672570592b ./gcc/ada/a-tiflio.ads ! 810361168b ./gcc/ada/a-tigeau.adb ! 1572153528b ./gcc/ada/a-tigeau.ads ! 819961222b ./gcc/ada/a-tiinau.adb ! 2292489642b ./gcc/ada/a-tiinau.ads ! 1710485185b ./gcc/ada/a-tiinio.adb ! 2237530049b ./gcc/ada/a-tiinio.ads ! 330984461b ./gcc/ada/a-timoau.adb ! 2636796425b ./gcc/ada/a-timoau.ads ! 3963870398b ./gcc/ada/a-timoio.adb ! 2610046346b ./gcc/ada/a-timoio.ads ! 214132248b ./gcc/ada/a-tiocst.adb ! 4121988035b ./gcc/ada/a-tiocst.ads ! 3910455454b ./gcc/ada/a-titest.adb ! 3599822963b ./gcc/ada/a-titest.ads ! 2501643743b ./gcc/ada/a-unccon.ads ! 125078292b ./gcc/ada/a-uncdea.ads ! 29969073b ./gcc/ada/a-witeio.adb ! 1654805280b ./gcc/ada/a-witeio.ads ! 399909379b ./gcc/ada/a-wtcoau.adb ! 15915668b ./gcc/ada/a-wtcoau.ads ! 3269698900b ./gcc/ada/a-wtcoio.adb ! 2633134472b ./gcc/ada/a-wtcoio.ads ! 3508555518b ./gcc/ada/a-wtcstr.adb ! 2332040028b ./gcc/ada/a-wtcstr.ads ! 641727529b ./gcc/ada/a-wtdeau.adb ! 2322401430b ./gcc/ada/a-wtdeau.ads ! 2118372476b ./gcc/ada/a-wtdeio.adb ! 2112087328b ./gcc/ada/a-wtdeio.ads ! 3854209025b ./gcc/ada/a-wtedit.adb ! 479264111b ./gcc/ada/a-wtedit.ads ! 1980816428b ./gcc/ada/a-wtenau.adb ! 3157540776b ./gcc/ada/a-wtenau.ads ! 3636478590b ./gcc/ada/a-wtenio.adb ! 2040027206b ./gcc/ada/a-wtenio.ads ! 890247767b ./gcc/ada/a-wtfiio.adb ! 2831441596b ./gcc/ada/a-wtfiio.ads ! 2557337210b ./gcc/ada/a-wtflau.adb ! 2182558825b ./gcc/ada/a-wtflau.ads ! 3508822041b ./gcc/ada/a-wtflio.adb ! 2091412810b ./gcc/ada/a-wtflio.ads ! 1511767393b ./gcc/ada/a-wtgeau.adb ! 2832624988b ./gcc/ada/a-wtgeau.ads ! 1836843487b ./gcc/ada/a-wtinau.adb ! 2000363120b ./gcc/ada/a-wtinau.ads ! 1243322800b ./gcc/ada/a-wtinio.adb ! 2970643185b ./gcc/ada/a-wtinio.ads ! 2930847231b ./gcc/ada/a-wtmoau.adb ! 2244525143b ./gcc/ada/a-wtmoau.ads ! 5494583b ./gcc/ada/a-wtmoio.adb ! 775232154b ./gcc/ada/a-wtmoio.ads ! 663806314b ./gcc/ada/a-wttest.adb ! 2990280730b ./gcc/ada/a-wttest.ads ! 1982115237b ./gcc/ada/ada-tree.def ! 1334528231b ./gcc/ada/ada-tree.h ! 3768095897b ./gcc/ada/ada.ads ! 1951378334b ./gcc/ada/ada.h ! 1295005255b ./gcc/ada/adadecode.c ! 1590048241b ./gcc/ada/adadecode.h ! 3752930348b ./gcc/ada/adafinal.c ! 4254504525b ./gcc/ada/adaint.c ! 842239939b ./gcc/ada/adaint.h ! 510875974b ./gcc/ada/ali-util.adb ! 3777303034b ./gcc/ada/ali-util.ads ! 394580827b ./gcc/ada/ali.adb ! 2668171343b ./gcc/ada/ali.ads ! 641549079b ./gcc/ada/alloc.ads ! 899190514b ./gcc/ada/argv.c ! 618728363b ./gcc/ada/atree.adb ! 1328381436b ./gcc/ada/atree.ads ! 3927429423b ./gcc/ada/atree.h ! 3257044236b ./gcc/ada/aux-io.c ! 1819935344b ./gcc/ada/back_end.adb ! 2085249332b ./gcc/ada/back_end.ads ! 2077333587b ./gcc/ada/bcheck.adb ! 610231922b ./gcc/ada/bcheck.ads ! 3315023152b ./gcc/ada/binde.adb ! 1670324692b ./gcc/ada/binde.ads ! 2059683005b ./gcc/ada/binderr.adb ! 3223521218b ./gcc/ada/binderr.ads ! 1109941393b ./gcc/ada/bindgen.adb ! 295408128b ./gcc/ada/bindgen.ads ! 2463228634b ./gcc/ada/bindusg.adb ! 2314222747b ./gcc/ada/bindusg.ads ! 2678651278b ./gcc/ada/butil.adb ! 440542872b ./gcc/ada/butil.ads ! 2310836100b ./gcc/ada/cal.c ! 1268893086b ./gcc/ada/calendar.ads ! 819907824b ./gcc/ada/casing.adb ! 383971693b ./gcc/ada/casing.ads ! 2658802005b ./gcc/ada/ceinfo.adb ! 2766796861b ./gcc/ada/checks.adb ! 2020343191b ./gcc/ada/checks.ads ! 1422160412b ./gcc/ada/cio.c ! 2875263289b ./gcc/ada/comperr.adb ! 1231263286b ./gcc/ada/comperr.ads ! 1849806667b ./gcc/ada/config-lang.in ! 1823124766b ./gcc/ada/csets.adb ! 3233617109b ./gcc/ada/csets.ads ! 90812921b ./gcc/ada/csinfo.adb ! 3005500375b ./gcc/ada/cstand.adb ! 281967843b ./gcc/ada/cstand.ads ! 2588845972b ./gcc/ada/cstreams.c ! 1496314704b ./gcc/ada/cuintp.c ! 4058447839b ./gcc/ada/debug.adb ! 1164136597b ./gcc/ada/debug.ads ! 282379933b ./gcc/ada/debug_a.adb ! 2893733810b ./gcc/ada/debug_a.ads ! 2327476984b ./gcc/ada/dec-io.adb ! 564204733b ./gcc/ada/dec-io.ads ! 4020479104b ./gcc/ada/dec.ads ! 269093773b ./gcc/ada/decl.c ! 3825382514b ./gcc/ada/deftarg.c ! 238197807b ./gcc/ada/directio.ads ! 511345179b ./gcc/ada/einfo.adb ! 248137143b ./gcc/ada/einfo.ads ! 3647101285b ./gcc/ada/einfo.h ! 616869107b ./gcc/ada/elists.adb ! 56994651b ./gcc/ada/elists.ads ! 1004247325b ./gcc/ada/elists.h ! 2475394593b ./gcc/ada/errno.c ! 4176702965b ./gcc/ada/errout.adb ! 3196840869b ./gcc/ada/errout.ads ! 3148452071b ./gcc/ada/eval_fat.adb ! 4226389411b ./gcc/ada/eval_fat.ads ! 1134022627b ./gcc/ada/exit.c ! 2205430929b ./gcc/ada/exp_aggr.adb ! 407903332b ./gcc/ada/exp_aggr.ads ! 4053842288b ./gcc/ada/exp_attr.adb ! 3526764645b ./gcc/ada/exp_attr.ads ! 235818397b ./gcc/ada/exp_ch10.ads ! 2818648683b ./gcc/ada/exp_ch11.adb ! 3533146355b ./gcc/ada/exp_ch11.ads ! 2334668711b ./gcc/ada/exp_ch12.adb ! 4092536961b ./gcc/ada/exp_ch12.ads ! 176447720b ./gcc/ada/exp_ch13.adb ! 2521527262b ./gcc/ada/exp_ch13.ads ! 1221904762b ./gcc/ada/exp_ch2.adb ! 3294806844b ./gcc/ada/exp_ch2.ads ! 4281826131b ./gcc/ada/exp_ch3.adb ! 2507567557b ./gcc/ada/exp_ch3.ads ! 2656116038b ./gcc/ada/exp_ch4.adb ! 1502930229b ./gcc/ada/exp_ch4.ads ! 758996479b ./gcc/ada/exp_ch5.adb ! 2064741599b ./gcc/ada/exp_ch5.ads ! 791462490b ./gcc/ada/exp_ch6.adb ! 544091101b ./gcc/ada/exp_ch6.ads ! 1034010091b ./gcc/ada/exp_ch7.adb ! 2662188587b ./gcc/ada/exp_ch7.ads ! 3988114403b ./gcc/ada/exp_ch8.adb ! 3648275711b ./gcc/ada/exp_ch8.ads ! 2387291365b ./gcc/ada/exp_ch9.adb ! 2693227642b ./gcc/ada/exp_ch9.ads ! 559795574b ./gcc/ada/exp_code.adb ! 121970742b ./gcc/ada/exp_code.ads ! 3428155909b ./gcc/ada/exp_dbug.adb ! 1356780760b ./gcc/ada/exp_dbug.ads ! 1275956251b ./gcc/ada/exp_disp.adb ! 2931129238b ./gcc/ada/exp_disp.ads ! 1762813961b ./gcc/ada/exp_dist.adb ! 1584948667b ./gcc/ada/exp_dist.ads ! 611747716b ./gcc/ada/exp_fixd.adb ! 3285837422b ./gcc/ada/exp_fixd.ads ! 2525026740b ./gcc/ada/exp_imgv.adb ! 3516513979b ./gcc/ada/exp_imgv.ads ! 3844454892b ./gcc/ada/exp_intr.adb ! 537028872b ./gcc/ada/exp_intr.ads ! 1048921478b ./gcc/ada/exp_pakd.adb ! 1524361927b ./gcc/ada/exp_pakd.ads ! 1168291146b ./gcc/ada/exp_prag.adb ! 769332415b ./gcc/ada/exp_prag.ads ! 3827387746b ./gcc/ada/exp_smem.adb ! 2116635502b ./gcc/ada/exp_smem.ads ! 2713308952b ./gcc/ada/exp_strm.adb ! 1540246149b ./gcc/ada/exp_strm.ads ! 2105460934b ./gcc/ada/exp_tss.adb ! 1765437710b ./gcc/ada/exp_tss.ads ! 2284259498b ./gcc/ada/exp_util.adb ! 2076521219b ./gcc/ada/exp_util.ads ! 700545860b ./gcc/ada/exp_vfpt.adb ! 100115849b ./gcc/ada/exp_vfpt.ads ! 1707095337b ./gcc/ada/expander.adb ! 326210343b ./gcc/ada/expander.ads ! 4257430321b ./gcc/ada/expect.c ! 1835720949b ./gcc/ada/fe.h ! 4158495892b ./gcc/ada/fmap.adb ! 3938265786b ./gcc/ada/fmap.ads ! 88842572b ./gcc/ada/fname-sf.adb ! 3062888730b ./gcc/ada/fname-sf.ads ! 3767595337b ./gcc/ada/fname-uf.adb ! 406969945b ./gcc/ada/fname-uf.ads ! 3153532790b ./gcc/ada/fname.adb ! 4114894862b ./gcc/ada/fname.ads ! 2227723631b ./gcc/ada/freeze.adb ! 1206777338b ./gcc/ada/freeze.ads ! 1826922110b ./gcc/ada/frontend.adb ! 676042928b ./gcc/ada/frontend.ads ! 3777138484b ./gcc/ada/g-awk.adb ! 195728151b ./gcc/ada/g-awk.ads ! 4003887320b ./gcc/ada/g-busora.adb ! 1554164314b ./gcc/ada/g-busora.ads ! 4279742334b ./gcc/ada/g-busorg.adb ! 961766446b ./gcc/ada/g-busorg.ads ! 2044229632b ./gcc/ada/g-calend.adb ! 1871777734b ./gcc/ada/g-calend.ads ! 2463536054b ./gcc/ada/g-casuti.adb ! 4184607737b ./gcc/ada/g-casuti.ads ! 1568571149b ./gcc/ada/g-catiio.adb ! 856490972b ./gcc/ada/g-catiio.ads ! 411567761b ./gcc/ada/g-cgi.adb ! 1605337887b ./gcc/ada/g-cgi.ads ! 3170554685b ./gcc/ada/g-cgicoo.adb ! 3501738986b ./gcc/ada/g-cgicoo.ads ! 1510367608b ./gcc/ada/g-cgideb.adb ! 2766087039b ./gcc/ada/g-cgideb.ads ! 835608648b ./gcc/ada/g-comlin.adb ! 3977497081b ./gcc/ada/g-comlin.ads ! 329127690b ./gcc/ada/g-crc32.adb ! 1568690540b ./gcc/ada/g-crc32.ads ! 3616287417b ./gcc/ada/g-curexc.ads ! 2927265554b ./gcc/ada/g-debpoo.adb ! 1885333662b ./gcc/ada/g-debpoo.ads ! 1269256047b ./gcc/ada/g-debuti.adb ! 2222481425b ./gcc/ada/g-debuti.ads ! 3634284999b ./gcc/ada/g-diopit.adb ! 2583507319b ./gcc/ada/g-diopit.ads ! 2061346770b ./gcc/ada/g-dirope.adb ! 2521970571b ./gcc/ada/g-dirope.ads ! 397180417b ./gcc/ada/g-dyntab.adb ! 748979667b ./gcc/ada/g-dyntab.ads ! 514040300b ./gcc/ada/g-enblsp.adb ! 997169893b ./gcc/ada/g-except.ads ! 401435319b ./gcc/ada/g-exctra.adb ! 3791669892b ./gcc/ada/g-exctra.ads ! 76806179b ./gcc/ada/g-expect.adb ! 872129069b ./gcc/ada/g-expect.ads ! 2314156678b ./gcc/ada/g-flocon.ads ! 592047281b ./gcc/ada/g-hesora.adb ! 1944268715b ./gcc/ada/g-hesora.ads ! 3121769016b ./gcc/ada/g-hesorg.adb ! 650879790b ./gcc/ada/g-hesorg.ads ! 3338369479b ./gcc/ada/g-htable.adb ! 3587450756b ./gcc/ada/g-htable.ads ! 2866037851b ./gcc/ada/g-io.adb ! 648542470b ./gcc/ada/g-io.ads ! 2816296285b ./gcc/ada/g-io_aux.adb ! 2095985066b ./gcc/ada/g-io_aux.ads ! 206565595b ./gcc/ada/g-locfil.adb ! 2765360318b ./gcc/ada/g-locfil.ads ! 1110643939b ./gcc/ada/g-md5.adb ! 313686793b ./gcc/ada/g-md5.ads ! 1229364627b ./gcc/ada/g-moreex.adb ! 1570727780b ./gcc/ada/g-moreex.ads ! 338464037b ./gcc/ada/g-os_lib.adb ! 513796027b ./gcc/ada/g-os_lib.ads ! 3830058578b ./gcc/ada/g-regexp.adb ! 3070508642b ./gcc/ada/g-regexp.ads ! 3686549610b ./gcc/ada/g-regist.adb ! 747937862b ./gcc/ada/g-regist.ads ! 3753845184b ./gcc/ada/g-regpat.adb ! 138782653b ./gcc/ada/g-regpat.ads ! 1544278900b ./gcc/ada/g-soccon.ads ! 2379071440b ./gcc/ada/g-socket.adb ! 4174873093b ./gcc/ada/g-socket.ads ! 3785404924b ./gcc/ada/g-socthi.adb ! 4269123058b ./gcc/ada/g-socthi.ads ! 3126417264b ./gcc/ada/g-soliop.ads ! 3097077070b ./gcc/ada/g-souinf.ads ! 3686684815b ./gcc/ada/g-speche.adb ! 464423481b ./gcc/ada/g-speche.ads ! 3531734945b ./gcc/ada/g-spipat.adb ! 2004680943b ./gcc/ada/g-spipat.ads ! 4054796442b ./gcc/ada/g-spitbo.adb ! 851716979b ./gcc/ada/g-spitbo.ads ! 209235236b ./gcc/ada/g-sptabo.ads ! 3316143435b ./gcc/ada/g-sptain.ads ! 3012239657b ./gcc/ada/g-sptavs.ads ! 1756615822b ./gcc/ada/g-table.adb ! 1263895460b ./gcc/ada/g-table.ads ! 287058550b ./gcc/ada/g-tasloc.adb ! 3577598512b ./gcc/ada/g-tasloc.ads ! 3777760030b ./gcc/ada/g-thread.adb ! 1458239623b ./gcc/ada/g-thread.ads ! 3423345674b ./gcc/ada/g-traceb.adb ! 110997839b ./gcc/ada/g-traceb.ads ! 4154493035b ./gcc/ada/g-trasym.adb ! 2114872806b ./gcc/ada/g-trasym.ads ! 1210185367b ./gcc/ada/get_targ.adb ! 667434559b ./gcc/ada/get_targ.ads ! 2523297721b ./gcc/ada/gigi.h ! 1321722641b ./gcc/ada/gmem.c ! 4283135334b ./gcc/ada/gnat-style.texi ! 1113521052b ./gcc/ada/gnat.ads ! 394153681b ./gcc/ada/gnat1drv.adb ! 1023650319b ./gcc/ada/gnat1drv.ads ! 2672136726b ./gcc/ada/gnat_rm.texi ! 2087208411b ./gcc/ada/gnat_ug.texi ! 804303635b ./gcc/ada/gnat_ug_unx.texi ! 1719659850b ./gcc/ada/gnat_ug_vms.texi ! 1705774003b ./gcc/ada/gnat_ug_vxw.texi ! 1236505387b ./gcc/ada/gnat_ug_wnt.texi ! 3119768779b ./gcc/ada/gnatbind.adb ! 33603998b ./gcc/ada/gnatbind.ads ! 1627437503b ./gcc/ada/gnatbl.c ! 540500642b ./gcc/ada/gnatchop.adb ! 2969604217b ./gcc/ada/gnatcmd.adb ! 4090853881b ./gcc/ada/gnatcmd.ads ! 2859978646b ./gcc/ada/gnatdll.adb ! 897045337b ./gcc/ada/gnatfind.adb ! 4239198286b ./gcc/ada/gnatkr.adb ! 2263227460b ./gcc/ada/gnatkr.ads ! 2824021054b ./gcc/ada/gnatlbr.adb ! 2717759059b ./gcc/ada/gnatlink.adb ! 2418815267b ./gcc/ada/gnatlink.ads ! 424096833b ./gcc/ada/gnatls.adb ! 1028292021b ./gcc/ada/gnatls.ads ! 3044577120b ./gcc/ada/gnatmake.adb ! 2090105224b ./gcc/ada/gnatmake.ads ! 3774075467b ./gcc/ada/gnatmem.adb ! 1656761015b ./gcc/ada/gnatname.adb ! 2261990630b ./gcc/ada/gnatname.ads ! 2304496705b ./gcc/ada/gnatprep.adb ! 2739505905b ./gcc/ada/gnatprep.ads ! 2618438921b ./gcc/ada/gnatpsta.adb ! 3334144073b ./gcc/ada/gnatvsn.adb ! 1947192708b ./gcc/ada/gnatvsn.ads ! 1802022950b ./gcc/ada/gnatxref.adb ! 1992194948b ./gcc/ada/hlo.adb ! 7965000b ./gcc/ada/hlo.ads ! 3338520812b ./gcc/ada/hostparm.ads ! 1669538892b ./gcc/ada/i-c.adb ! 3530665587b ./gcc/ada/i-c.ads ! 1230378873b ./gcc/ada/i-cexten.ads ! 2075740660b ./gcc/ada/i-cobol.adb ! 3820285535b ./gcc/ada/i-cobol.ads ! 1479110528b ./gcc/ada/i-cpoint.adb ! 819019048b ./gcc/ada/i-cpoint.ads ! 298672945b ./gcc/ada/i-cpp.adb ! 28240857b ./gcc/ada/i-cpp.ads ! 1834260068b ./gcc/ada/i-cstrea.adb ! 43927628b ./gcc/ada/i-cstrea.ads ! 3182760100b ./gcc/ada/i-cstrin.adb ! 760004464b ./gcc/ada/i-cstrin.ads ! 1082363589b ./gcc/ada/i-fortra.adb ! 437203870b ./gcc/ada/i-fortra.ads ! 3167896627b ./gcc/ada/i-os2err.ads ! 1197558233b ./gcc/ada/i-os2lib.adb ! 2393101475b ./gcc/ada/i-os2lib.ads ! 3768225662b ./gcc/ada/i-os2syn.ads ! 113148653b ./gcc/ada/i-os2thr.ads ! 1225602965b ./gcc/ada/i-pacdec.adb ! 2496798758b ./gcc/ada/i-pacdec.ads ! 2140184443b ./gcc/ada/i-vxwork.ads ! 2860077370b ./gcc/ada/impunit.adb ! 1270682056b ./gcc/ada/impunit.ads ! 3972829514b ./gcc/ada/init.c ! 3278491691b ./gcc/ada/inline.adb ! 1762674301b ./gcc/ada/inline.ads ! 2192188241b ./gcc/ada/interfac.ads ! 629054167b ./gcc/ada/io-aux.c ! 2207881126b ./gcc/ada/ioexcept.ads ! 2314855848b ./gcc/ada/itypes.adb ! 2459378339b ./gcc/ada/itypes.ads ! 632117246b ./gcc/ada/krunch.adb ! 4246886280b ./gcc/ada/krunch.ads ! 1862862910b ./gcc/ada/lang-options.h ! 3845386634b ./gcc/ada/lang-specs.h ! 4287853992b ./gcc/ada/layout.adb ! 4081150350b ./gcc/ada/layout.ads ! 2597706667b ./gcc/ada/lib-list.adb ! 4055706216b ./gcc/ada/lib-load.adb ! 1245484453b ./gcc/ada/lib-load.ads ! 1969356493b ./gcc/ada/lib-sort.adb ! 626402722b ./gcc/ada/lib-util.adb ! 2975162935b ./gcc/ada/lib-util.ads ! 2489845101b ./gcc/ada/lib-writ.adb ! 1673066597b ./gcc/ada/lib-writ.ads ! 2264530243b ./gcc/ada/lib-xref.adb ! 901200146b ./gcc/ada/lib-xref.ads ! 2230935205b ./gcc/ada/lib.adb ! 2936051516b ./gcc/ada/lib.ads ! 999948081b ./gcc/ada/link.c ! 2630990747b ./gcc/ada/live.adb ! 2000138918b ./gcc/ada/live.ads ! 1415864294b ./gcc/ada/machcode.ads ! 122623076b ./gcc/ada/make.adb ! 793009024b ./gcc/ada/make.ads ! 2487708892b ./gcc/ada/makeusg.adb ! 3790916888b ./gcc/ada/makeusg.ads ! 3923163233b ./gcc/ada/math_lib.adb ! 3362749341b ./gcc/ada/mdll-fil.adb ! 1485790591b ./gcc/ada/mdll-fil.ads ! 1067337271b ./gcc/ada/mdll-utl.adb ! 1242830681b ./gcc/ada/mdll-utl.ads ! 1956935174b ./gcc/ada/mdll.adb ! 3933871472b ./gcc/ada/mdll.ads ! 1750383127b ./gcc/ada/memroot.adb ! 3615380192b ./gcc/ada/memroot.ads ! 608378712b ./gcc/ada/memtrack.adb ! 2932384816b ./gcc/ada/misc.c ! 3998763736b ./gcc/ada/mkdir.c ! 2065833419b ./gcc/ada/mlib-fil.adb ! 1905259349b ./gcc/ada/mlib-fil.ads ! 2608943021b ./gcc/ada/mlib-prj.adb ! 1529256654b ./gcc/ada/mlib-prj.ads ! 3283324341b ./gcc/ada/mlib-tgt.adb ! 3830455991b ./gcc/ada/mlib-tgt.ads ! 81774383b ./gcc/ada/mlib-utl.adb ! 1275564670b ./gcc/ada/mlib-utl.ads ! 203897137b ./gcc/ada/mlib.adb ! 2020670378b ./gcc/ada/mlib.ads ! 3538350861b ./gcc/ada/namet.adb ! 3639574738b ./gcc/ada/namet.ads ! 1508657599b ./gcc/ada/namet.h ! 340034992b ./gcc/ada/nlists.adb ! 818865783b ./gcc/ada/nlists.ads ! 72558113b ./gcc/ada/nlists.h ! 3764030160b ./gcc/ada/nmake.adb ! 3274222280b ./gcc/ada/nmake.ads ! 3284608311b ./gcc/ada/nmake.adt ! 3260145123b ./gcc/ada/opt.adb ! 3447732531b ./gcc/ada/opt.ads ! 1098506633b ./gcc/ada/osint-b.adb ! 1413972832b ./gcc/ada/osint-b.ads ! 516902818b ./gcc/ada/osint-c.adb ! 2923643768b ./gcc/ada/osint-c.ads ! 3431937667b ./gcc/ada/osint-l.adb ! 1051131321b ./gcc/ada/osint-l.ads ! 1024511265b ./gcc/ada/osint-m.adb ! 3386418329b ./gcc/ada/osint-m.ads ! 915506958b ./gcc/ada/osint.adb ! 2272158773b ./gcc/ada/osint.ads ! 1573212521b ./gcc/ada/output.adb ! 2178583884b ./gcc/ada/output.ads ! 4236451772b ./gcc/ada/par-ch10.adb ! 1865473235b ./gcc/ada/par-ch11.adb ! 169758113b ./gcc/ada/par-ch12.adb ! 2654076926b ./gcc/ada/par-ch13.adb ! 2010507628b ./gcc/ada/par-ch2.adb ! 122888040b ./gcc/ada/par-ch3.adb ! 1660113933b ./gcc/ada/par-ch4.adb ! 457010280b ./gcc/ada/par-ch5.adb ! 1487424859b ./gcc/ada/par-ch6.adb ! 2829010181b ./gcc/ada/par-ch7.adb ! 2316044432b ./gcc/ada/par-ch8.adb ! 2506138788b ./gcc/ada/par-ch9.adb ! 1062189622b ./gcc/ada/par-endh.adb ! 1168771263b ./gcc/ada/par-labl.adb ! 2269988244b ./gcc/ada/par-load.adb ! 3261829805b ./gcc/ada/par-prag.adb ! 2376621938b ./gcc/ada/par-sync.adb ! 288991157b ./gcc/ada/par-tchk.adb ! 2421943630b ./gcc/ada/par-util.adb ! 4267838632b ./gcc/ada/par.adb ! 3463587827b ./gcc/ada/par.ads ! 4198954950b ./gcc/ada/prj-attr.adb ! 455900702b ./gcc/ada/prj-attr.ads ! 1801774749b ./gcc/ada/prj-com.adb ! 1046429840b ./gcc/ada/prj-com.ads ! 217311928b ./gcc/ada/prj-dect.adb ! 445199952b ./gcc/ada/prj-dect.ads ! 1382477323b ./gcc/ada/prj-env.adb ! 1372104369b ./gcc/ada/prj-env.ads ! 1906670537b ./gcc/ada/prj-ext.adb ! 2859385035b ./gcc/ada/prj-ext.ads ! 2047634603b ./gcc/ada/prj-makr.adb ! 1883015243b ./gcc/ada/prj-makr.ads ! 2163536706b ./gcc/ada/prj-nmsc.adb ! 2064214000b ./gcc/ada/prj-nmsc.ads ! 1598163413b ./gcc/ada/prj-pars.adb ! 367734767b ./gcc/ada/prj-pars.ads ! 1918222795b ./gcc/ada/prj-part.adb ! 4117638943b ./gcc/ada/prj-part.ads ! 2413852799b ./gcc/ada/prj-pp.adb ! 118812696b ./gcc/ada/prj-pp.ads ! 202512728b ./gcc/ada/prj-proc.adb ! 3183599143b ./gcc/ada/prj-proc.ads ! 2843521976b ./gcc/ada/prj-strt.adb ! 2786884499b ./gcc/ada/prj-strt.ads ! 1081269790b ./gcc/ada/prj-tree.adb ! 11711493b ./gcc/ada/prj-tree.ads ! 1004920764b ./gcc/ada/prj-util.adb ! 2130834746b ./gcc/ada/prj-util.ads ! 1783366994b ./gcc/ada/prj.adb ! 273475311b ./gcc/ada/prj.ads ! 3391358262b ./gcc/ada/raise.c ! 3177561595b ./gcc/ada/raise.h ! 1627893020b ./gcc/ada/repinfo.adb ! 1594795890b ./gcc/ada/repinfo.ads ! 2981853782b ./gcc/ada/repinfo.h ! 2934715699b ./gcc/ada/restrict.adb ! 3998552992b ./gcc/ada/restrict.ads ! 2764605227b ./gcc/ada/rident.ads ! 339035659b ./gcc/ada/rtsfind.adb ! 3155450455b ./gcc/ada/rtsfind.ads ! 2722724428b ./gcc/ada/s-addima.adb ! 3098169944b ./gcc/ada/s-addima.ads ! 4012036131b ./gcc/ada/s-arit64.adb ! 3804503140b ./gcc/ada/s-arit64.ads ! 3808766513b ./gcc/ada/s-assert.adb ! 37695168b ./gcc/ada/s-assert.ads ! 345958931b ./gcc/ada/s-asthan.adb ! 183676191b ./gcc/ada/s-asthan.ads ! 4105809443b ./gcc/ada/s-atacco.adb ! 2144915640b ./gcc/ada/s-atacco.ads ! 893556810b ./gcc/ada/s-auxdec.adb ! 351034639b ./gcc/ada/s-auxdec.ads ! 809451314b ./gcc/ada/s-bitops.adb ! 1402671709b ./gcc/ada/s-bitops.ads ! 1684329982b ./gcc/ada/s-chepoo.ads ! 2895675623b ./gcc/ada/s-crc32.adb ! 132785702b ./gcc/ada/s-crc32.ads ! 1025936575b ./gcc/ada/s-direio.adb ! 2310567932b ./gcc/ada/s-direio.ads ! 3003047560b ./gcc/ada/s-errrep.adb ! 773860744b ./gcc/ada/s-errrep.ads ! 3034094549b ./gcc/ada/s-except.ads ! 2840870838b ./gcc/ada/s-exctab.adb ! 1381021952b ./gcc/ada/s-exctab.ads ! 277321339b ./gcc/ada/s-exnflt.ads ! 3305630942b ./gcc/ada/s-exngen.adb ! 170878969b ./gcc/ada/s-exngen.ads ! 2009440222b ./gcc/ada/s-exnint.ads ! 3585703256b ./gcc/ada/s-exnlfl.ads ! 2025729305b ./gcc/ada/s-exnlin.ads ! 76085712b ./gcc/ada/s-exnllf.ads ! 3587640776b ./gcc/ada/s-exnlli.ads ! 2253337806b ./gcc/ada/s-exnsfl.ads ! 121555862b ./gcc/ada/s-exnsin.ads ! 927678392b ./gcc/ada/s-exnssi.ads ! 2635019319b ./gcc/ada/s-expflt.ads ! 4131466647b ./gcc/ada/s-expgen.adb ! 1934847450b ./gcc/ada/s-expgen.ads ! 3146866455b ./gcc/ada/s-expint.ads ! 856080363b ./gcc/ada/s-explfl.ads ! 1256691204b ./gcc/ada/s-explin.ads ! 1743577065b ./gcc/ada/s-expllf.ads ! 4032558196b ./gcc/ada/s-explli.ads ! 1225992011b ./gcc/ada/s-expllu.adb ! 164475265b ./gcc/ada/s-expllu.ads ! 30334755b ./gcc/ada/s-expmod.adb ! 2989805776b ./gcc/ada/s-expmod.ads ! 453434327b ./gcc/ada/s-expsfl.ads ! 2982056988b ./gcc/ada/s-expsin.ads ! 3696165970b ./gcc/ada/s-expssi.ads ! 1405412241b ./gcc/ada/s-expuns.adb ! 4136946288b ./gcc/ada/s-expuns.ads ! 1285555801b ./gcc/ada/s-fatflt.ads ! 4124895106b ./gcc/ada/s-fatgen.adb ! 1305345872b ./gcc/ada/s-fatgen.ads ! 1597561807b ./gcc/ada/s-fatlfl.ads ! 94457987b ./gcc/ada/s-fatllf.ads ! 762738475b ./gcc/ada/s-fatsfl.ads ! 2088548454b ./gcc/ada/s-ficobl.ads ! 74527873b ./gcc/ada/s-fileio.adb ! 1465520633b ./gcc/ada/s-fileio.ads ! 1377364567b ./gcc/ada/s-finimp.adb ! 1794340590b ./gcc/ada/s-finimp.ads ! 2900827968b ./gcc/ada/s-finroo.adb ! 2894460b ./gcc/ada/s-finroo.ads ! 2452192785b ./gcc/ada/s-fore.adb ! 2647276537b ./gcc/ada/s-fore.ads ! 1958017185b ./gcc/ada/s-gloloc.adb ! 3901978355b ./gcc/ada/s-gloloc.ads ! 3092639076b ./gcc/ada/s-imgbiu.adb ! 839282222b ./gcc/ada/s-imgbiu.ads ! 3215984198b ./gcc/ada/s-imgboo.adb ! 1012955290b ./gcc/ada/s-imgboo.ads ! 770596485b ./gcc/ada/s-imgcha.adb ! 2182675496b ./gcc/ada/s-imgcha.ads ! 271764343b ./gcc/ada/s-imgdec.adb ! 4035532201b ./gcc/ada/s-imgdec.ads ! 1507540352b ./gcc/ada/s-imgenu.adb ! 3796933383b ./gcc/ada/s-imgenu.ads ! 527517008b ./gcc/ada/s-imgint.adb ! 2115107724b ./gcc/ada/s-imgint.ads ! 2065084451b ./gcc/ada/s-imgllb.adb ! 1277602504b ./gcc/ada/s-imgllb.ads ! 3028659959b ./gcc/ada/s-imglld.adb ! 706233748b ./gcc/ada/s-imglld.ads ! 1525142427b ./gcc/ada/s-imglli.adb ! 1465381421b ./gcc/ada/s-imglli.ads ! 4211809579b ./gcc/ada/s-imgllu.adb ! 334271664b ./gcc/ada/s-imgllu.ads ! 374169505b ./gcc/ada/s-imgllw.adb ! 585067938b ./gcc/ada/s-imgllw.ads ! 42487149b ./gcc/ada/s-imgrea.adb ! 1518997582b ./gcc/ada/s-imgrea.ads ! 3263329409b ./gcc/ada/s-imguns.adb ! 627244436b ./gcc/ada/s-imguns.ads ! 3126113706b ./gcc/ada/s-imgwch.adb ! 3303847345b ./gcc/ada/s-imgwch.ads ! 2781247757b ./gcc/ada/s-imgwiu.adb ! 1501445148b ./gcc/ada/s-imgwiu.ads ! 539067745b ./gcc/ada/s-inmaop.ads ! 1744313288b ./gcc/ada/s-interr.adb ! 636552118b ./gcc/ada/s-interr.ads ! 2883071225b ./gcc/ada/s-intman.ads ! 3616964442b ./gcc/ada/s-io.adb ! 1391751882b ./gcc/ada/s-io.ads ! 2255910292b ./gcc/ada/s-maccod.ads ! 3381361830b ./gcc/ada/s-mantis.adb ! 3702023408b ./gcc/ada/s-mantis.ads ! 995102447b ./gcc/ada/s-mastop.adb ! 2897130749b ./gcc/ada/s-mastop.ads ! 243974377b ./gcc/ada/s-memory.adb ! 4199680369b ./gcc/ada/s-memory.ads ! 4294421032b ./gcc/ada/s-osprim.ads ! 1606354282b ./gcc/ada/s-pack03.adb ! 209622955b ./gcc/ada/s-pack03.ads ! 1005272667b ./gcc/ada/s-pack05.adb ! 760603435b ./gcc/ada/s-pack05.ads ! 2343322905b ./gcc/ada/s-pack06.adb ! 1027847988b ./gcc/ada/s-pack06.ads ! 405219508b ./gcc/ada/s-pack07.adb ! 3141158466b ./gcc/ada/s-pack07.ads ! 4081272889b ./gcc/ada/s-pack09.adb ! 4007014623b ./gcc/ada/s-pack09.ads ! 3602928622b ./gcc/ada/s-pack10.adb ! 1833574656b ./gcc/ada/s-pack10.ads ! 860091623b ./gcc/ada/s-pack11.adb ! 3543085520b ./gcc/ada/s-pack11.ads ! 899311322b ./gcc/ada/s-pack12.adb ! 910454706b ./gcc/ada/s-pack12.ads ! 277864968b ./gcc/ada/s-pack13.adb ! 2138309588b ./gcc/ada/s-pack13.ads ! 3406118855b ./gcc/ada/s-pack14.adb ! 2344287793b ./gcc/ada/s-pack14.ads ! 1960565049b ./gcc/ada/s-pack15.adb ! 1357403033b ./gcc/ada/s-pack15.ads ! 1461178326b ./gcc/ada/s-pack17.adb ! 4239614365b ./gcc/ada/s-pack17.ads ! 3981085628b ./gcc/ada/s-pack18.adb ! 3657571721b ./gcc/ada/s-pack18.ads ! 3161698139b ./gcc/ada/s-pack19.adb ! 265351939b ./gcc/ada/s-pack19.ads ! 3919873425b ./gcc/ada/s-pack20.adb ! 1671185151b ./gcc/ada/s-pack20.ads ! 3792887105b ./gcc/ada/s-pack21.adb ! 4178794595b ./gcc/ada/s-pack21.ads ! 184463525b ./gcc/ada/s-pack22.adb ! 949095501b ./gcc/ada/s-pack22.ads ! 3252603822b ./gcc/ada/s-pack23.adb ! 1430809191b ./gcc/ada/s-pack23.ads ! 4100057528b ./gcc/ada/s-pack24.adb ! 3581992859b ./gcc/ada/s-pack24.ads ! 2777346207b ./gcc/ada/s-pack25.adb ! 2060728874b ./gcc/ada/s-pack25.ads ! 389799052b ./gcc/ada/s-pack26.adb ! 2391707945b ./gcc/ada/s-pack26.ads ! 2252793456b ./gcc/ada/s-pack27.adb ! 3599697966b ./gcc/ada/s-pack27.ads ! 3526254019b ./gcc/ada/s-pack28.adb ! 3570695798b ./gcc/ada/s-pack28.ads ! 1830979325b ./gcc/ada/s-pack29.adb ! 636263088b ./gcc/ada/s-pack29.ads ! 1247267451b ./gcc/ada/s-pack30.adb ! 1714316202b ./gcc/ada/s-pack30.ads ! 2904701475b ./gcc/ada/s-pack31.adb ! 3774382322b ./gcc/ada/s-pack31.ads ! 2397973708b ./gcc/ada/s-pack33.adb ! 1285796598b ./gcc/ada/s-pack33.ads ! 1469228626b ./gcc/ada/s-pack34.adb ! 3493002958b ./gcc/ada/s-pack34.ads ! 3938064381b ./gcc/ada/s-pack35.adb ! 1665131195b ./gcc/ada/s-pack35.ads ! 3033043814b ./gcc/ada/s-pack36.adb ! 2336010364b ./gcc/ada/s-pack36.ads ! 3379953938b ./gcc/ada/s-pack37.adb ! 3479490751b ./gcc/ada/s-pack37.ads ! 1910313513b ./gcc/ada/s-pack38.adb ! 3513147171b ./gcc/ada/s-pack38.ads ! 571629983b ./gcc/ada/s-pack39.adb ! 1007108641b ./gcc/ada/s-pack39.ads ! 2540513647b ./gcc/ada/s-pack40.adb ! 2117108993b ./gcc/ada/s-pack40.ads ! 2613151820b ./gcc/ada/s-pack41.adb ! 2909506309b ./gcc/ada/s-pack41.ads ! 1949768795b ./gcc/ada/s-pack42.adb ! 624872371b ./gcc/ada/s-pack42.ads ! 3087900323b ./gcc/ada/s-pack43.adb ! 19970305b ./gcc/ada/s-pack43.ads ! 2326283590b ./gcc/ada/s-pack44.adb ! 3358333029b ./gcc/ada/s-pack44.ads ! 3696862610b ./gcc/ada/s-pack45.adb ! 783083852b ./gcc/ada/s-pack45.ads ! 1777496178b ./gcc/ada/s-pack46.adb ! 2468501207b ./gcc/ada/s-pack46.ads ! 4288000893b ./gcc/ada/s-pack47.adb ! 2197281608b ./gcc/ada/s-pack47.ads ! 2900881725b ./gcc/ada/s-pack48.adb ! 3380132232b ./gcc/ada/s-pack48.ads ! 351392752b ./gcc/ada/s-pack49.adb ! 1905543638b ./gcc/ada/s-pack49.ads ! 882796165b ./gcc/ada/s-pack50.adb ! 2072159316b ./gcc/ada/s-pack50.ads ! 3572592430b ./gcc/ada/s-pack51.adb ! 3028308884b ./gcc/ada/s-pack51.ads ! 3619967921b ./gcc/ada/s-pack52.adb ! 546106086b ./gcc/ada/s-pack52.ads ! 4148001217b ./gcc/ada/s-pack53.adb ! 417030544b ./gcc/ada/s-pack53.ads ! 693832364b ./gcc/ada/s-pack54.adb ! 3449698608b ./gcc/ada/s-pack54.ads ! 2473149168b ./gcc/ada/s-pack55.adb ! 927412701b ./gcc/ada/s-pack55.ads ! 3389079448b ./gcc/ada/s-pack56.adb ! 2526050178b ./gcc/ada/s-pack56.ads ! 2963624991b ./gcc/ada/s-pack57.adb ! 2602304473b ./gcc/ada/s-pack57.ads ! 253017815b ./gcc/ada/s-pack58.adb ! 3435829469b ./gcc/ada/s-pack58.ads ! 1539388562b ./gcc/ada/s-pack59.adb ! 1753190727b ./gcc/ada/s-pack59.ads ! 200978682b ./gcc/ada/s-pack60.adb ! 1968490411b ./gcc/ada/s-pack60.ads ! 94389896b ./gcc/ada/s-pack61.adb ! 2663135783b ./gcc/ada/s-pack61.ads ! 3902834126b ./gcc/ada/s-pack62.adb ! 777685273b ./gcc/ada/s-pack62.ads ! 644632679b ./gcc/ada/s-pack63.adb ! 854001699b ./gcc/ada/s-pack63.ads ! 3824482028b ./gcc/ada/s-parame.adb ! 100337926b ./gcc/ada/s-parame.ads ! 489302103b ./gcc/ada/s-parint.adb ! 1680959992b ./gcc/ada/s-parint.ads ! 1359239001b ./gcc/ada/s-pooglo.adb ! 3563085528b ./gcc/ada/s-pooglo.ads ! 3795210994b ./gcc/ada/s-pooloc.adb ! 3045504111b ./gcc/ada/s-pooloc.ads ! 2673838793b ./gcc/ada/s-poosiz.adb ! 438866099b ./gcc/ada/s-poosiz.ads ! 3029625785b ./gcc/ada/s-powtab.ads ! 830131794b ./gcc/ada/s-proinf.adb ! 271040113b ./gcc/ada/s-proinf.ads ! 2019333834b ./gcc/ada/s-rpc.adb ! 2908648187b ./gcc/ada/s-rpc.ads ! 446869618b ./gcc/ada/s-scaval.ads ! 30021732b ./gcc/ada/s-secsta.adb ! 1897968564b ./gcc/ada/s-secsta.ads ! 833329011b ./gcc/ada/s-sequio.adb ! 2909740124b ./gcc/ada/s-sequio.ads ! 4059417223b ./gcc/ada/s-shasto.adb ! 571382670b ./gcc/ada/s-shasto.ads ! 606537845b ./gcc/ada/s-soflin.adb ! 128602045b ./gcc/ada/s-soflin.ads ! 2957311133b ./gcc/ada/s-sopco3.adb ! 4163085753b ./gcc/ada/s-sopco3.ads ! 3463409789b ./gcc/ada/s-sopco4.adb ! 2234349572b ./gcc/ada/s-sopco4.ads ! 3479052300b ./gcc/ada/s-sopco5.adb ! 3566552120b ./gcc/ada/s-sopco5.ads ! 1229103716b ./gcc/ada/s-stache.adb ! 600743323b ./gcc/ada/s-stache.ads ! 2172697981b ./gcc/ada/s-stalib.adb ! 3474397127b ./gcc/ada/s-stalib.ads ! 4262180487b ./gcc/ada/s-stoele.adb ! 2971232174b ./gcc/ada/s-stoele.ads ! 4047429847b ./gcc/ada/s-stopoo.ads ! 3324639495b ./gcc/ada/s-stratt.adb ! 3974377445b ./gcc/ada/s-stratt.ads ! 370100204b ./gcc/ada/s-strops.adb ! 971678965b ./gcc/ada/s-strops.ads ! 3175332127b ./gcc/ada/s-taasde.adb ! 2376128105b ./gcc/ada/s-taasde.ads ! 296590963b ./gcc/ada/s-tadeca.adb ! 3931772177b ./gcc/ada/s-tadeca.ads ! 818008913b ./gcc/ada/s-tadert.adb ! 4037517831b ./gcc/ada/s-tadert.ads ! 3686545646b ./gcc/ada/s-taenca.adb ! 3926496203b ./gcc/ada/s-taenca.ads ! 2333648438b ./gcc/ada/s-taprob.adb ! 3419796729b ./gcc/ada/s-taprob.ads ! 571402338b ./gcc/ada/s-taprop.ads ! 1482926311b ./gcc/ada/s-tarest.adb ! 3894716834b ./gcc/ada/s-tarest.ads ! 4228845147b ./gcc/ada/s-tasdeb.adb ! 3250527878b ./gcc/ada/s-tasdeb.ads ! 261034302b ./gcc/ada/s-tasinf.adb ! 2352748810b ./gcc/ada/s-tasinf.ads ! 1578965009b ./gcc/ada/s-tasini.adb ! 2571536798b ./gcc/ada/s-tasini.ads ! 512143507b ./gcc/ada/s-taskin.adb ! 1376141781b ./gcc/ada/s-taskin.ads ! 1136094041b ./gcc/ada/s-tasque.adb ! 3759133430b ./gcc/ada/s-tasque.ads ! 2601412157b ./gcc/ada/s-tasren.adb ! 2827947168b ./gcc/ada/s-tasren.ads ! 3360475183b ./gcc/ada/s-tasres.ads ! 112793573b ./gcc/ada/s-tassta.adb ! 4013453345b ./gcc/ada/s-tassta.ads ! 3341695004b ./gcc/ada/s-tasuti.adb ! 2920439586b ./gcc/ada/s-tasuti.ads ! 2841804633b ./gcc/ada/s-tataat.adb ! 3281524283b ./gcc/ada/s-tataat.ads ! 4284210032b ./gcc/ada/s-tpinop.adb ! 1010260087b ./gcc/ada/s-tpinop.ads ! 1437959453b ./gcc/ada/s-tpoben.adb ! 78459834b ./gcc/ada/s-tpoben.ads ! 4108440041b ./gcc/ada/s-tpobop.adb ! 2707769297b ./gcc/ada/s-tpobop.ads ! 2861663022b ./gcc/ada/s-tposen.adb ! 3033925472b ./gcc/ada/s-tposen.ads ! 1383192057b ./gcc/ada/s-traceb.adb ! 2741886828b ./gcc/ada/s-traceb.ads ! 3234353667b ./gcc/ada/s-traces.adb ! 783758788b ./gcc/ada/s-traces.ads ! 922433200b ./gcc/ada/s-tratas.adb ! 1365141773b ./gcc/ada/s-tratas.ads ! 297299147b ./gcc/ada/s-unstyp.ads ! 3663234314b ./gcc/ada/s-vaflop.adb ! 1802491369b ./gcc/ada/s-vaflop.ads ! 3661545185b ./gcc/ada/s-valboo.adb ! 3721856174b ./gcc/ada/s-valboo.ads ! 755162775b ./gcc/ada/s-valcha.adb ! 1114541695b ./gcc/ada/s-valcha.ads ! 3585578263b ./gcc/ada/s-valdec.adb ! 851743862b ./gcc/ada/s-valdec.ads ! 2996009070b ./gcc/ada/s-valenu.adb ! 2467192511b ./gcc/ada/s-valenu.ads ! 2679797603b ./gcc/ada/s-valint.adb ! 627239498b ./gcc/ada/s-valint.ads ! 236165297b ./gcc/ada/s-vallld.adb ! 389421167b ./gcc/ada/s-vallld.ads ! 633857741b ./gcc/ada/s-vallli.adb ! 2812263233b ./gcc/ada/s-vallli.ads ! 1585236839b ./gcc/ada/s-valllu.adb ! 3383667889b ./gcc/ada/s-valllu.ads ! 1699855b ./gcc/ada/s-valrea.adb ! 2113650187b ./gcc/ada/s-valrea.ads ! 1259299469b ./gcc/ada/s-valuns.adb ! 3396059374b ./gcc/ada/s-valuns.ads ! 1775985419b ./gcc/ada/s-valuti.adb ! 45852770b ./gcc/ada/s-valuti.ads ! 3725838485b ./gcc/ada/s-valwch.adb ! 2626906273b ./gcc/ada/s-valwch.ads ! 751102067b ./gcc/ada/s-vercon.adb ! 1087339633b ./gcc/ada/s-vercon.ads ! 1035815090b ./gcc/ada/s-vmexta.adb ! 1273025419b ./gcc/ada/s-vmexta.ads ! 354330343b ./gcc/ada/s-wchcnv.adb ! 2396752870b ./gcc/ada/s-wchcnv.ads ! 597674757b ./gcc/ada/s-wchcon.ads ! 2580581322b ./gcc/ada/s-wchjis.adb ! 673518722b ./gcc/ada/s-wchjis.ads ! 3191144132b ./gcc/ada/s-wchstw.adb ! 2365550925b ./gcc/ada/s-wchstw.ads ! 2490415534b ./gcc/ada/s-wchwts.adb ! 1818373135b ./gcc/ada/s-wchwts.ads ! 2261037173b ./gcc/ada/s-widboo.adb ! 2020492367b ./gcc/ada/s-widboo.ads ! 450893490b ./gcc/ada/s-widcha.adb ! 1582980633b ./gcc/ada/s-widcha.ads ! 1589563136b ./gcc/ada/s-widenu.adb ! 443673851b ./gcc/ada/s-widenu.ads ! 2448211898b ./gcc/ada/s-widlli.adb ! 2514294788b ./gcc/ada/s-widlli.ads ! 2817457313b ./gcc/ada/s-widllu.adb ! 2104007358b ./gcc/ada/s-widllu.ads ! 777204248b ./gcc/ada/s-widwch.adb ! 2602874053b ./gcc/ada/s-widwch.ads ! 3179820469b ./gcc/ada/s-wwdcha.adb ! 566151854b ./gcc/ada/s-wwdcha.ads ! 2981811991b ./gcc/ada/s-wwdenu.adb ! 876921949b ./gcc/ada/s-wwdenu.ads ! 742539160b ./gcc/ada/s-wwdwch.adb ! 1368753201b ./gcc/ada/s-wwdwch.ads ! 128154809b ./gcc/ada/scans.adb ! 345695149b ./gcc/ada/scans.ads ! 96767155b ./gcc/ada/scn-nlit.adb ! 4141266749b ./gcc/ada/scn-slit.adb ! 2641128141b ./gcc/ada/scn.adb ! 3913556059b ./gcc/ada/scn.ads ! 3456501945b ./gcc/ada/sdefault.ads ! 457587035b ./gcc/ada/sem.adb ! 3718551417b ./gcc/ada/sem.ads ! 1853623673b ./gcc/ada/sem_aggr.adb ! 4131551728b ./gcc/ada/sem_aggr.ads ! 153562469b ./gcc/ada/sem_attr.adb ! 453667776b ./gcc/ada/sem_attr.ads ! 564785830b ./gcc/ada/sem_case.adb ! 495176024b ./gcc/ada/sem_case.ads ! 2598563707b ./gcc/ada/sem_cat.adb ! 1516953566b ./gcc/ada/sem_cat.ads ! 237781320b ./gcc/ada/sem_ch10.adb ! 95842022b ./gcc/ada/sem_ch10.ads ! 1597810602b ./gcc/ada/sem_ch11.adb ! 301514658b ./gcc/ada/sem_ch11.ads ! 905665264b ./gcc/ada/sem_ch12.adb ! 1406477684b ./gcc/ada/sem_ch12.ads ! 2427266513b ./gcc/ada/sem_ch13.adb ! 3162337120b ./gcc/ada/sem_ch13.ads ! 675010544b ./gcc/ada/sem_ch2.adb ! 1337056150b ./gcc/ada/sem_ch2.ads ! 2468230337b ./gcc/ada/sem_ch3.adb ! 2282414621b ./gcc/ada/sem_ch3.ads ! 3533963930b ./gcc/ada/sem_ch4.adb ! 1626692841b ./gcc/ada/sem_ch4.ads ! 574340438b ./gcc/ada/sem_ch5.adb ! 3874469898b ./gcc/ada/sem_ch5.ads ! 1081660985b ./gcc/ada/sem_ch6.adb ! 1784406070b ./gcc/ada/sem_ch6.ads ! 3448287303b ./gcc/ada/sem_ch7.adb ! 3876690738b ./gcc/ada/sem_ch7.ads ! 532800431b ./gcc/ada/sem_ch8.adb ! 1332122704b ./gcc/ada/sem_ch8.ads ! 1333912384b ./gcc/ada/sem_ch9.adb ! 1981701559b ./gcc/ada/sem_ch9.ads ! 2874178694b ./gcc/ada/sem_disp.adb ! 64069076b ./gcc/ada/sem_disp.ads ! 3106266291b ./gcc/ada/sem_dist.adb ! 448784348b ./gcc/ada/sem_dist.ads ! 820420908b ./gcc/ada/sem_elab.adb ! 1737329980b ./gcc/ada/sem_elab.ads ! 1101292401b ./gcc/ada/sem_elim.adb ! 1586521596b ./gcc/ada/sem_elim.ads ! 1855970064b ./gcc/ada/sem_eval.adb ! 1644532762b ./gcc/ada/sem_eval.ads ! 2923550281b ./gcc/ada/sem_intr.adb ! 1636056678b ./gcc/ada/sem_intr.ads ! 3707937295b ./gcc/ada/sem_maps.adb ! 1420921962b ./gcc/ada/sem_maps.ads ! 823176495b ./gcc/ada/sem_mech.adb ! 3673774677b ./gcc/ada/sem_mech.ads ! 21685246b ./gcc/ada/sem_prag.adb ! 1882250315b ./gcc/ada/sem_prag.ads ! 573356616b ./gcc/ada/sem_res.adb ! 3045351009b ./gcc/ada/sem_res.ads ! 1138920335b ./gcc/ada/sem_smem.adb ! 2750071125b ./gcc/ada/sem_smem.ads ! 1762658297b ./gcc/ada/sem_type.adb ! 103784610b ./gcc/ada/sem_type.ads ! 1845973319b ./gcc/ada/sem_util.adb ! 2371663768b ./gcc/ada/sem_util.ads ! 784565722b ./gcc/ada/sem_vfpt.adb ! 3753664166b ./gcc/ada/sem_vfpt.ads ! 989663054b ./gcc/ada/sem_warn.adb ! 2835167594b ./gcc/ada/sem_warn.ads ! 2659804483b ./gcc/ada/sequenio.ads ! 3879844819b ./gcc/ada/sfn_scan.adb ! 3386500562b ./gcc/ada/sfn_scan.ads ! 3157179136b ./gcc/ada/sinfo-cn.adb ! 1838430262b ./gcc/ada/sinfo-cn.ads ! 1510702737b ./gcc/ada/sinfo.adb ! 776264779b ./gcc/ada/sinfo.ads ! 3191222610b ./gcc/ada/sinfo.h ! 1139072857b ./gcc/ada/sinput-d.adb ! 1552980541b ./gcc/ada/sinput-d.ads ! 1072947695b ./gcc/ada/sinput-l.adb ! 1344432336b ./gcc/ada/sinput-l.ads ! 3419288990b ./gcc/ada/sinput-p.adb ! 4012597971b ./gcc/ada/sinput-p.ads ! 1602228275b ./gcc/ada/sinput.adb ! 3934432023b ./gcc/ada/sinput.ads ! 1625013762b ./gcc/ada/snames.adb ! 1436168100b ./gcc/ada/snames.ads ! 3744225773b ./gcc/ada/snames.h ! 4234849843b ./gcc/ada/sprint.adb ! 2040623862b ./gcc/ada/sprint.ads ! 1915984406b ./gcc/ada/stand.adb ! 3516623899b ./gcc/ada/stand.ads ! 3202054863b ./gcc/ada/stringt.adb ! 3453373995b ./gcc/ada/stringt.ads ! 1716263916b ./gcc/ada/stringt.h ! 1443073414b ./gcc/ada/style.adb ! 3757146219b ./gcc/ada/style.ads ! 4004656796b ./gcc/ada/stylesw.adb ! 2425837244b ./gcc/ada/stylesw.ads ! 2685331831b ./gcc/ada/switch-b.adb ! 3801384459b ./gcc/ada/switch-b.ads ! 3455476498b ./gcc/ada/switch-c.adb ! 3473960847b ./gcc/ada/switch-c.ads ! 1451377305b ./gcc/ada/switch-m.adb ! 1510716097b ./gcc/ada/switch-m.ads ! 507332671b ./gcc/ada/switch.adb ! 3452617480b ./gcc/ada/switch.ads ! 1097000358b ./gcc/ada/sysdep.c ! 863555368b ./gcc/ada/system.ads ! 1599555682b ./gcc/ada/table.adb ! 1565425186b ./gcc/ada/table.ads ! 413715310b ./gcc/ada/targparm.adb ! 3629509569b ./gcc/ada/targparm.ads ! 2656928717b ./gcc/ada/targtyps.c ! 1635537564b ./gcc/ada/tbuild.adb ! 1007224603b ./gcc/ada/tbuild.ads ! 2469703775b ./gcc/ada/text_io.ads ! 3022378179b ./gcc/ada/tracebak.c ! 3621738649b ./gcc/ada/trans.c ! 1930086756b ./gcc/ada/tree_gen.adb ! 2954553707b ./gcc/ada/tree_gen.ads ! 2410960934b ./gcc/ada/tree_in.adb ! 2092964734b ./gcc/ada/tree_in.ads ! 2795403287b ./gcc/ada/tree_io.adb ! 1074378588b ./gcc/ada/tree_io.ads ! 2422943668b ./gcc/ada/treepr.adb ! 667089060b ./gcc/ada/treepr.ads ! 1669384487b ./gcc/ada/treeprs.ads ! 3795314685b ./gcc/ada/treeprs.adt ! 3206526706b ./gcc/ada/ttypef.ads ! 2602607923b ./gcc/ada/ttypes.ads ! 2872000972b ./gcc/ada/types.adb ! 3049108073b ./gcc/ada/types.ads ! 2029472243b ./gcc/ada/types.h 981400444b ./gcc/ada/ug_words ! 2163270927b ./gcc/ada/uintp.adb ! 3083805627b ./gcc/ada/uintp.ads ! 4017347024b ./gcc/ada/uintp.h ! 3335630020b ./gcc/ada/uname.adb ! 3381102603b ./gcc/ada/uname.ads ! 1037780895b ./gcc/ada/unchconv.ads ! 2684345166b ./gcc/ada/unchdeal.ads ! 3748300839b ./gcc/ada/urealp.adb ! 2461048567b ./gcc/ada/urealp.ads ! 2654407585b ./gcc/ada/urealp.h ! 2228862505b ./gcc/ada/usage.adb ! 319517319b ./gcc/ada/usage.ads ! 3812277810b ./gcc/ada/utils.c ! 1439939771b ./gcc/ada/utils2.c ! 48927045b ./gcc/ada/validsw.adb ! 3951594422b ./gcc/ada/validsw.ads ! 1550194581b ./gcc/ada/widechar.adb ! 3442909407b ./gcc/ada/widechar.ads ! 3406844766b ./gcc/ada/xeinfo.adb 208322693b ./gcc/ada/xgnatug.adb ! 268664355b ./gcc/ada/xnmake.adb ! 2160162827b ./gcc/ada/xr_tabls.adb ! 1571871756b ./gcc/ada/xr_tabls.ads ! 1730081979b ./gcc/ada/xref_lib.adb ! 1668630154b ./gcc/ada/xref_lib.ads ! 3573112600b ./gcc/ada/xsinfo.adb ! 4190686960b ./gcc/ada/xsnames.adb ! 511048883b ./gcc/ada/xtreeprs.adb ! 2840631424b ./gcc/alias.c ! 3329204760b ./gcc/attribs.c ! 661204297b ./gcc/basic-block.h ! 3868878276b ./gcc/bb-reorder.c ! 3592689596b ./gcc/bitmap.c ! 3888731700b ./gcc/bitmap.h ! 866389233b ./gcc/builtin-attrs.def ! 2231934789b ./gcc/builtin-types.def ! 3267464475b ./gcc/builtins.c ! 3399851061b ./gcc/builtins.def ! 266754123b ./gcc/c-aux-info.c ! 1775829814b ./gcc/c-common.c ! 1911269762b ./gcc/c-common.def ! 3230227898b ./gcc/c-common.h 2498727911b ./gcc/c-config-lang.in ! 4223371978b ./gcc/c-convert.c ! 579906276b ./gcc/c-decl.c ! 420078897b ./gcc/c-dump.c ! 3988343334b ./gcc/c-errors.c ! 1308520655b ./gcc/c-format.c ! 2967450474b ./gcc/c-lang.c ! 940015516b ./gcc/c-lex.c ! 3974543740b ./gcc/c-objc-common.c ! 327769972b ./gcc/c-opts.c ! 215284404b ./gcc/c-parse.c ! 2637246862b ./gcc/c-parse.in ! 1656602684b ./gcc/c-parse.y ! 3843981782b ./gcc/c-pragma.c ! 2824587351b ./gcc/c-pragma.h ! 1364992996b ./gcc/c-pretty-print.c ! 322270390b ./gcc/c-pretty-print.h ! 2307648174b ./gcc/c-semantics.c ! 3323894092b ./gcc/c-tree.h ! 3800723537b ./gcc/c-typeck.c ! 1929894132b ./gcc/caller-save.c ! 1946827628b ./gcc/calls.c ! 2570201327b ./gcc/cfg.c ! 1424850360b ./gcc/cfganal.c ! 2497073643b ./gcc/cfgbuild.c ! 1214884536b ./gcc/cfgcleanup.c ! 2495299687b ./gcc/cfglayout.c ! 397535119b ./gcc/cfglayout.h ! 3649311558b ./gcc/cfgloop.c ! 1528447670b ./gcc/cfgrtl.c ! 879130284b ./gcc/collect2.c ! 1843868705b ./gcc/collect2.h ! 3800413649b ./gcc/combine.c 4122382037b ./gcc/conditions.h ! 3072373159b ./gcc/config.gcc ! 1315260558b ./gcc/config.guess ! 1565770251b ./gcc/config.in ! 3917072699b ./gcc/config/README ! 1081521208b ./gcc/config/alpha/alpha-interix.h ! 1148890194b ./gcc/config/alpha/alpha-protos.h ! 3977497323b ./gcc/config/alpha/alpha.c ! 1346602339b ./gcc/config/alpha/alpha.h ! 3145148145b ./gcc/config/alpha/alpha.md ! 3915788506b ./gcc/config/alpha/alpha32.h 1407988137b ./gcc/config/alpha/crtfastmath.c ! 1689355033b ./gcc/config/alpha/elf.h ! 4100757221b ./gcc/config/alpha/ev4.md ! 592376398b ./gcc/config/alpha/ev5.md ! 320649145b ./gcc/config/alpha/ev6.md ! 3434499482b ./gcc/config/alpha/freebsd.h ! 2439445430b ./gcc/config/alpha/gnu.h ! 2998860143b ./gcc/config/alpha/lib1funcs.asm ! 116786968b ./gcc/config/alpha/linux-elf.h ! 2178551847b ./gcc/config/alpha/linux.h ! 1246797152b ./gcc/config/alpha/netbsd.h ! 3083238444b ./gcc/config/alpha/openbsd.h ! 2934606255b ./gcc/config/alpha/osf.h ! 1148914945b ./gcc/config/alpha/osf5.h 1190572001b ./gcc/config/alpha/qrnnd.asm 2672344824b ./gcc/config/alpha/t-alpha 2436402688b ./gcc/config/alpha/t-crtfm 3084092578b ./gcc/config/alpha/t-ieee ! 3884780449b ./gcc/config/alpha/t-interix ! 1579687087b ./gcc/config/alpha/t-osf4 1191509594b ./gcc/config/alpha/t-unicosmk 1694999122b ./gcc/config/alpha/t-vms 3342100479b ./gcc/config/alpha/t-vms64 ! 1874402377b ./gcc/config/alpha/unicosmk.h 2817356982b ./gcc/config/alpha/va_list.h ! 2980547348b ./gcc/config/alpha/vms-cc.c ! 3010004084b ./gcc/config/alpha/vms-crt0-64.c ! 4198282733b ./gcc/config/alpha/vms-crt0.c ! 3572749067b ./gcc/config/alpha/vms-dwarf2.asm ! 3031921581b ./gcc/config/alpha/vms-dwarf2eh.asm ! 278320441b ./gcc/config/alpha/vms-ld.c ! 3270218594b ./gcc/config/alpha/vms-psxcrt0-64.c ! 2164189970b ./gcc/config/alpha/vms-psxcrt0.c ! 2505978720b ./gcc/config/alpha/vms.h ! 2920918174b ./gcc/config/alpha/vms64.h ! 1497613985b ./gcc/config/alpha/vms_tramp.asm ! 945163077b ./gcc/config/alpha/vxworks.h 1756604664b ./gcc/config/alpha/x-vms ! 1631226706b ./gcc/config/alpha/xm-alpha-interix.h ! 1813891070b ./gcc/config/alpha/xm-vms.h ! 2164887597b ./gcc/config/alpha/xm-vms64.h ! 662120966b ./gcc/config/aoutos.h ! 3176057659b ./gcc/config/arc/arc-modes.def ! 1430913830b ./gcc/config/arc/arc-protos.h ! 984169977b ./gcc/config/arc/arc.c ! 1864215868b ./gcc/config/arc/arc.h ! 2879061285b ./gcc/config/arc/arc.md ! 2242623574b ./gcc/config/arc/initfini.c ! 4224412506b ./gcc/config/arc/lib1funcs.asm 1378203063b ./gcc/config/arc/t-arc ! 751909821b ./gcc/config/arm/README-interworking ! 2219060296b ./gcc/config/arm/aof.h ! 2675616798b ./gcc/config/arm/aout.h ! 1511706560b ./gcc/config/arm/arm-modes.def ! 2313150707b ./gcc/config/arm/arm-protos.h ! 2570786956b ./gcc/config/arm/arm.c ! 2554986637b ./gcc/config/arm/arm.h ! 1970299264b ./gcc/config/arm/arm.md ! 152133707b ./gcc/config/arm/coff.h ! 3566890009b ./gcc/config/arm/conix-elf.h 1666366669b ./gcc/config/arm/crti.asm ! 3836293988b ./gcc/config/arm/crtn.asm ! 4281626291b ./gcc/config/arm/ecos-elf.h ! 259208134b ./gcc/config/arm/elf.h ! 4010625370b ./gcc/config/arm/freebsd.h ! 3355567723b ./gcc/config/arm/lib1funcs.asm ! 2684835712b ./gcc/config/arm/linux-elf.h ! 2410223095b ./gcc/config/arm/linux-gas.h ! 816029099b ./gcc/config/arm/netbsd-elf.h ! 3559608348b ./gcc/config/arm/netbsd.h ! 152326865b ./gcc/config/arm/pe.c ! 2382903214b ./gcc/config/arm/pe.h ! 1835834968b ./gcc/config/arm/rtems-elf.h ! 4226743428b ./gcc/config/arm/semi.h ! 3907181312b ./gcc/config/arm/semiaof.h ! 1676744073b ./gcc/config/arm/strongarm-coff.h ! 2572947596b ./gcc/config/arm/strongarm-elf.h ! 4084147202b ./gcc/config/arm/strongarm-pe.h ! 1225127474b ./gcc/config/arm/t-arm-aout ! 1432575844b ./gcc/config/arm/t-arm-coff ! 558258459b ./gcc/config/arm/t-arm-elf ! 2454749767b ./gcc/config/arm/t-linux ! 1462551033b ./gcc/config/arm/t-netbsd ! 2218565760b ./gcc/config/arm/t-pe ! 1572194130b ./gcc/config/arm/t-semi ! 3145229981b ./gcc/config/arm/t-strongarm-coff 358695252b ./gcc/config/arm/t-strongarm-elf ! 2389193190b ./gcc/config/arm/t-strongarm-pe 3941249553b ./gcc/config/arm/t-xscale-coff ! 4238855457b ./gcc/config/arm/t-xscale-elf ! 3331622085b ./gcc/config/arm/uclinux-elf.h ! 4033330429b ./gcc/config/arm/unknown-elf-oabi.h ! 1071156127b ./gcc/config/arm/unknown-elf.h ! 1588213826b ./gcc/config/arm/vxarm.h 2210599114b ./gcc/config/arm/xscale-coff.h ! 1990441242b ./gcc/config/arm/xscale-elf.h ! 1358701110b ./gcc/config/avr/avr-protos.h ! 1025531934b ./gcc/config/avr/avr.c ! 4086669495b ./gcc/config/avr/avr.h ! 3351685131b ./gcc/config/avr/avr.md 4272425436b ./gcc/config/avr/libgcc.S 2062536157b ./gcc/config/avr/t-avr ! 2135324155b ./gcc/config/c4x/c4x-c.c ! 3103028321b ./gcc/config/c4x/c4x-modes.def ! 3891197136b ./gcc/config/c4x/c4x-protos.h ! 2961519321b ./gcc/config/c4x/c4x.c ! 2694923076b ./gcc/config/c4x/c4x.h ! 455436257b ./gcc/config/c4x/c4x.md ! 611817595b ./gcc/config/c4x/libgcc.S ! 2241768860b ./gcc/config/c4x/rtems.h ! 2323387481b ./gcc/config/c4x/t-c4x ! 1330177116b ./gcc/config/chorus.h ! 3983475564b ./gcc/config/cris/aout.h 3670658933b ./gcc/config/cris/arit.c ! 881494957b ./gcc/config/cris/cris-protos.h ! 2733582021b ./gcc/config/cris/cris.c ! 718151887b ./gcc/config/cris/cris.h ! 3653765946b ./gcc/config/cris/cris.md ! 4228128527b ./gcc/config/cris/cris_abi_symbol.c ! 744364725b ./gcc/config/cris/linux.h ! 907689569b ./gcc/config/cris/mulsi3.asm 45521295b ./gcc/config/cris/t-aout ! 3846478151b ./gcc/config/cris/t-cris 2080407099b ./gcc/config/cris/t-elfmulti 1112852607b ./gcc/config/cris/t-linux 3834330727b ./gcc/config/d30v/abi ! 3447920759b ./gcc/config/d30v/d30v-protos.h ! 2625081148b ./gcc/config/d30v/d30v.c ! 1965727304b ./gcc/config/d30v/d30v.h ! 3430463305b ./gcc/config/d30v/d30v.md 1512688016b ./gcc/config/d30v/libgcc1.asm 2120255627b ./gcc/config/d30v/t-d30v ! 4059801364b ./gcc/config/darwin-c.c 3226016932b ./gcc/config/darwin-crt2.c ! 1838012452b ./gcc/config/darwin-protos.h ! 3101942541b ./gcc/config/darwin.c ! 3020045688b ./gcc/config/darwin.h ! 2662634125b ./gcc/config/dbx.h ! 2063159136b ./gcc/config/dbxcoff.h ! 741369544b ./gcc/config/dbxelf.h 4083711028b ./gcc/config/divmod.c ! 3807169411b ./gcc/config/dsp16xx/dsp16xx-protos.h ! 2358823832b ./gcc/config/dsp16xx/dsp16xx.c ! 749466720b ./gcc/config/dsp16xx/dsp16xx.h ! 3159876720b ./gcc/config/dsp16xx/dsp16xx.md ! 3752303804b ./gcc/config/elfos.h ! 4261313761b ./gcc/config/fp-bit.c ! 174418986b ./gcc/config/fp-bit.h 2304723625b ./gcc/config/fr30/crti.asm 2025473533b ./gcc/config/fr30/crtn.asm ! 2264307288b ./gcc/config/fr30/fr30-protos.h ! 1284148066b ./gcc/config/fr30/fr30.c ! 1920296356b ./gcc/config/fr30/fr30.h ! 1664440102b ./gcc/config/fr30/fr30.md ! 2734319269b ./gcc/config/fr30/lib1funcs.asm 3068633205b ./gcc/config/fr30/t-fr30 ! 3532526787b ./gcc/config/freebsd-nthr.h ! 3606513384b ./gcc/config/freebsd-spec.h ! 3873089153b ./gcc/config/freebsd.h ! 3857422654b ./gcc/config/freebsd3.h ! 2210711654b ./gcc/config/freebsd4.h ! 1531797731b ./gcc/config/freebsd5.h ! 3920011053b ./gcc/config/freebsd6.h ! 927977764b ./gcc/config/frv/cmovd.c ! 1433509166b ./gcc/config/frv/cmovh.c ! 2671877583b ./gcc/config/frv/cmovw.c ! 1018636984b ./gcc/config/frv/frv-abi.h ! 2218059281b ./gcc/config/frv/frv-asm.h ! 3648172764b ./gcc/config/frv/frv-modes.def ! 923550243b ./gcc/config/frv/frv-protos.h ! 4224181574b ./gcc/config/frv/frv.c ! 1111096050b ./gcc/config/frv/frv.h ! 3428515036b ./gcc/config/frv/frv.md ! 1047071374b ./gcc/config/frv/frvbegin.c ! 1886816641b ./gcc/config/frv/frvend.c ! 3504198099b ./gcc/config/frv/lib1funcs.asm 3184593289b ./gcc/config/frv/modi.c ! 3995816317b ./gcc/config/frv/t-frv 3539083584b ./gcc/config/frv/uitod.c 1261623248b ./gcc/config/frv/uitof.c 3087488293b ./gcc/config/frv/ulltod.c 788903798b ./gcc/config/frv/ulltof.c 946276139b ./gcc/config/frv/umodi.c ! 2184744613b ./gcc/config/gnu.h ! 2188992916b ./gcc/config/gofast.h ! 2135233002b ./gcc/config/h8300/crti.asm ! 3919963794b ./gcc/config/h8300/crtn.asm ! 367022637b ./gcc/config/h8300/elf.h ! 4087866448b ./gcc/config/h8300/fixunssfsi.c ! 2922330864b ./gcc/config/h8300/h8300-protos.h ! 2060412524b ./gcc/config/h8300/h8300.c ! 3743077297b ./gcc/config/h8300/h8300.h ! 4265687184b ./gcc/config/h8300/h8300.md ! 1262063656b ./gcc/config/h8300/lib1funcs.asm ! 186420544b ./gcc/config/h8300/rtems.h 2094865057b ./gcc/config/h8300/t-elf ! 3777445358b ./gcc/config/h8300/t-h8300 1257665765b ./gcc/config/h8300/t-rtems 2187046003b ./gcc/config/i370/README ! 4183152766b ./gcc/config/i370/i370-c.c ! 2357921251b ./gcc/config/i370/i370-protos.h ! 273465087b ./gcc/config/i370/i370.c ! 2997303532b ./gcc/config/i370/i370.h ! 4214408308b ./gcc/config/i370/i370.md ! 577722511b ./gcc/config/i370/linux.h ! 191137681b ./gcc/config/i370/mvs.h ! 3293906116b ./gcc/config/i370/oe.h ! 1034372910b ./gcc/config/i370/t-i370 ! 1100145942b ./gcc/config/i370/t-oe ! 2939308789b ./gcc/config/i386/athlon.md ! 3863347282b ./gcc/config/i386/att.h ! 2364445438b ./gcc/config/i386/beos-elf.h ! 3766713138b ./gcc/config/i386/biarch64.h ! 1477481609b ./gcc/config/i386/bsd.h ! 1364240360b ./gcc/config/i386/crtdll.h ! 4293145615b ./gcc/config/i386/cygwin.asm ! 349707370b ./gcc/config/i386/cygwin.h ! 2056477512b ./gcc/config/i386/darwin.h ! 608631702b ./gcc/config/i386/djgpp.h ! 3766969086b ./gcc/config/i386/emmintrin.h ! 1846061297b ./gcc/config/i386/freebsd-aout.h ! 2385678914b ./gcc/config/i386/freebsd.h ! 77685811b ./gcc/config/i386/freebsd64.h ! 1581335257b ./gcc/config/i386/gas.h 4266288971b ./gcc/config/i386/gmon-sol2.c ! 2242373399b ./gcc/config/i386/gnu.h 240648641b ./gcc/config/i386/gstabs.h ! 798942156b ./gcc/config/i386/gthr-win32.c ! 3155216183b ./gcc/config/i386/i386-aout.h ! 2124176398b ./gcc/config/i386/i386-coff.h ! 1295044612b ./gcc/config/i386/i386-interix.h ! 1579586996b ./gcc/config/i386/i386-interix3.h ! 1349730319b ./gcc/config/i386/i386-modes.def ! 1963183629b ./gcc/config/i386/i386-protos.h ! 4151473718b ./gcc/config/i386/i386.c ! 3999975198b ./gcc/config/i386/i386.h ! 1850777154b ./gcc/config/i386/i386.md ! 3652974168b ./gcc/config/i386/i386elf.h ! 3010218896b ./gcc/config/i386/k6.md 877642037b ./gcc/config/i386/libgcc-x86_64-glibc.ver ! 2740762784b ./gcc/config/i386/linux-aout.h ! 1734112220b ./gcc/config/i386/linux.h ! 1143030283b ./gcc/config/i386/linux64.h ! 2085036314b ./gcc/config/i386/lynx-ng.h ! 4257006542b ./gcc/config/i386/lynx.h 720171487b ./gcc/config/i386/mach.h ! 2356303309b ./gcc/config/i386/mingw32.h ! 792087563b ./gcc/config/i386/mmintrin.h ! 2276904589b ./gcc/config/i386/moss.h ! 1701064821b ./gcc/config/i386/netbsd-elf.h 4058916110b ./gcc/config/i386/netbsd.h ! 1802874307b ./gcc/config/i386/netbsd64.h ! 3368473133b ./gcc/config/i386/netware.h ! 1680355485b ./gcc/config/i386/openbsd.h ! 3736205979b ./gcc/config/i386/pentium.md ! 2175093847b ./gcc/config/i386/pmmintrin.h ! 3476241273b ./gcc/config/i386/ppro.md ! 1986050166b ./gcc/config/i386/ptx4-i.h ! 574801934b ./gcc/config/i386/rtemself.h ! 3499499073b ./gcc/config/i386/sco5.h 425477609b ./gcc/config/i386/sol2-c1.asm 1565106149b ./gcc/config/i386/sol2-ci.asm 4008317666b ./gcc/config/i386/sol2-cn.asm 2045686122b ./gcc/config/i386/sol2-gc1.asm ! 3525567971b ./gcc/config/i386/sol2.h 3846064431b ./gcc/config/i386/svr3.ifile - 2491384943b ./gcc/config/i386/svr3dbx.h - 4076081204b ./gcc/config/i386/svr3gas.h 1523044645b ./gcc/config/i386/svr3z.ifile ! 139630777b ./gcc/config/i386/sysv3.h ! 1152040164b ./gcc/config/i386/sysv4-cpp.h ! 1378936193b ./gcc/config/i386/sysv4.h ! 3004666215b ./gcc/config/i386/sysv5.h ! 3914733738b ./gcc/config/i386/t-beos 2437302600b ./gcc/config/i386/t-crtpic 2246944266b ./gcc/config/i386/t-crtstuff ! 687615070b ./gcc/config/i386/t-cygwin 2902972689b ./gcc/config/i386/t-djgpp 537671296b ./gcc/config/i386/t-i386elf ! 2564210106b ./gcc/config/i386/t-interix 3660907309b ./gcc/config/i386/t-linux64 160014998b ./gcc/config/i386/t-mingw32 ! 92801654b ./gcc/config/i386/t-netware 709063989b ./gcc/config/i386/t-openbsd 422823583b ./gcc/config/i386/t-rtems-i386 ! 2334743380b ./gcc/config/i386/t-sco5 2786912378b ./gcc/config/i386/t-sol2 3128852740b ./gcc/config/i386/t-svr3dbx 2977164768b ./gcc/config/i386/t-udk 1023926647b ./gcc/config/i386/t-uwin 1775100101b ./gcc/config/i386/udk.h ! 3322583387b ./gcc/config/i386/unix.h 2798938994b ./gcc/config/i386/uwin.asm ! 131643872b ./gcc/config/i386/uwin.h ! 3582201266b ./gcc/config/i386/vsta.h ! 2708017943b ./gcc/config/i386/vxi386.h ! 1855791963b ./gcc/config/i386/win32.h ! 3157997263b ./gcc/config/i386/winnt.c ! 239023222b ./gcc/config/i386/x86-64.h ! 1690208514b ./gcc/config/i386/xm-cygwin.h ! 3902343879b ./gcc/config/i386/xm-djgpp.h ! 3631826497b ./gcc/config/i386/xm-i386-interix.h ! 92688945b ./gcc/config/i386/xm-mingw32.h ! 3684275717b ./gcc/config/i386/xm-vsta.h ! 551915097b ./gcc/config/i386/xmmintrin.h ! 3455814797b ./gcc/config/i960/i960-c.c ! 3384279950b ./gcc/config/i960/i960-coff.h ! 1168116397b ./gcc/config/i960/i960-modes.def ! 2301317945b ./gcc/config/i960/i960-protos.h ! 1340742553b ./gcc/config/i960/i960.c ! 283530641b ./gcc/config/i960/i960.h ! 3878035903b ./gcc/config/i960/i960.md ! 1281966645b ./gcc/config/i960/rtems.h ! 2106185496b ./gcc/config/i960/t-960bare ! 3631800738b ./gcc/config/i960/t-vxworks960 ! 3103531078b ./gcc/config/i960/vx960-coff.h ! 1895495318b ./gcc/config/i960/vx960.h ! 2397709646b ./gcc/config/ia64/aix.h ! 2620377854b ./gcc/config/ia64/crtbegin.asm ! 772692470b ./gcc/config/ia64/crtend.asm 281392077b ./gcc/config/ia64/crtfastmath.c ! 3128441059b ./gcc/config/ia64/crti.asm ! 3161585686b ./gcc/config/ia64/crtn.asm ! 1650540400b ./gcc/config/ia64/elf.h ! 2446839914b ./gcc/config/ia64/fde-glibc.c ! 2020318486b ./gcc/config/ia64/freebsd.h ! 89320936b ./gcc/config/ia64/hpux.h ! 3568056609b ./gcc/config/ia64/hpux_longdouble.h ! 1964471896b ./gcc/config/ia64/ia64-c.c ! 342783782b ./gcc/config/ia64/ia64-modes.def ! 3227157966b ./gcc/config/ia64/ia64-protos.h ! 2795822269b ./gcc/config/ia64/ia64.c ! 1078623376b ./gcc/config/ia64/ia64.h ! 3224577197b ./gcc/config/ia64/ia64.md 2966325857b ./gcc/config/ia64/ia64intrin.h ! 3488320870b ./gcc/config/ia64/lib1funcs.asm 2632266533b ./gcc/config/ia64/libgcc-ia64.ver ! 2199665684b ./gcc/config/ia64/linux.h ! 3940638341b ./gcc/config/ia64/quadlib.c ! 4206796904b ./gcc/config/ia64/sysv4.h ! 3165145488b ./gcc/config/ia64/t-aix 2148782144b ./gcc/config/ia64/t-glibc ! 1051208108b ./gcc/config/ia64/t-hpux ! 308156643b ./gcc/config/ia64/t-ia64 ! 2759923269b ./gcc/config/ia64/unwind-aix.c ! 2016093184b ./gcc/config/ia64/unwind-ia64.c ! 2355075302b ./gcc/config/ia64/unwind-ia64.h ! 4115959553b ./gcc/config/interix.h ! 3221870490b ./gcc/config/interix3.h ! 1877317600b ./gcc/config/ip2k/crt0.S ! 2278252724b ./gcc/config/ip2k/ip2k-protos.h ! 2273505501b ./gcc/config/ip2k/ip2k.c ! 379096003b ./gcc/config/ip2k/ip2k.h ! 3634264842b ./gcc/config/ip2k/ip2k.md ! 3381820128b ./gcc/config/ip2k/libgcc.S 3899189512b ./gcc/config/ip2k/t-ip2k 3774321010b ./gcc/config/libgcc-glibc.ver ! 431681775b ./gcc/config/libgloss.h ! 1132125030b ./gcc/config/linux-aout.h ! 3480817898b ./gcc/config/linux.h ! 1696444785b ./gcc/config/lynx-ng.h ! 836960090b ./gcc/config/lynx.h ! 2460604231b ./gcc/config/m32r/initfini.c ! 4238084767b ./gcc/config/m32r/m32r-protos.h ! 3082370632b ./gcc/config/m32r/m32r.c ! 582485384b ./gcc/config/m32r/m32r.h ! 3253973863b ./gcc/config/m32r/m32r.md ! 3043182144b ./gcc/config/m32r/t-m32r ! 2563624329b ./gcc/config/m68hc11/larith.asm ! 763404077b ./gcc/config/m68hc11/m68hc11-crt0.S ! 3203494610b ./gcc/config/m68hc11/m68hc11-protos.h ! 3705868201b ./gcc/config/m68hc11/m68hc11.c ! 1421065453b ./gcc/config/m68hc11/m68hc11.h ! 2108112324b ./gcc/config/m68hc11/m68hc11.md ! 900567272b ./gcc/config/m68hc11/m68hc12.h ! 414967778b ./gcc/config/m68hc11/t-m68hc11-gas ! 950165799b ./gcc/config/m68k/3b1.h ! 4152566641b ./gcc/config/m68k/3b1g.h ! 3699861513b ./gcc/config/m68k/amix.h ! 407639156b ./gcc/config/m68k/atari.h ! 2332207756b ./gcc/config/m68k/ccur-GAS.h ! 3538569647b ./gcc/config/m68k/coff.h ! 4282280342b ./gcc/config/m68k/crds.h ! 1173190318b ./gcc/config/m68k/crti.s ! 4181788584b ./gcc/config/m68k/crtn.s ! 2518640661b ./gcc/config/m68k/fpgnulib.c ! 835972293b ./gcc/config/m68k/hp2bsd.h ! 2184215546b ./gcc/config/m68k/hp310.h ! 2008864906b ./gcc/config/m68k/hp310g.h ! 3937265644b ./gcc/config/m68k/hp320.h ! 2880102244b ./gcc/config/m68k/hp320g.h ! 2670392370b ./gcc/config/m68k/hp3bsd.h ! 724663990b ./gcc/config/m68k/hp3bsd44.h ! 2864047424b ./gcc/config/m68k/hpux7.h ! 704862081b ./gcc/config/m68k/lb1sf68.asm ! 1561647958b ./gcc/config/m68k/linux-aout.h ! 2094168098b ./gcc/config/m68k/linux.h ! 3379792683b ./gcc/config/m68k/m68020-elf.h ! 1327537006b ./gcc/config/m68k/m68k-aout.h ! 3882947461b ./gcc/config/m68k/m68k-coff.h ! 3855098247b ./gcc/config/m68k/m68k-none.h ! 3524361138b ./gcc/config/m68k/m68k-protos.h ! 1109594909b ./gcc/config/m68k/m68k-psos.h ! 2980964013b ./gcc/config/m68k/m68k.c ! 2362160659b ./gcc/config/m68k/m68k.h ! 1138622429b ./gcc/config/m68k/m68k.md ! 2319834314b ./gcc/config/m68k/m68kelf.h ! 1120822994b ./gcc/config/m68k/m68kemb.h ! 2697287693b ./gcc/config/m68k/m68kv4.h 3047408322b ./gcc/config/m68k/math-68