package com.oracle.svm.core.posix;
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.StackValue;
import org.graalvm.nativeimage.c.type.CTypeConversion;
import org.graalvm.nativeimage.c.type.CTypeConversion.CCharPointerHolder;
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.impl.InternalPlatform;
import org.graalvm.word.PointerBase;
import org.graalvm.word.UnsignedWord;
import org.graalvm.word.WordFactory;
import com.oracle.svm.core.CErrorNumber;
import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.AutomaticFeature;
import com.oracle.svm.core.annotate.TargetClass;
import com.oracle.svm.core.jdk.JNIPlatformNativeLibrarySupport;
import com.oracle.svm.core.jdk.Jvm;
import com.oracle.svm.core.jdk.NativeLibrarySupport;
import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport;
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.posix.headers.Dlfcn;
import com.oracle.svm.core.posix.headers.Resource;
import com.oracle.svm.core.posix.headers.darwin.DarwinSyslimits;
@AutomaticFeature
class PosixNativeLibraryFeature implements Feature {
@Override
public void afterRegistration(AfterRegistrationAccess access) {
PosixNativeLibrarySupport.initialize();
}
@Override
public void duringSetup(DuringSetupAccess access) {
if (JavaVersionUtil.JAVA_SPEC >= 11) {
NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("extnet");
}
}
}
final class PosixNativeLibrarySupport extends JNIPlatformNativeLibrarySupport {
@Platforms(Platform.HOSTED_ONLY.class)
private PosixNativeLibrarySupport() {
}
static void initialize() {
ImageSingletons.add(PlatformNativeLibrarySupport.class, new PosixNativeLibrarySupport());
}
@Override
public boolean initializeBuiltinLibraries() {
if (isFirstIsolate()) {
Resource.rlimit rlp = StackValue.get(Resource.rlimit.class);
if (Resource.getrlimit(Resource.RLIMIT_NOFILE(), rlp) == 0) {
UnsignedWord newValue = rlp.rlim_max();
if (Platform.includedIn(Platform.DARWIN.class)) {
newValue = WordFactory.unsigned(DarwinSyslimits.OPEN_MAX());
}
rlp.set_rlim_cur(newValue);
if (Resource.setrlimit(Resource.RLIMIT_NOFILE(), rlp) != 0) {
Log.log().string("setrlimit to increase file descriptor limit failed, errno ").signed(CErrorNumber.getCErrorNumber()).newline();
}
} else {
Log.log().string("getrlimit failed, errno ").signed(CErrorNumber.getCErrorNumber()).newline();
}
}
if (Platform.includedIn(InternalPlatform.PLATFORM_JNI.class)) {
try {
loadJavaLibrary();
loadZipLibrary();
loadNetLibrary();
System.setProperty("jdk.lang.Process.launchMechanism", "FORK");
} catch (UnsatisfiedLinkError e) {
Log.log().string("System.loadLibrary failed, " + e).newline();
return false;
}
}
return true;
}
@Override
protected void loadJavaLibrary() {
super.loadJavaLibrary();
Target_java_io_UnixFileSystem_JNI.initIDs();
}
protected void loadNetLibrary() {
if (isFirstIsolate()) {
System.loadLibrary("net");
} else {
NativeLibrarySupport.singleton().registerInitializedBuiltinLibrary("net");
}
}
@Override
public PosixNativeLibrary createLibrary(String canonical, boolean builtIn) {
return new PosixNativeLibrary(canonical, builtIn);
}
@Override
public PointerBase findBuiltinSymbol(String name) {
try (CCharPointerHolder symbol = CTypeConversion.toCString(name)) {
return Dlfcn.dlsym(Dlfcn.RTLD_DEFAULT(), symbol.get());
}
}
class PosixNativeLibrary implements NativeLibrary {
private final String canonicalIdentifier;
private final boolean builtin;
private PointerBase dlhandle = WordFactory.nullPointer();
private boolean loaded = false;
PosixNativeLibrary(String canonicalIdentifier, boolean builtin) {
this.canonicalIdentifier = canonicalIdentifier;
this.builtin = builtin;
}
@Override
public String getCanonicalIdentifier() {
return canonicalIdentifier;
}
@Override
public boolean isBuiltin() {
return builtin;
}
@Override
public boolean load() {
assert !loaded;
loaded = doLoad();
return loaded;
}
private boolean doLoad() {
if (Platform.includedIn(Platform.LINUX.class) ||
Platform.includedIn(Platform.DARWIN.class)) {
Jvm.initialize();
}
if (builtin) {
return true;
}
assert dlhandle.isNull();
dlhandle = PosixUtils.dlopen(canonicalIdentifier, Dlfcn.RTLD_LAZY());
return dlhandle.isNonNull();
}
@Override
public boolean isLoaded() {
return loaded;
}
@Override
public PointerBase findSymbol(String name) {
if (builtin) {
return findBuiltinSymbol(name);
}
assert dlhandle.isNonNull();
return PosixUtils.dlsym(dlhandle, name);
}
}
}
@TargetClass(className = "java.io.UnixFileSystem")
final class Target_java_io_UnixFileSystem_JNI {
@Alias
static native void initIDs();
}