Skip to content

Commit

Permalink
[GR-57969] Update PosixPerfMemoryProvider to JDK 24+13 and annotate w…
Browse files Browse the repository at this point in the history
…ith @BasedOnJDKFile.

PullRequest: graal/18801
  • Loading branch information
christianhaeubl committed Sep 16, 2024
2 parents 65bff40 + 84be97d commit 09e0d06
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,16 @@
import com.oracle.svm.core.posix.headers.Errno;
import com.oracle.svm.core.posix.headers.Locale;
import com.oracle.svm.core.posix.headers.Pwd;
import com.oracle.svm.core.posix.headers.Pwd.passwd;
import com.oracle.svm.core.posix.headers.Pwd.passwdPointer;
import com.oracle.svm.core.posix.headers.Signal;
import com.oracle.svm.core.posix.headers.Time;
import com.oracle.svm.core.posix.headers.Unistd;
import com.oracle.svm.core.posix.headers.Wait;
import com.oracle.svm.core.posix.headers.Pwd.passwd;
import com.oracle.svm.core.posix.headers.Pwd.passwdPointer;
import com.oracle.svm.core.posix.headers.darwin.DarwinTime;
import com.oracle.svm.core.posix.headers.linux.LinuxTime;
import com.oracle.svm.core.thread.VMOperation;
import com.oracle.svm.core.util.BasedOnJDKFile;
import com.oracle.svm.core.util.VMError;

public class PosixUtils {
Expand Down Expand Up @@ -352,6 +353,7 @@ public static String getUserDir(int uid) {
return getUserNameOrDir(uid, false);
}

@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L436-L486")
private static String getUserNameOrDir(int uid, boolean name) {
/* Determine max. pwBuf size. */
long bufSize = Unistd.sysconf(_SC_GETPW_R_SIZE_MAX());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class PosixDirectives implements CContext.Directives {
"<semaphore.h>",
"<signal.h>",
"<errno.h>",
"<sys/file.h>",
"<sys/mman.h>",
"<sys/resource.h>",
"<sys/stat.h>",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2024, 2024, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.oracle.svm.core.posix.headers;

import org.graalvm.nativeimage.c.CContext;
import org.graalvm.nativeimage.c.constant.CConstant;
import org.graalvm.nativeimage.c.function.CFunction;

import com.oracle.svm.core.headers.LibC;

// Checkstyle: stop

/**
* See C header file <sys/file.h>.
*/
@CContext(PosixDirectives.class)
public class PosixFile {
@CConstant
public static native int LOCK_EX();

@CConstant
public static native int LOCK_NB();

@CFunction
public static native int flock(int fd, int operation);

public static int restartableFlock(int fd, int operation) {
int result;
do {
result = flock(fd, operation);
} while (result == -1 && LibC.errno() == Errno.EINTR());

return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platform.LINUX;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.StackValue;
import org.graalvm.nativeimage.c.type.CCharPointer;
Expand Down Expand Up @@ -71,17 +72,17 @@
import com.oracle.svm.core.posix.headers.Errno;
import com.oracle.svm.core.posix.headers.Fcntl;
import com.oracle.svm.core.posix.headers.Mman;
import com.oracle.svm.core.posix.headers.PosixFile;
import com.oracle.svm.core.posix.headers.Signal;
import com.oracle.svm.core.posix.headers.Unistd;
import com.oracle.svm.core.util.BasedOnJDKFile;

import jdk.graal.compiler.core.common.NumUtil;

/**
* This class uses high-level JDK features at the moment. In the future, we will need to rewrite
* this code so that it can be executed during the isolate startup (i.e., in uninterruptible code),
* see GR-40601.
* <p>
* Based on JDK 19 (git commit hash: 967a28c3d85fdde6d5eb48aa0edd8f7597772469, JDK tag: jdk-19+36.
*/
class PosixPerfMemoryProvider implements PerfMemoryProvider {
private static final String PERFDATA_NAME = "hsperfdata";
Expand All @@ -97,6 +98,7 @@ class PosixPerfMemoryProvider implements PerfMemoryProvider {
* null on failure. A return value of null will ultimately disable the shared memory feature.
*/
@Override
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L1015-L1082")
public ByteBuffer create() {
assert backingFilePath == null;

Expand All @@ -116,10 +118,10 @@ public ByteBuffer create() {

int fd;
try (CTypeConversion.CCharPointerHolder d = CTypeConversion.toCString(dirName)) {
cleanupSharedMemResources(d.get(), vmId);
cleanupSharedMemFiles(d.get(), vmId);

try (CTypeConversion.CCharPointerHolder f = CTypeConversion.toCString(fileName)) {
fd = createSharedMemResources(d.get(), f.get(), size);
fd = createSharedMemFile(d.get(), f.get(), size);
}
}

Expand All @@ -145,9 +147,10 @@ public ByteBuffer create() {
return DirectByteBufferUtil.allocate(mapAddress.rawValue(), size);
}

@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L134-L157")
private static String getUserTmpDir(String user, int vmId, int nsPid) {
String tmpDir = Target_jdk_internal_vm_VMSupport.getVMTemporaryDirectory();
if (Platform.includedIn(Platform.LINUX.class)) {
if (Platform.includedIn(LINUX.class)) {
if (nsPid != -1) {
/* Use different directory if we have a containerized process on Linux. */
tmpDir = "/proc/" + vmId + "/root" + tmpDir;
Expand All @@ -156,9 +159,10 @@ private static String getUserTmpDir(String user, int vmId, int nsPid) {
return tmpDir + "/" + PERFDATA_NAME + "_" + user;
}

@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L657-L668")
private static String getSharedMemFileName(int vmId, int nspid) {
int pid = vmId;
if (Platform.includedIn(Platform.LINUX.class) && nspid != -1) {
if (Platform.includedIn(LINUX.class) && nspid != -1) {
pid = nspid;
}
return Integer.toString(pid);
Expand All @@ -170,7 +174,8 @@ private static String getSharedMemFileName(int vmId, int nspid) {
* extracted from the file name and a test is run to determine if the process is alive. If the
* process is not alive, any stale file resources are removed.
*/
private static void cleanupSharedMemResources(CCharPointer directoryPath, int selfPid) {
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L703-L807")
private static void cleanupSharedMemFiles(CCharPointer directoryPath, int selfPid) {
try (SecureDirectory s = openDirectorySecure(directoryPath)) {
if (s == null) {
return;
Expand All @@ -188,6 +193,24 @@ private static void cleanupSharedMemResources(CCharPointer directoryPath, int se
continue;
}

int fileFd = -1;
if (Platform.includedIn(LINUX.class)) {
/*
* On Linux, different containerized processes may have the same pid and share
* the /tmp directory. So, use file locking to claim ownership of the file.
*/
fileFd = restartableOpenat(s.fd, entry.d_name(), O_RDONLY(), 0);
if (fileFd == -1) {
continue;
}

int n = PosixFile.restartableFlock(fileFd, PosixFile.LOCK_EX() | PosixFile.LOCK_NB());
if (n != 0) {
Unistd.NoTransitions.close(fileFd);
continue;
}
}

/*
* We now have a file name that converts to a valid integer that could represent a
* process id. If this process id matches the current process id or the process is
Expand All @@ -196,11 +219,17 @@ private static void cleanupSharedMemResources(CCharPointer directoryPath, int se
if (pid == selfPid || canFileBeDeleted(pid)) {
Fcntl.NoTransitions.unlinkat(s.fd, entry.d_name(), 0);
}

if (Platform.includedIn(LINUX.class)) {
/* Close the file and release the lock. */
Unistd.NoTransitions.close(fileFd);
}
}
}
}

private static int createSharedMemResources(CCharPointer directoryPath, CCharPointer filename, int size) {
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L853-L967")
private static int createSharedMemFile(CCharPointer directoryPath, CCharPointer filename, int size) {
if (!makeUserTmpDir(directoryPath)) {
return -1;
}
Expand All @@ -215,6 +244,19 @@ private static int createSharedMemResources(CCharPointer directoryPath, CCharPoi
return -1;
}

if (Platform.includedIn(LINUX.class)) {
/*
* On Linux, different containerized processes may have the same pid and share the /tmp
* directory. So, try to claim exclusive ownership of the file before manipulating the
* file.
*/
int n = PosixFile.restartableFlock(fd, PosixFile.LOCK_EX() | PosixFile.LOCK_NB());
if (n != 0) {
Unistd.NoTransitions.close(fd);
return -1;
}
}

/* Truncate the file to get rid of any existing data. */
int result = restartableFtruncate(fd, 0);
if (result == -1) {
Expand Down Expand Up @@ -275,6 +317,7 @@ private static int tryCreatePerfFile(CCharPointer directoryPath, CCharPointer fi
* Convert the given file name into a process id. If the file does not meet the file naming
* constraints, return 0.
*/
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L162-L191")
private static int filenameToPid(String filename) {
try {
return Integer.parseInt(filename);
Expand All @@ -284,6 +327,7 @@ private static int filenameToPid(String filename) {
}

@Uninterruptible(reason = "LibC.errno() must not be overwritten accidentally.")
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L814-L845")
private static boolean makeUserTmpDir(CCharPointer directory) {
/*
* Create the directory with 0755 permissions. note that the directory will be owned by
Expand All @@ -304,6 +348,7 @@ private static boolean makeUserTmpDir(CCharPointer directory) {
return true;
}

@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L291-L341")
private static SecureDirectory openDirectorySecure(CCharPointer directory) {
int fd = restartableOpen(directory, O_RDONLY() | O_NOFOLLOW(), 0);
if (fd == -1) {
Expand All @@ -329,6 +374,7 @@ private static SecureDirectory openDirectorySecure(CCharPointer directory) {
* true if the directory is considered a secure location. Returns false if the dir is a symbolic
* link or if an error occurred.
*/
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L230-L241")
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static boolean isDirectorySecure(CCharPointer directory) {
PosixStat.stat buf = StackValue.get(PosixStat.sizeOfStatStruct());
Expand All @@ -344,6 +390,7 @@ private static boolean isDirectorySecure(CCharPointer directory) {
* store files. Returns true if the directory exists and is considered a secure location.
* Returns false if the path is a symbolic link or if an error occurred.
*/
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L249-L260")
private static boolean isDirFdSecure(int dirFd) {
PosixStat.stat buf = StackValue.get(PosixStat.sizeOfStatStruct());
int result = restartableFstat(dirFd, buf);
Expand All @@ -353,6 +400,7 @@ private static boolean isDirFdSecure(int dirFd) {
return isStatBufSecure(buf);
}

@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L408-L429")
private static boolean isFileSecure(int fd) {
PosixStat.stat buf = StackValue.get(PosixStat.sizeOfStatStruct());
int result = restartableFstat(fd, buf);
Expand All @@ -371,6 +419,7 @@ private static boolean isFileSecure(int fd) {
* is a symbolic link or if an error occurred.
*/
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L199-L222")
private static boolean isStatBufSecure(PosixStat.stat statp) {
if (PosixStat.S_ISLNK(statp) || !PosixStat.S_ISDIR(statp)) {
/*
Expand Down Expand Up @@ -437,6 +486,7 @@ private static int restartableOpenat(int fd, CCharPointer filename, int flags, i
return result;
}

@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L675-L691")
private static int restartableUnlink(String pathname) {
try (CTypeConversion.CCharPointerHolder f = CTypeConversion.toCString(pathname)) {
return restartableUnlink(f.get());
Expand Down Expand Up @@ -484,6 +534,7 @@ private static int restartableLstat(CCharPointer directory, PosixStat.stat buf)
}

@Override
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+13/src/hotspot/os/posix/perfMemory_posix.cpp#L1112-L1128")
public void teardown() {
if (backingFilePath != null) {
restartableUnlink(backingFilePath);
Expand All @@ -509,7 +560,7 @@ public void close() {
}

@AutomaticallyRegisteredFeature
@Platforms({Platform.LINUX.class, Platform.DARWIN.class})
@Platforms({LINUX.class, Platform.DARWIN.class})
class PosixPerfMemoryFeature implements InternalFeature {
@Override
public boolean isInConfiguration(IsInConfigurationAccess access) {
Expand Down

0 comments on commit 09e0d06

Please sign in to comment.