From d1bb94992e15bf6f74b320d96d131403e75d329e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Thu, 5 Mar 2009 00:27:13 +0000 Subject: [PATCH] WIP migration of bootloader from C++ to C --- build.xml | 36 +- .../jni/org_jikesrvm_runtime_DynamicLibrary.c | 14 +- tools/bootloader/{jvm.C => jvm.c} | 0 tools/bootloader/{RunBootImage.C => main.c} | 149 ++-- tools/bootloader/sys.h | 10 + ...ysAlignmentCheck.C => sysAlignmentCheck.c} | 0 .../bootloader/{sysConsole.C => sysConsole.c} | 0 tools/bootloader/{sysGCSpy.C => sysGCSpy.c} | 0 tools/bootloader/{sysIO.C => sysIO.c} | 0 .../bootloader/{sysLibrary.C => sysLibrary.c} | 0 tools/bootloader/{sysMath.C => sysMath.c} | 0 tools/bootloader/{sysMemory.C => sysMemory.c} | 3 +- tools/bootloader/{sysMisc.C => sysMisc.c} | 8 +- .../bootloader/{sysPerfCtr.C => sysPerfCtr.c} | 0 tools/bootloader/sysThread.C | 4 +- tools/bootloader/sysThread.c | 674 ++++++++++++++++++ tools/bootloader/{sysTime.C => sysTime.c} | 0 17 files changed, 792 insertions(+), 106 deletions(-) rename tools/bootloader/{jvm.C => jvm.c} (100%) rename tools/bootloader/{RunBootImage.C => main.c} (86%) rename tools/bootloader/{sysAlignmentCheck.C => sysAlignmentCheck.c} (100%) rename tools/bootloader/{sysConsole.C => sysConsole.c} (100%) rename tools/bootloader/{sysGCSpy.C => sysGCSpy.c} (100%) rename tools/bootloader/{sysIO.C => sysIO.c} (100%) rename tools/bootloader/{sysLibrary.C => sysLibrary.c} (100%) rename tools/bootloader/{sysMath.C => sysMath.c} (100%) rename tools/bootloader/{sysMemory.C => sysMemory.c} (99%) rename tools/bootloader/{sysMisc.C => sysMisc.c} (98%) rename tools/bootloader/{sysPerfCtr.C => sysPerfCtr.c} (100%) create mode 100644 tools/bootloader/sysThread.c rename tools/bootloader/{sysTime.C => sysTime.c} (100%) diff --git a/build.xml b/build.xml index e864cb857..bda4a6688 100644 --- a/build.xml +++ b/build.xml @@ -1476,7 +1476,7 @@ Check to make sure all required properties are specified. This includes properti - + const unsigned heap_default_initial_size = ${config.default-heapsize.initial}*1024*1024; const unsigned heap_default_maximum_size = ${config.default-heapsize.maximum}*1024*1024; const char *rvm_version = "Jikes RVM ${rvm.version} (r${svn.revision})"; @@ -1531,7 +1531,7 @@ Check to make sure all required properties are specified. This includes properti - + @@ -1547,11 +1547,11 @@ Check to make sure all required properties are specified. This includes properti - + + value="${bl.dir}/main.c ${bl.dir}/sysGCSpy.c ${rvm.syscall.src} ${rvm.arch.src} ${perfctr.src}" + else="${bl.dir}/main.c ${rvm.syscall.src} ${rvm.arch.src} ${perfctr.src}"> @@ -1577,7 +1577,7 @@ Check to make sure all required properties are specified. This includes properti - + @@ -1585,7 +1585,7 @@ Check to make sure all required properties are specified. This includes properti - + @@ -1600,11 +1600,11 @@ Check to make sure all required properties are specified. This includes properti - - + + - + @@ -1618,7 +1618,7 @@ Check to make sure all required properties are specified. This includes properti - + @@ -1631,8 +1631,8 @@ Check to make sure all required properties are specified. This includes properti - - + + @@ -1650,8 +1650,8 @@ Check to make sure all required properties are specified. This includes properti - - + + @@ -1666,8 +1666,8 @@ Check to make sure all required properties are specified. This includes properti - - + + @@ -1694,7 +1694,7 @@ Check to make sure all required properties are specified. This includes properti - + diff --git a/tools/bootloader/jni/org_jikesrvm_runtime_DynamicLibrary.c b/tools/bootloader/jni/org_jikesrvm_runtime_DynamicLibrary.c index c5dbdcd7c..c2d8f572c 100644 --- a/tools/bootloader/jni/org_jikesrvm_runtime_DynamicLibrary.c +++ b/tools/bootloader/jni/org_jikesrvm_runtime_DynamicLibrary.c @@ -15,23 +15,23 @@ * JNI functions to support OnLoad */ -// Java includes +/* Java includes */ #include -// generated class header +/* generated class header */ #include "org_jikesrvm_runtime_DynamicLibrary.h" -extern struct Java sysJavaVM; +extern struct JavaVM_ sysJavaVM; -typedef jint (*JNI_OnLoad)(Java *vm, void *reserved); +typedef jint (*JNI_OnLoad)(struct JavaVM_ *vm, void *reserved); /* * Class: comibm.jikesrvm.DynamicLibrary * Method: runJNI_OnLoad * Signature: (Lorg/vmmagic/unboxed/Address;)I */ -extern "C" JNIEXPORT jint JNICALL Java_org_jikesrvm_runtime_DynamicLibrary_runJNI_1OnLoad (JNIEnv *env, - jclass clazz, - jobject JNI_OnLoadAddress) { +JNIEXPORT jint JNICALL Java_org_jikesrvm_runtime_DynamicLibrary_runJNI_1OnLoad (JNIEnv *env, + jclass clazz, + jobject JNI_OnLoadAddress) { return ((JNI_OnLoad)JNI_OnLoadAddress)(&sysJavaVM, NULL); } diff --git a/tools/bootloader/jvm.C b/tools/bootloader/jvm.c similarity index 100% rename from tools/bootloader/jvm.C rename to tools/bootloader/jvm.c diff --git a/tools/bootloader/RunBootImage.C b/tools/bootloader/main.c similarity index 86% rename from tools/bootloader/RunBootImage.C rename to tools/bootloader/main.c index bc88ca917..523136efe 100644 --- a/tools/bootloader/RunBootImage.C +++ b/tools/bootloader/main.c @@ -37,7 +37,7 @@ #define NEED_GNU_CLASSPATH_VERSION #define NEED_EXIT_STATUS_CODES // Get EXIT_STATUS_BOGUS_COMMAND_LINE_ARG -#include "RunBootImage.h" /* definitions created during the build */ +#include "bootloader.h" /* definitions created during the build */ #include "sys.h" #include /* isspace */ #include /* for strtol errors */ @@ -50,32 +50,32 @@ uint64_t maximumHeapSize; /* Declared in bootImageRunner.h */ int verboseBoot; /* Declared in bootImageRunner.h */ -static int DEBUG = 0; // have to set this from a debugger -static const unsigned BYTES_IN_PAGE = MMTk_Constants_BYTES_IN_PAGE; +static int DEBUG = 0; /* have to set this from a debugger */ +#define BYTES_IN_PAGE MMTk_Constants_BYTES_IN_PAGE /* These definitions must remain in sync with nonStandardArgs, the array * immediately below. */ -static const int HELP_INDEX = 0; -static const int VERBOSE_INDEX = HELP_INDEX+1; -static const int VERBOSE_BOOT_INDEX = VERBOSE_INDEX+1; -static const int MS_INDEX = VERBOSE_BOOT_INDEX+1; -static const int MX_INDEX = MS_INDEX+1; -static const int SYSLOGFILE_INDEX = MX_INDEX+1; -static const int BOOTIMAGE_CODE_FILE_INDEX = SYSLOGFILE_INDEX+1; -static const int BOOTIMAGE_DATA_FILE_INDEX = BOOTIMAGE_CODE_FILE_INDEX+1; -static const int BOOTIMAGE_RMAP_FILE_INDEX = BOOTIMAGE_DATA_FILE_INDEX+1; -static const int INDEX = BOOTIMAGE_RMAP_FILE_INDEX+1; -static const int GC_INDEX = INDEX+1; -static const int AOS_INDEX = GC_INDEX+1; -static const int IRC_INDEX = AOS_INDEX+1; -static const int RECOMP_INDEX = IRC_INDEX+1; -static const int BASE_INDEX = RECOMP_INDEX+1; -static const int OPT_INDEX = BASE_INDEX+1; -static const int VMCLASSES_INDEX = OPT_INDEX+1; -static const int CPUAFFINITY_INDEX = VMCLASSES_INDEX+1; -static const int PROCESSORS_INDEX = CPUAFFINITY_INDEX+1; - -static const int numNonstandardArgs = PROCESSORS_INDEX+1; +#define HELP_INDEX 0 +#define VERBOSE_INDEX HELP_INDEX+1 +#define VERBOSE_BOOT_INDEX VERBOSE_INDEX+1 +#define MS_INDEX VERBOSE_BOOT_INDEX+1 +#define MX_INDEX MS_INDEX+1 +#define SYSLOGFILE_INDEX MX_INDEX+1 +#define BOOTIMAGE_CODE_FILE_INDEX SYSLOGFILE_INDEX+1 +#define BOOTIMAGE_DATA_FILE_INDEX BOOTIMAGE_CODE_FILE_INDEX+1 +#define BOOTIMAGE_RMAP_FILE_INDEX BOOTIMAGE_DATA_FILE_INDEX+1 +#define INDEX BOOTIMAGE_RMAP_FILE_INDEX+1 +#define GC_INDEX INDEX+1 +#define AOS_INDEX GC_INDEX+1 +#define IRC_INDEX AOS_INDEX+1 +#define RECOMP_INDEX IRC_INDEX+1 +#define BASE_INDEX RECOMP_INDEX+1 +#define OPT_INDEX BASE_INDEX+1 +#define VMCLASSES_INDEX OPT_INDEX+1 +#define CPUAFFINITY_INDEX VMCLASSES_INDEX+1 +#define PROCESSORS_INDEX CPUAFFINITY_INDEX+1 + +#define numNonstandardArgs PROCESSORS_INDEX+1 static const char* nonStandardArgs[numNonstandardArgs] = { "-X", @@ -134,8 +134,8 @@ static const char* nonStandardUsage[] = { NULL /* End of messages */ }; -static bool strequal(const char *s1, const char *s2); -static bool strnequal(const char *s1, const char *s2, size_t n); +static int strequal(const char *s1, const char *s2); +static int strnequal(const char *s1, const char *s2, size_t n); /* * What standard command line arguments are supported? @@ -176,14 +176,15 @@ usage(void) static void nonstandard_usage() { - SYS_START(); - CONSOLE_PRINTF("Usage: %s [options] class [args...]\n",Me); - CONSOLE_PRINTF(" (to execute a class)\n"); - CONSOLE_PRINTF("where options include\n"); - for (const char * const *msgp = nonStandardUsage; *msgp; ++msgp) { - CONSOLE_PRINTF( *msgp); - CONSOLE_PRINTF("\n"); - } + const char * const *msgp = nonStandardUsage; + SYS_START(); + CONSOLE_PRINTF("Usage: %s [options] class [args...]\n",Me); + CONSOLE_PRINTF(" (to execute a class)\n"); + CONSOLE_PRINTF("where options include\n"); + for (;*msgp; ++msgp) { + CONSOLE_PRINTF( *msgp); + CONSOLE_PRINTF("\n"); + } } static void @@ -230,15 +231,15 @@ fullVersion() * In case of trouble, we set fastExit. We call exit(0) if no trouble, but * still want to exit. */ -static const char ** -processCommandLineArguments(const char *CLAs[], int n_CLAs, bool *fastExit) +static const char ** processCommandLineArguments(const char *CLAs[], int n_CLAs, int *fastExit) { SYS_START(); int n_JCLAs = 0; - bool startApplicationOptions = false; + int startApplicationOptions = 0; + int i; const char *subtoken; - for (int i = 0; i < n_CLAs; i++) { + for (i = 0; i < n_CLAs; i++) { const char *token = CLAs[i]; subtoken = NULL; // strictly, not needed. @@ -257,12 +258,13 @@ processCommandLineArguments(const char *CLAs[], int n_CLAs, bool *fastExit) // while (*argv && **argv == '-') { if (strequal(token, "-help") || strequal(token, "-?") ) { usage(); - *fastExit = true; + *fastExit = 1; break; } if (strequal(token, nonStandardArgs[HELP_INDEX])) { nonstandard_usage(); - *fastExit = true; break; + *fastExit = 1; + break; } if (strequal(token, nonStandardArgs[VERBOSE_INDEX])) { ++lib_verbose; @@ -278,14 +280,17 @@ processCommandLineArguments(const char *CLAs[], int n_CLAs, bool *fastExit) if (vb < 0) { CONSOLE_PRINTF( "%s: \"%s\": You may not specify a negative verboseBoot value\n", Me, token); - *fastExit = true; break; + *fastExit = 1; + break; } else if (errno == ERANGE || vb > INT_MAX ) { CONSOLE_PRINTF( "%s: \"%s\": too big a number to represent internally\n", Me, token); - *fastExit = true; break; + *fastExit = 1; + break; } else if (*endp) { CONSOLE_PRINTF( "%s: \"%s\": I don't recognize \"%s\" as a number\n", Me, token, subtoken); - *fastExit = true; break; + *fastExit = 1; + break; } verboseBoot = vb; @@ -298,12 +303,10 @@ processCommandLineArguments(const char *CLAs[], int n_CLAs, bool *fastExit) continue; if (strequal(token, "-version")) { shortVersion(); - // *fastExit = true; break; exit(0); } if (strequal(token, "-fullversion")) { fullVersion(); - // *fastExit = true; break; exit(0); } if (strequal(token, "-showversion")) { @@ -316,7 +319,6 @@ processCommandLineArguments(const char *CLAs[], int n_CLAs, bool *fastExit) } if (strequal(token, "-findMappable")) { findMappable(); - // *fastExit = true; break; exit(0); // success, no? } if (strnequal(token, "-verbose:gc", 11)) { @@ -334,13 +336,13 @@ processCommandLineArguments(const char *CLAs[], int n_CLAs, bool *fastExit) if (level < 0) { CONSOLE_PRINTF( "%s: \"%s\": You may not specify a negative GC verbose value\n", Me, token); - *fastExit = true; + *fastExit = 1; } else if (errno == ERANGE || level > INT_MAX ) { CONSOLE_PRINTF( "%s: \"%s\": too big a number to represent internally\n", Me, token); - *fastExit = true; + *fastExit = 1; } else if (*endp) { CONSOLE_PRINTF( "%s: \"%s\": I don't recognize \"%s\" as a number\n", Me, token, subtoken); - *fastExit = true; + *fastExit = 1; } if (*fastExit) { CONSOLE_PRINTF( "%s: please specify GC verbose level as \"-verbose:gc=\" or as \"-verbose:gc\"\n", Me); @@ -360,7 +362,7 @@ processCommandLineArguments(const char *CLAs[], int n_CLAs, bool *fastExit) if ((unsigned) ret >= bufsiz) { CONSOLE_PRINTF( "%s: \"%s\": %ld is too big a number" " to process internally\n", Me, token, level); - *fastExit = true; + *fastExit = 1; break; } @@ -396,7 +398,7 @@ processCommandLineArguments(const char *CLAs[], int n_CLAs, bool *fastExit) FILE* ftmp = fopen(subtoken, "a"); if (!ftmp) { CONSOLE_PRINTF( "%s: can't open SysTraceFile \"%s\": %s\n", Me, subtoken, strerror(errno)); - *fastExit = true; + *fastExit = 1; break; continue; } @@ -472,6 +474,7 @@ processCommandLineArguments(const char *CLAs[], int n_CLAs, bool *fastExit) int main(int argc, const char **argv) { + int j; SYS_START(); Me = strrchr(*argv, '/') + 1; ++argv, --argc; @@ -488,13 +491,13 @@ main(int argc, const char **argv) */ if (DEBUG) { printf("RunBootImage.main(): process %d command line arguments\n",argc); - for (int j=0; j (((long double) (UINT_MAX - roundTo))/factor) ) { CONSOLE_PRINTF( "%s: \"%s\": out of range to represent internally\n", Me, subtoken); - *fastExit = true; + *fastExit = 1; } } diff --git a/tools/bootloader/sys.h b/tools/bootloader/sys.h index 16fe6fb25..af5cc5663 100644 --- a/tools/bootloader/sys.h +++ b/tools/bootloader/sys.h @@ -89,5 +89,15 @@ EXTERNAL long long sysNanoTime(); EXTERNAL void sysExit(int) NORETURN; EXTERNAL void* sysMalloc(int length); EXTERNAL void sysFree(void *location); +EXTERNAL unsigned int parse_memory_size(const char *sizeName, /* "initial heap" or "maximum heap" or + "initial stack" or "maximum stack" + */ + const char *sizeFlag, // "-Xms" or "-Xmx" or + // "-Xss" or "-Xsg" or "-Xsx" + const char *defaultFactor, // We now always default to bytes ("") + unsigned roundTo, // Round to PAGE_SIZE_BYTES or to 4. + const char *token /* e.g., "-Xms200M" or "-Xms200" */, + const char *subtoken /* e.g., "200M" or "200" */, + int *fastExit); #endif // RVM_SYSCALL_DEFINITIONS diff --git a/tools/bootloader/sysAlignmentCheck.C b/tools/bootloader/sysAlignmentCheck.c similarity index 100% rename from tools/bootloader/sysAlignmentCheck.C rename to tools/bootloader/sysAlignmentCheck.c diff --git a/tools/bootloader/sysConsole.C b/tools/bootloader/sysConsole.c similarity index 100% rename from tools/bootloader/sysConsole.C rename to tools/bootloader/sysConsole.c diff --git a/tools/bootloader/sysGCSpy.C b/tools/bootloader/sysGCSpy.c similarity index 100% rename from tools/bootloader/sysGCSpy.C rename to tools/bootloader/sysGCSpy.c diff --git a/tools/bootloader/sysIO.C b/tools/bootloader/sysIO.c similarity index 100% rename from tools/bootloader/sysIO.C rename to tools/bootloader/sysIO.c diff --git a/tools/bootloader/sysLibrary.C b/tools/bootloader/sysLibrary.c similarity index 100% rename from tools/bootloader/sysLibrary.C rename to tools/bootloader/sysLibrary.c diff --git a/tools/bootloader/sysMath.C b/tools/bootloader/sysMath.c similarity index 100% rename from tools/bootloader/sysMath.C rename to tools/bootloader/sysMath.c diff --git a/tools/bootloader/sysMemory.C b/tools/bootloader/sysMemory.c similarity index 99% rename from tools/bootloader/sysMemory.C rename to tools/bootloader/sysMemory.c index f95216f40..1e5426f51 100644 --- a/tools/bootloader/sysMemory.C +++ b/tools/bootloader/sysMemory.c @@ -373,11 +373,12 @@ EXTERNAL int sysGetPageSize() */ EXTERNAL void findMappable() { + int i; int granularity = 1 << 22; // every 4 megabytes int max = (1 << 30) / (granularity >> 2); int pageSize = sysGetPageSize(); SYS_START(); - for (int i=0; i + +#ifdef RVM_FOR_HARMONY +// TODO: remove these dependencies for Harmony +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#endif + +#ifdef _AIX +#include +#endif + +#ifdef RVM_FOR_HARMONY +#define TLS_KEY_TYPE hythread_tls_key_t +#else +#define TLS_KEY_TYPE pthread_key_t +typedef struct { + pthread_mutex_t mutex; + pthread_cond_t cond; +} vmmonitor_t; +#endif + +/** keys for managing thread termination */ +static TLS_KEY_TYPE TerminateJmpBufKey; +static TLS_KEY_TYPE VmThreadKey; +static TLS_KEY_TYPE IsVmThreadKey; +static Address DeathLock; +static bool systemExiting = false; + +/* Function prototypes */ +#ifdef RVM_FOR_HARMONY +static int sysThreadStartup(void *args); +#else +static void* sysThreadStartup(void *args); +#endif +EXTERNAL Address sysMonitorCreate(); +EXTERNAL void sysMonitorEnter(Address _monitor); + +/** Initialize for sysCalls */ +EXTERNAL void sysInitialize() +{ +#ifdef RVM_FOR_HARMONY + VMI_Initialize(); + SYS_START(); /* start after VMI is initialized */ + DefaultPageSize = hyvmem_supported_page_sizes()[0]; +#endif + DeathLock = sysMonitorCreate(); +} + +/** Exit with a return code. */ +EXTERNAL void sysExit(int value) +{ + SYS_START(); + TRACE_PRINTF("%s: sysExit %d\n", Me, value); + // alignment checking: report info before exiting, then turn off checking +#ifdef RVM_WITH_ALIGNMENT_CHECKING + if (numEnableAlignCheckingCalls > 0) { + sysReportAlignmentChecking(); + sysDisableAlignmentChecking(); + } +#endif // RVM_WITH_ALIGNMENT_CHECKING + +#ifndef RVM_FOR_HARMONY + fflush(SysErrorFile); + fflush(SysTraceFile); + fflush(stdout); +#endif + systemExiting = true; + if (DeathLock != NULL) { + sysMonitorEnter(DeathLock); + } +#ifndef RVM_FOR_HARMONY + exit(value); +#else + hyexit_shutdown_and_exit(value); +#endif +} + + +/** Utility to create a thread local key */ +static TLS_KEY_TYPE createThreadLocal() +{ + SYS_START(); + TLS_KEY_TYPE key; + int rc; +#ifdef RVM_FOR_HARMONY + rc = hythread_tls_alloc(&key); +#else + rc = pthread_key_create(&key, 0); +#endif + if (rc != 0) { + ERROR_PRINTF("%s: alloc tls key failed (err=%d)\n", Me, rc); + sysExit(EXIT_STATUS_SYSCALL_TROUBLE); + } + return key; +} + +/** Utility to get a thread local key */ +static void* getThreadLocal(TLS_KEY_TYPE key) { +#ifdef RVM_FOR_HARMONY + return hythread_tls_get(hythread_self(), key); +#else + return pthread_getspecific(key); +#endif +} + +/** Utility to set a thread local key */ +static void setThreadLocal(TLS_KEY_TYPE key, void *value) { + SYS_START(); +#ifdef RVM_FOR_HARMONY + int rc = hythread_tls_set(hythread_self(), key, value); +#else + int rc = pthread_setspecific(key, value); +#endif + if (rc != 0) { + ERROR_PRINTF("%s: set tls failed (err=%d)\n", Me, rc); + sysExit(EXIT_STATUS_SYSCALL_TROUBLE); + } +} + +/** + * Stash address of the Thread object in the thread-specific data for + * the current native thread. This allows us to get a handle on the + * Thread (and its associated state) from arbitrary native code. + */ +EXTERNAL void sysStashVMThread(Address vmThread) +{ + SYS_START(); + TRACE_PRINTF("%s: sysStashVmProcessorInPthread %p\n", Me, vmThread); + setThreadLocal(VmThreadKey, (void*)vmThread); +} + +/** Read the VMThread stashed earlier, used in jvm.C */ +EXTERNAL void * getVMThread() +{ + SYS_START(); + TRACE_PRINTF("%s: getVMThread\n", Me); + return getThreadLocal(VmThreadKey); +} + +/** Create keys for thread-specific data. */ +EXTERNAL void sysCreateThreadSpecificDataKeys(void) +{ + int rc; + SYS_START(); + TRACE_PRINTF("%s: sysThreadSpecificDataKeys\n"); + + // Create a key for thread-specific data so we can associate + // the id of the Processor object with the pthread it is running on. + VmThreadKey = createThreadLocal(); + TerminateJmpBufKey = createThreadLocal(); + TRACE_PRINTF("%s: vm processor key=%u\n", Me, VmThreadKey); +} + +/** + * How many physical cpu's are present and actually online? + * Assume 1 if no other good ansewr. + * @return number of cpu's + * + * Note: this function is only called once. If it were called more often + * than that, we would want to use a static variable to indicate that we'd + * already printed the WARNING messages and were not about to print any more. + */ +EXTERNAL int sysNumProcessors() +{ + int numCpus = -1; /* -1 means failure. */ + SYS_START(); + TRACE_PRINTF("%s: sysNumProcessors\n", Me); +#ifdef RVM_FOR_HARMONY + numCpus = hysysinfo_get_number_CPUs(); +#else +#ifdef __GNU_LIBRARY__ // get_nprocs is part of the GNU C library. + /* get_nprocs_conf will give us a how many processors the operating + system configured. The number of processors actually online is what + we want. */ + // numCpus = get_nprocs_conf(); + errno = 0; + numCpus = get_nprocs(); + // It is not clear if get_nprocs can ever return failure; assume it might. + if (numCpus < 1) { + CONSOLE_PRINTF("%s: WARNING: get_nprocs() returned %d (errno=%d)\n", + Me, numCpus, errno); + /* Continue on. Try to get a better answer by some other method, not + that it's likely, but this should not be a fatal error. */ + } +#endif + +#if defined(CTL_HW) && defined(HW_NCPU) + if (numCpus < 1) { + int mib[2]; + size_t len; + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(numCpus); + errno = 0; + if (sysctl(mib, 2, &numCpus, &len, NULL, 0) < 0) { + CONSOLE_PRINTF("%s: WARNING: sysctl(CTL_HW,HW_NCPU) failed;" + " errno = %d\n", Me, errno); + numCpus = -1; // failed so far... + }; + } +#endif + +#if defined(_SC_NPROCESSORS_ONLN) + if (numCpus < 0) { + /* This alternative is probably the same as + * _system_configuration.ncpus. This one says how many CPUs are + * actually on line. It seems to be supported on AIX, at least; I + * yanked this out of sysVirtualProcessorBind. + */ + numCpus = sysconf(_SC_NPROCESSORS_ONLN); // does not set errno + if (numCpus < 0) { + CONSOLE_PRINTF("%s: WARNING: sysconf(_SC_NPROCESSORS_ONLN)" + " failed\n", Me); + } + } +#endif + +#ifdef _AIX + if (numCpus < 0) { + numCpus = _system_configuration.ncpus; + if (numCpus < 0) { + fprintf("%s: WARNING: _system_configuration.ncpus" + " has the insane value %d\n" , Me, numCpus); + } + } +#endif +#endif // RVM_FOR_HARMONY + + if (numCpus < 0) { + TRACE_PRINTF("%s: WARNING: Can not figure out how many CPUs" + " are online; assuming 1\n"); + numCpus = 1; // Default + } + + TRACE_PRINTF("%s: sysNumProcessors: returning %d\n", Me, numCpus); + return numCpus; +} + +/** + * Create a native thread + * Taken: register values to use for thread startup + * Returned: virtual processor's OS handle + */ +EXTERNAL Address sysThreadCreate(Address tr, Address ip, Address fp) +{ + Address *sysThreadArguments; +#ifndef RVM_FOR_HARMONY + pthread_attr_t sysThreadAttributes; + pthread_t sysThreadHandle; +#else + hythread_t sysThreadHandle; +#endif + int rc; + SYS_START(); + TRACE_PRINTF("%s: sysThreadCreate %p %p %p\n", Me, tr, ip, fp); + + // create arguments - memory reclaimed in sysThreadStartup + sysThreadArguments = (Address *)sysMalloc(sizeof(Address[3])); + sysThreadArguments[0] = tr; + sysThreadArguments[1] = ip; + sysThreadArguments[2] = fp; + +#ifndef RVM_FOR_HARMONY + // create attributes + if ((rc = pthread_attr_init(&sysThreadAttributes))) { + ERROR_PRINTF("%s: pthread_attr_init failed (rc=%d)\n", Me, rc); + sysExit(EXIT_STATUS_SYSCALL_TROUBLE); + } + // force 1:1 pthread to kernel thread mapping (on AIX 4.3) + pthread_attr_setscope(&sysThreadAttributes, PTHREAD_SCOPE_SYSTEM); +#endif + // create native thread +#ifdef RVM_FOR_HARMONY + rc = hythread_create(&sysThreadHandle, 0, HYTHREAD_PRIORITY_NORMAL, 0, + (hythread_entrypoint_t)sysThreadStartup, + sysThreadArguments); +#else + rc = pthread_create(&sysThreadHandle, + &sysThreadAttributes, + sysThreadStartup, + sysThreadArguments); +#endif + if (rc) + { + ERROR_PRINTF("%s: thread_create failed (rc=%d)\n", Me, rc); + sysExit(EXIT_STATUS_SYSCALL_TROUBLE); + } + +#ifndef RVM_FOR_HARMONY + rc = pthread_detach(sysThreadHandle); + if (rc) + { + ERROR_PRINTF("%s: pthread_detach failed (rc=%d)\n", Me, rc); + sysExit(EXIT_STATUS_SYSCALL_TROUBLE); + } +#endif + TRACE_PRINTF("%s: pthread_create 0x%08x\n", Me, (Address) sysThreadHandle); + + return (Address)sysThreadHandle; +} + +#ifdef RVM_FOR_HARMONY +static int sysThreadStartup(void *args) +#else +static void* sysThreadStartup(void *args) +#endif +{ + /* install a stack for hardwareTrapHandler() to run on */ + stack_t stack; + char *stackBuf; + Address tr, ip, fp, sp; + jmp_buf *jb; + + SYS_START(); + memset (&stack, 0, sizeof stack); + stackBuf = (char*)sysMalloc(sizeof(char[SIGSTKSZ])); + stack.ss_sp = stackBuf; + stack.ss_flags = 0; + stack.ss_size = SIGSTKSZ; + if (sigaltstack (&stack, 0)) { + ERROR_PRINTF("sigaltstack failed (errno=%d)\n",errno); + exit(1); + } + + tr = ((Address *)args)[0]; + ip = ((Address *)args)[1]; + fp = ((Address *)args)[2]; + sysFree(args); + + jb = (jmp_buf*)sysMalloc(sizeof(jmp_buf)); + if (setjmp(*jb)) { + // this is where we come to terminate the thread +#ifdef RVM_FOR_HARMONY + hythread_detach(NULL); +#endif + sysFree(jb); + *(int*)(tr + RVMThread_execStatus_offset) = RVMThread_TERMINATED; + stack.ss_flags = SS_DISABLE; + sigaltstack(&stack, 0); + sysFree(stackBuf); + } else { + setThreadLocal(TerminateJmpBufKey, (void*)jb); + TRACE_PRINTF("%s: sysThreadStartup: pr=%p ip=%p fp=%p\n", Me, tr, ip, fp); + // branch to vm code +#ifndef RVM_FOR_POWERPC + { + *(Address *) (tr + Thread_framePointer_offset) = fp; + sp = fp + Constants_STACKFRAME_BODY_OFFSET; + bootThread((void*)ip, (void*)tr, (void*)sp); + } +#else + bootThread((int)(Word)getJTOC(), tr, ip, fp); +#endif + // not reached + CONSOLE_PRINTF("%s: sysThreadStartup: failed\n", Me); + return 0; + } +} + + +/** Terminate a thread */ +EXTERNAL void sysThreadTerminate() +{ + SYS_START(); + TRACE_PRINTF("%s: sysThreadTerminate\n", Me); +#ifdef RVM_FOR_POWERPC + asm("sync"); +#endif + jmp_buf *jb = (jmp_buf*)getThreadLocal(TerminateJmpBufKey); + if (jb==NULL) { + jb=&primordial_jb; + } + longjmp(*jb,1); +} + +/** + * Perform some initialization related to per-thread signal handling + * for that thread. (Block SIGCONT, set up a special signal handling + * stack for the thread.) This is only called once, at thread startup + * time. + */ +EXTERNAL void sysSetupHardwareTrapHandler() +{ + int rc; // retval from subfunction. + SYS_START(); + TRACE_PRINTF("%s: sysSetupHardwareTrapHandler\n", Me); +#ifndef RVM_FOR_HARMONY +#ifndef RVM_FOR_AIX + /* + * Provide space for this pthread to process exceptions. This is + * needed on Linux because multiple pthreads can handle signals + * concurrently, since the masking of signals during handling applies + * on a per-pthread basis. + */ + stack_t stack; + + memset (&stack, 0, sizeof stack); + stack.ss_sp = (char*)sysMalloc(sizeof(char[SIGSTKSZ])); + + stack.ss_size = SIGSTKSZ; + if (sigaltstack (&stack, 0)) { + /* Only fails with EINVAL, ENOMEM, EPERM */ + ERROR_PRINTF ("sigaltstack failed (errno=%d): ", errno); + perror(NULL); + sysExit(EXIT_STATUS_IMPOSSIBLE_LIBRARY_FUNCTION_ERROR); + } +#endif + + /* + * Block the CONT signal. This makes SIGCONT reach this + * pthread only when this pthread performs a sigwait(). + */ + sigset_t input_set, output_set; + sigemptyset(&input_set); + sigaddset(&input_set, SIGCONT); + +#ifdef RVM_FOR_AIX + rc = sigthreadmask(SIG_BLOCK, &input_set, &output_set); + /* like pthread_sigmask, sigthreadmask can only return EINVAL, EFAULT, and + * EPERM. Again, these are all good reasons to complain and croak. */ +#else + rc = pthread_sigmask(SIG_BLOCK, &input_set, &output_set); + /* pthread_sigmask can only return the following errors. Either of them + * indicates serious trouble and is grounds for aborting the process: + * EINVAL EFAULT. */ +#endif + if (rc) { + ERROR_PRINTF ("pthread_sigmask or sigthreadmask failed (errno=%d):", errno); + perror(NULL); + sysExit(EXIT_STATUS_IMPOSSIBLE_LIBRARY_FUNCTION_ERROR); + } +#endif // RVM_FOR_HARMONY -- TODO +} + +EXTERNAL int sysThreadBindSupported() +{ + int result=0; + SYS_START(); + TRACE_PRINTF("%s: sysThreadBindSupported"); +#ifdef RVM_FOR_AIX + result=1; +#endif +#ifdef RVM_FOR_LINUX + result=1; +#endif + return result; +} + +/** + * Bind execution of current thread to specified physical cpu. + * Taken: physical cpu id (0, 1, 2, ...) + * Returned: nothing + */ +EXTERNAL void sysThreadBind(int UNUSED cpuId) +{ + SYS_START(); + TRACE_PRINTF("%s: sysThreadBind"); +#ifndef RVM_FOR_HARMONY + // bindprocessor() seems to be only on AIX +#ifdef RVM_FOR_AIX + int rc = bindprocessor(BINDTHREAD, thread_self(), cpuId); + fprintf("%s: bindprocessor pthread %d (kernel thread %d) %s to cpu %d\n", Me, pthread_self(), thread_self(), (rc ? "NOT bound" : "bound"), cpuId); + + if (rc) { + ERROR_PRINTF("%s: bindprocessor failed (errno=%d): ", Me, errno); + perror(NULL); + sysExit(EXIT_STATUS_SYSCALL_TROUBLE); + } +#endif + +#ifdef RVM_FOR_LINUX + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(cpuId, &cpuset); + + pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset); +#endif +#endif +} + +/** Return the thread ID of the current thread */ +EXTERNAL Address sysThreadSelf() +{ + void *thread; + SYS_START(); +#ifdef RVM_FOR_HARMONY + thread = hythread_self(); +#else + thread = (void*)pthread_self(); +#endif + TRACE_PRINTF("%s: sysThreadSelf: thread %p\n", Me, thread); + return (Address)thread; +} + +/** + * Yield execution of current thread back to o/s. + */ +EXTERNAL void sysThreadYield() +{ + SYS_START(); + TRACE_PRINTF("%s: sysThreadYield\n", Me); +#ifdef RVM_FOR_HARMONY + hythread_yield(); +#else + /* According to the Linux manpage, sched_yield()'s presence can be + * tested for by using the #define _POSIX_PRIORITY_SCHEDULING, and if + * that is not present to use the sysconf feature, searching against + * _SC_PRIORITY_SCHEDULING. However, I don't really trust it, since + * the AIX 5.1 include files include this definition: + * ./unistd.h:#undef _POSIX_PRIORITY_SCHEDULING + * so my trust that it is implemented properly is scanty. --augart + */ + sched_yield(); +#endif // RVM_FOR_HARMONY +} + + +/** + * Routine to sleep for a number of nanoseconds (howLongNanos). This is + * ridiculous on regular Linux, where we actually only sleep in increments of + * 1/HZ (1/100 of a second on x86). Luckily, Linux will round up. + * + * This is just used internally in the scheduler, but we might as well make + * the function work properly even if it gets used for other purposes. + * + * We don't return anything, since we don't need to right now. Just try to + * sleep; if interrupted, return. + */ +EXTERNAL void sysNanoSleep(long long howLongNanos) +{ + SYS_START(); + TRACE_PRINTF("%s: sysNanosleep %lld\n", Me, howLongNanos); +#ifdef RVM_FOR_HARMONY + hythread_sleep(howLongNanos/1000); +#else + struct timespec req; + const long long nanosPerSec = 1000LL * 1000 * 1000; + req.tv_sec = howLongNanos / nanosPerSec; + req.tv_nsec = howLongNanos % nanosPerSec; + int ret = nanosleep(&req, (struct timespec *) NULL); + if (ret < 0) { + if (errno == EINTR) + /* EINTR is expected, since we do use signals internally. */ + return; + ERROR_PRINTF("%s: nanosleep() failed:" + " %s (errno=%d)\n" + " That should never happen; please report it as a bug.\n", + Me, req.tv_sec, req.tv_nsec, + strerror( errno ), errno); + } +#endif +} + +EXTERNAL Address sysMonitorCreate() +{ + SYS_START(); + TRACE_PRINTF("%s: sysMonitorCreate\n", Me); +#ifdef RVM_FOR_HARMONY + hythread_monitor_t monitor; + hythread_monitor_init_with_name(&monitor, 0, NULL); +#else + vmmonitor_t *monitor = (vmmonitor_t*)sysMalloc(sizeof(vmmonitor_t)); + pthread_mutex_init(&monitor->mutex, NULL); + pthread_cond_init(&monitor->cond, NULL); +#endif + return (Address)monitor; +} + +EXTERNAL void sysMonitorDestroy(Address _monitor) +{ + SYS_START(); + TRACE_PRINTF("%s: sysMonitorDestroy\n", Me); +#ifdef RVM_FOR_HARMONY + hythread_monitor_destroy((hythread_monitor_t)_monitor); +#else + vmmonitor_t *monitor = (vmmonitor_t*)_monitor; + pthread_mutex_destroy(&monitor->mutex); + pthread_cond_destroy(&monitor->cond); + sysFree(monitor); +#endif +} + +EXTERNAL void sysMonitorEnter(Address _monitor) +{ + SYS_START(); + TRACE_PRINTF("%s: sysMonitorEnter\n", Me); +#ifdef RVM_FOR_HARMONY + hythread_monitor_enter((hythread_monitor_t)_monitor); +#else + vmmonitor_t *monitor = (vmmonitor_t*)_monitor; + pthread_mutex_lock(&monitor->mutex); +#endif +} + +EXTERNAL void sysMonitorExit(Address _monitor) +{ + SYS_START(); + TRACE_PRINTF("%s: sysMonitorExit\n", Me); +#ifdef RVM_FOR_HARMONY + hythread_monitor_exit((hythread_monitor_t)_monitor); +#else + vmmonitor_t *monitor = (vmmonitor_t*)_monitor; + pthread_mutex_unlock(&monitor->mutex); +#endif +} + +EXTERNAL void sysMonitorTimedWaitAbsolute(Address _monitor, long long whenWakeupNanos) +{ + SYS_START(); + TRACE_PRINTF("%s: sysMonitorTimedWaitAbsolute\n", Me); +#ifdef RVM_FOR_HARMONY + // syscall wait is absolute, but harmony monitor wait is relative. + whenWakeupNanos -= sysNanoTime(); + if (whenWakeupNanos <= 0) return; + hythread_monitor_wait_timed((hythread_monitor_t)_monitor, (I_64)(whenWakeupNanos / 1000000LL), (IDATA)(whenWakeupNanos % 1000000LL)); +#else + timespec ts; + ts.tv_sec = (time_t)(whenWakeupNanos/1000000000LL); + ts.tv_nsec = (long)(whenWakeupNanos%1000000000LL); + TRACE_PRINTF("starting wait at %lld until %lld (%ld, %ld)\n", + sysNanoTime(),whenWakeupNanos,ts.tv_sec,ts.tv_nsec); + vmmonitor_t *monitor = (vmmonitor_t*)_monitor; + int rc = pthread_cond_timedwait(&monitor->cond, &monitor->mutex, &ts); + TRACE_PRINTF("returned from wait at %lld instead of %lld with res = %d\n", + sysNanoTime(),whenWakeupNanos,rc); +#endif +} + +EXTERNAL void sysMonitorWait(Address _monitor) +{ + SYS_START(); + TRACE_PRINTF("%s: sysMonitorWait\n", Me); +#ifdef RVM_FOR_HARMONY + hythread_monitor_wait((hythread_monitor_t)_monitor); +#else + vmmonitor_t *monitor = (vmmonitor_t*)_monitor; + pthread_cond_wait(&monitor->cond, &monitor->mutex); +#endif +} + +EXTERNAL void sysMonitorNotifyAll(Address _monitor) +{ + SYS_START(); + TRACE_PRINTF("%s: sysMonitorBroadcast\n", Me); +#ifdef RVM_FOR_HARMONY + hythread_monitor_notify_all((hythread_monitor_t)_monitor); +#else + vmmonitor_t *monitor = (vmmonitor_t*)_monitor; + pthread_cond_broadcast(&monitor->cond); +#endif +} diff --git a/tools/bootloader/sysTime.C b/tools/bootloader/sysTime.c similarity index 100% rename from tools/bootloader/sysTime.C rename to tools/bootloader/sysTime.c