jdk-24/test/hotspot/jtreg/runtime/TLS/exestack-tls.c
Aleksei Voitylov 63009f90ec 8247589: Implementation of Alpine Linux/x64 Port
Co-authored-by: Mikael Vidstedt <mikael@openjdk.org>
Co-authored-by: Alexander Scherbatiy <alexsch@openjdk.org>
Co-authored-by: Axel Siebenborn <asiebenborn@openjdk.org>
Co-authored-by: Aleksei Voitylov <avoitylov@openjdk.org>
Reviewed-by: alanb, erikj, dholmes
2020-10-13 09:35:58 +00:00

133 lines
4.2 KiB
C

/*
* Copyright (c) 2019, Google Inc. All rights reserved.
* Copyright (c) 2019, 2020, 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>
#ifdef __GLIBC__
#include <gnu/libc-version.h>
#endif
// 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;
}
#ifdef __GLIBC__
// glibc 2.15 introduced __pthread_get_minstack
int glibc_has_pthread_get_minstack() {
const char* glibc_vers = gnu_get_libc_version();
const int glibc_vers_major = atoi(glibc_vers);
const int glibc_vers_minor = atoi(strchr(glibc_vers, '.') + 1);;
printf("GNU libc version: %s\n", glibc_vers);
if ((glibc_vers_major > 2) || ((glibc_vers_major == 2) && (glibc_vers_minor >= 15))) {
return 1;
}
printf("This version does not provide __pthread_get_minstack\n");
return 0;
}
#else
int glibc_has_pthread_get_minstack() {
return 0;
}
#endif
int run(jboolean addTLS) {
JavaVM *jvm;
jclass testClass;
jmethodID runMethod;
char* argTLS;
int res = -1;
if (addTLS) {
if (!glibc_has_pthread_get_minstack()) {
printf("Skipping the test.\n");
return 0;
}
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);
}
}