--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/TLS/exestack-tls.c Tue Jul 09 10:27:38 2019 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2019, Google Inc. All rights reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Declare the thread local variable(s) in the main executable. This can be
+// used to demonstrate the issues associated with the on-stack static TLS blocks
+// that may cause insufficient stack space. The dynamic TLS blocks for shared
+// objects (such as a JNI library) loaded via dlopen are not allocated on stack.
+__thread int tls[128 * 1024];
+
+JNIEnv* create_vm(JavaVM **jvm, char* argTLS) {
+ JNIEnv* env;
+ JavaVMInitArgs args;
+ JavaVMOption options[3];
+ args.version = JNI_VERSION_1_8;
+ args.nOptions = 3;
+ char classpath[4096];
+ snprintf(classpath, sizeof classpath,
+ "-Djava.class.path=%s", getenv("CLASSPATH"));
+ options[0].optionString = classpath;
+ options[1].optionString = "-Xlog:os+thread=info";
+ options[2].optionString = argTLS;
+ args.options = &options[0];
+ args.ignoreUnrecognized = 0;
+ int rv;
+ rv = JNI_CreateJavaVM(jvm, (void**)&env, &args);
+ if (rv < 0) return NULL;
+ return env;
+}
+
+int run(jboolean addTLS) {
+ JavaVM *jvm;
+ jclass testClass;
+ jmethodID runMethod;
+ char* argTLS;
+ int res = -1;
+
+ if (addTLS) {
+ argTLS = "-XX:+AdjustStackSizeForTLS";
+ } else {
+ argTLS = "-XX:-AdjustStackSizeForTLS"; // default
+ }
+ printf("Running test with %s ...\n", argTLS);
+ JNIEnv *env = create_vm(&jvm, argTLS);
+
+ // Run T.run() and check result:
+ // - Expect T.run() to return 'true' when stack size is adjusted for TLS,
+ // return 0 if so
+ // - Expect T.run() to return 'false' if stack size is not adjusted for
+ // TLS, return 0 if so
+ // Return -1 (fail) for other cases
+ testClass = (*env)->FindClass(env, "T");
+ runMethod = (*env)->GetStaticMethodID(env, testClass, "run", "()Z");
+ if ((*env)->CallStaticBooleanMethod(env, testClass, runMethod, NULL)) {
+ if (addTLS) {
+ // expect T.run() to return 'true'
+ res = 0;
+ }
+ } else {
+ if (!addTLS) {
+ // expect T.run() to return 'false'
+ res = 0;
+ }
+ }
+
+ if (res == 0) {
+ printf("Test passed with %s\n", argTLS);
+ } else {
+ printf("Test failed with %s\n", argTLS);
+ }
+ return res;
+}
+
+int main(int argc, char **argv) {
+ if (argc == 2 && strcmp(argv[1], "-add_tls") == 0) {
+ return run(JNI_TRUE);
+ } else {
+ return run(JNI_FALSE);
+ }
+}