Skip to content

Commit

Permalink
[GR-18215] Uninterruptible stack walk
Browse files Browse the repository at this point in the history
PullRequest: graal/10980
  • Loading branch information
jovanstevanovic committed Mar 31, 2022
2 parents 63f1a04 + 2a4ad2e commit 3fc931b
Show file tree
Hide file tree
Showing 17 changed files with 148 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ default PointerBase getThreadPointer(Context context) {
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
default PointerBase getSP(Context context) {
return getSP((ucontext_t) context);
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
default PointerBase getIP(Context context) {
return getIP((ucontext_t) context);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,14 @@ public PointerBase getThreadPointer(Signal.ucontext_t uContext) {
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public PointerBase getSP(Signal.ucontext_t uContext) {
Signal.AArch64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_aarch64();
return WordFactory.pointer(sigcontext.sp());
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public PointerBase getIP(Signal.ucontext_t uContext) {
Signal.AArch64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_aarch64();
return WordFactory.pointer(sigcontext.pc());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,14 @@ public PointerBase getThreadPointer(ucontext_t uContext) {
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public PointerBase getSP(ucontext_t uContext) {
mcontext_linux_aarch64_t sigcontext = uContext.uc_mcontext_linux_aarch64();
return WordFactory.pointer(sigcontext.sp());
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public PointerBase getIP(ucontext_t uContext) {
mcontext_linux_aarch64_t sigcontext = uContext.uc_mcontext_linux_aarch64();
return WordFactory.pointer(sigcontext.pc());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,14 @@ public PointerBase getThreadPointer(ucontext_t uContext) {
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public PointerBase getSP(ucontext_t uContext) {
Signal.AMD64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_amd64();
return ((Pointer) sigcontext).readWord(sigcontext.rsp_offset());
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public PointerBase getIP(ucontext_t uContext) {
Signal.AMD64DarwinMContext64 sigcontext = uContext.uc_mcontext_darwin_amd64();
return ((Pointer) sigcontext).readWord(sigcontext.rip_offset());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,26 +82,28 @@ public void dumpRegisters(Log log, ucontext_t uContext, boolean printLocationInf
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true, calleeMustBe = false)
@Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true)
public PointerBase getHeapBase(ucontext_t uContext) {
GregsPointer gregs = uContext.uc_mcontext_linux_amd64_gregs();
return WordFactory.pointer(gregs.read(GregEnumLinuxAMD64.REG_R14()));
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true, calleeMustBe = false)
@Uninterruptible(reason = "Called from uninterruptible code", mayBeInlined = true)
public PointerBase getThreadPointer(ucontext_t uContext) {
GregsPointer gregs = uContext.uc_mcontext_linux_amd64_gregs();
return WordFactory.pointer(gregs.read(GregEnumLinuxAMD64.REG_R15()));
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public PointerBase getSP(ucontext_t uContext) {
GregsPointer gregs = uContext.uc_mcontext_linux_amd64_gregs();
return WordFactory.pointer(gregs.read(GregEnumLinuxAMD64.REG_RSP()));
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public PointerBase getIP(ucontext_t uContext) {
GregsPointer gregs = uContext.uc_mcontext_linux_amd64_gregs();
return WordFactory.pointer(gregs.read(GregEnumLinuxAMD64.REG_RIP()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ public class Errno {
@CConstant
public static native int ETIMEDOUT();

@CConstant
public static native int EFAULT();

@CConstant
public static native int EINVAL();

@CConstant
public static native int EAGAIN();

@CConstant
public static native int ENOMEM();

@CFunction
public static native CCharPointer strerror(int errnum);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.graalvm.nativeimage.c.function.CLibrary;
import org.graalvm.nativeimage.c.struct.CPointerTo;
import org.graalvm.nativeimage.c.struct.CStruct;
import org.graalvm.nativeimage.c.type.VoidPointer;
import org.graalvm.nativeimage.c.type.WordPointer;
import org.graalvm.word.PointerBase;
import org.graalvm.word.UnsignedWord;
Expand Down Expand Up @@ -77,6 +78,17 @@ public interface pthread_cond_t extends PointerBase {
public interface pthread_condattr_t extends PointerBase {
}

public interface pthread_key_t extends UnsignedWord {
}

@CPointerTo(nameOfCType = "size_t")
public interface pthread_key_tPointer extends PointerBase {
pthread_key_t read();
}

@CConstant
public static native int PTHREAD_KEYS_MAX();

@CConstant
public static native int PTHREAD_CREATE_JOINABLE();

Expand Down Expand Up @@ -161,4 +173,13 @@ public interface pthread_condattr_t extends PointerBase {

@CFunction
public static native int pthread_kill(pthread_t thread, Signal.SignalEnum sig);

@CFunction(transition = Transition.NO_TRANSITION)
public static native int pthread_key_create(pthread_key_tPointer key, PointerBase keyDestructor);

@CFunction(transition = Transition.NO_TRANSITION)
public static native int pthread_setspecific(pthread_key_t key, VoidPointer value);

@CFunction(transition = Transition.NO_TRANSITION)
public static native VoidPointer pthread_getspecific(pthread_key_t key);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@
package com.oracle.svm.core.posix.headers;

import org.graalvm.nativeimage.c.CContext;
import org.graalvm.nativeimage.c.constant.CEnum;
import org.graalvm.nativeimage.c.constant.CEnumValue;
import org.graalvm.nativeimage.c.function.CFunction;
import org.graalvm.nativeimage.c.function.CFunction.Transition;
import org.graalvm.nativeimage.c.struct.AllowNarrowingCast;
import org.graalvm.nativeimage.c.struct.AllowWideningCast;
import org.graalvm.nativeimage.c.struct.CField;
import org.graalvm.nativeimage.c.struct.CFieldAddress;
import org.graalvm.nativeimage.c.struct.CStruct;
import org.graalvm.word.PointerBase;

Expand Down Expand Up @@ -78,7 +81,33 @@ public interface timespec extends PointerBase {
void set_tv_nsec(long value);
}

@CStruct(addStructKeyword = true)
public interface itimerval extends PointerBase {
@CFieldAddress
timeval it_interval();

@CFieldAddress
timeval it_value();
}

@CEnum
@CContext(PosixDirectives.class)
public enum TimerTypeEnum {
ITIMER_REAL,
ITIMER_VIRTUAL,
ITIMER_PROF;

@CEnumValue
public native int getCValue();
}

public static class NoTransitions {
/**
* @param which from {@link TimerTypeEnum#getCValue()}
*/
@CFunction(transition = CFunction.Transition.NO_TRANSITION)
public static native int setitimer(TimerTypeEnum which, itimerval newValue, itimerval oldValue);

@CFunction(transition = CFunction.Transition.NO_TRANSITION)
public static native int gettimeofday(timeval tv, timezone tz);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,13 @@ public PointerBase getThreadPointer(Context context) {
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public PointerBase getSP(Context context) {
return WordFactory.pointer(((CONTEXT) context).Rsp());
}

@Override
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public PointerBase getIP(Context context) {
return WordFactory.pointer(((CONTEXT) context).Rip());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,6 @@ public static <T> void setObject(NonmovableObjectArray<T> array, int index, T va
/**
* Visits all array elements with the provided {@link ObjectReferenceVisitor}.
*/
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true, calleeMustBe = false)
public static boolean walkUnmanagedObjectArray(NonmovableObjectArray<?> array, ObjectReferenceVisitor visitor) {
if (array.isNonNull()) {
return walkUnmanagedObjectArray(array, visitor, 0, lengthOf(array));
Expand All @@ -454,7 +453,6 @@ public static boolean walkUnmanagedObjectArray(NonmovableObjectArray<?> array, O
/**
* Visits all array elements with the provided {@link ObjectReferenceVisitor}.
*/
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true, calleeMustBe = false)
public static boolean walkUnmanagedObjectArray(NonmovableObjectArray<?> array, ObjectReferenceVisitor visitor, int startIndex, int count) {
if (array.isNonNull()) {
assert startIndex >= 0 && count <= lengthOf(array) - startIndex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ public static void lookupCodeInfo(CodeInfo info, long ip, CodeInfoQueryResult co
CodeInfoDecoder.lookupCodeInfo(info, ip, codeInfoQueryResult);
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static void lookupCodeInfo(CodeInfo info, long ip, SimpleCodeInfoQueryResult codeInfoQueryResult) {
CodeInfoDecoder.lookupCodeInfo(info, ip, codeInfoQueryResult);
}
Expand Down Expand Up @@ -371,10 +372,12 @@ static CodePointer getCodeEnd(CodeInfo info) {
return (CodePointer) ((UnsignedWord) impl.getCodeStart()).add(impl.getCodeSize());
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static NonmovableArray<Byte> getCodeInfoIndex(CodeInfo info) {
return cast(info).getCodeInfoIndex();
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static NonmovableArray<Byte> getCodeInfoEncodings(CodeInfo info) {
return cast(info).getCodeInfoEncodings();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import com.oracle.svm.core.annotate.Uninterruptible;
import com.oracle.svm.core.heap.ReferenceMapIndex;
import com.oracle.svm.core.option.HostedOptionKey;
import com.oracle.svm.core.util.ByteArrayReader;
import com.oracle.svm.core.util.Counter;
import com.oracle.svm.core.util.NonmovableByteArrayReader;

Expand Down Expand Up @@ -114,6 +113,7 @@ static void lookupCodeInfo(CodeInfo info, long ip, CodeInfoQueryResult codeInfoQ
codeInfoQueryResult.frameInfo = CodeInfoQueryResult.NO_FRAME_INFO;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
static void lookupCodeInfo(CodeInfo info, long ip, SimpleCodeInfoQueryResult codeInfoQueryResult) {
long sizeEncoding = initialSizeEncoding();
long entryIP = lookupEntryIP(ip);
Expand Down Expand Up @@ -200,33 +200,39 @@ static long lookupStackReferenceMapIndex(CodeInfo info, long ip) {
return ReferenceMapIndex.NO_REFERENCE_MAP;
}

@Fold
static long indexGranularity() {
return Options.CodeInfoIndexGranularity.getValue();
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
static long lookupEntryIP(long ip) {
return Long.divideUnsigned(ip, indexGranularity()) * indexGranularity();
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long loadEntryOffset(CodeInfo info, long ip) {
counters().lookupEntryOffsetCount.inc();
long index = Long.divideUnsigned(ip, indexGranularity());
return NonmovableByteArrayReader.getU4(CodeInfoAccess.getCodeInfoIndex(info), index * Integer.BYTES);
}

@AlwaysInline("Make IP-lookup loop call free")
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
static int loadEntryFlags(CodeInfo info, long curOffset) {
counters().loadEntryFlagsCount.inc();
return NonmovableByteArrayReader.getU1(CodeInfoAccess.getCodeInfoEncodings(info), curOffset);
}

private static final int INVALID_SIZE_ENCODING = 0;

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static int initialSizeEncoding() {
return INVALID_SIZE_ENCODING;
}

@AlwaysInline("Make IP-lookup loop call free")
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long updateSizeEncoding(CodeInfo info, long entryOffset, int entryFlags, long sizeEncoding) {
switch (extractFS(entryFlags)) {
case FS_NO_CHANGE:
Expand All @@ -242,6 +248,7 @@ private static long updateSizeEncoding(CodeInfo info, long entryOffset, int entr
}
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long loadExceptionOffset(CodeInfo info, long entryOffset, int entryFlags) {
switch (extractEX(entryFlags)) {
case EX_NO_HANDLER:
Expand All @@ -257,6 +264,7 @@ private static long loadExceptionOffset(CodeInfo info, long entryOffset, int ent
}
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long loadReferenceMapIndex(CodeInfo info, long entryOffset, int entryFlags) {
switch (extractRM(entryFlags)) {
case RM_NO_MAP:
Expand Down Expand Up @@ -359,6 +367,7 @@ private static FrameInfoQueryResult loadFrameInfo(CodeInfo info, long entryOffse
}

@AlwaysInline("Make IP-lookup loop call free")
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long advanceIP(CodeInfo info, long entryOffset, long entryIP) {
int deltaIP = NonmovableByteArrayReader.getU1(CodeInfoAccess.getCodeInfoEncodings(info), offsetIP(entryOffset));
if (deltaIP == DELTA_END_OF_TABLE) {
Expand Down Expand Up @@ -441,14 +450,17 @@ private static boolean endOfTable(long entryIP) {
}
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
static int extractFS(int entryFlags) {
return (entryFlags & FS_MASK_IN_PLACE) >> FS_SHIFT;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
static int extractEX(int entryFlags) {
return (entryFlags & EX_MASK_IN_PLACE) >> EX_SHIFT;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
static int extractRM(int entryFlags) {
return (entryFlags & RM_MASK_IN_PLACE) >> RM_SHIFT;
}
Expand All @@ -457,34 +469,44 @@ static int extractFI(int entryFlags) {
return (entryFlags & FI_MASK_IN_PLACE) >> FI_SHIFT;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long offsetIP(long entryOffset) {
return entryOffset + IP_OFFSET;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long offsetFS(long entryOffset, int entryFlags) {
assert extractFS(entryFlags) != FS_NO_CHANGE;
return entryOffset + FS_OFFSET;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long getU1(byte[] data, long byteIndex) {
return data[(int) byteIndex] & 0xFF;
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long offsetEX(long entryOffset, int entryFlags) {
assert extractEX(entryFlags) != EX_NO_HANDLER;
return entryOffset + ByteArrayReader.getU1(EX_OFFSET, entryFlags);
return entryOffset + getU1(EX_OFFSET, entryFlags);
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long offsetRM(long entryOffset, int entryFlags) {
assert extractRM(entryFlags) != RM_NO_MAP && extractRM(entryFlags) != RM_EMPTY_MAP;
return entryOffset + ByteArrayReader.getU1(RM_OFFSET, entryFlags);
return entryOffset + getU1(RM_OFFSET, entryFlags);
}

private static long offsetFI(long entryOffset, int entryFlags) {
assert extractFI(entryFlags) != FI_NO_DEOPT;
return entryOffset + ByteArrayReader.getU1(FI_OFFSET, entryFlags);
return entryOffset + getU1(FI_OFFSET, entryFlags);
}

@AlwaysInline("Make IP-lookup loop call free")
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private static long advanceOffset(long entryOffset, int entryFlags) {
counters().advanceOffset.inc();
return entryOffset + ByteArrayReader.getU1(MEM_SIZE, entryFlags);
return entryOffset + getU1(MEM_SIZE, entryFlags);
}

@Fold
Expand Down
Loading

0 comments on commit 3fc931b

Please sign in to comment.