Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
320 changes: 2 additions & 318 deletions druntime/src/core/thread/osthread.d
Original file line number Diff line number Diff line change
Expand Up @@ -941,16 +941,10 @@ in (fn)
* writefln("Current process id: %s", getpid());
* ---
*/
version (Posix)
{
alias getpid = imported!"core.sys.posix.unistd".getpid;
}
else version (Windows)
version (CoreDdoc)
{
alias getpid = imported!"core.sys.windows.winbase".GetCurrentProcessId;
size_t getpid() nothrow @nogc { return 0; }

@denizzzka denizzzka Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what return type to put here because implementation may be different for different platforms, so I wrote size_t

}
else
static assert(0, "unsupported os");

extern (C) @nogc nothrow
{
Expand Down Expand Up @@ -1111,316 +1105,6 @@ private extern (D) bool suspend( Thread t ) nothrow @nogc
return true;
}

private void loadStackAndRegInfo(Thread t, const bool sameThread) nothrow @nogc
{
version (Windows)
{
CONTEXT context = void;
context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;

if ( !GetThreadContext( t.m_tdescr.hndl, &context ) )
onThreadError( "Unable to load thread context" );
version (X86)
{
if ( !t.m_lock )
t.m_curr.tstack = cast(void*) context.Esp;
// eax,ebx,ecx,edx,edi,esi,ebp,esp
t.m_reg[0] = context.Eax;
t.m_reg[1] = context.Ebx;
t.m_reg[2] = context.Ecx;
t.m_reg[3] = context.Edx;
t.m_reg[4] = context.Edi;
t.m_reg[5] = context.Esi;
t.m_reg[6] = context.Ebp;
t.m_reg[7] = context.Esp;
}
else version (X86_64)
{
if ( !t.m_lock )
t.m_curr.tstack = cast(void*) context.Rsp;
// rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp
t.m_reg[0] = context.Rax;
t.m_reg[1] = context.Rbx;
t.m_reg[2] = context.Rcx;
t.m_reg[3] = context.Rdx;
t.m_reg[4] = context.Rdi;
t.m_reg[5] = context.Rsi;
t.m_reg[6] = context.Rbp;
t.m_reg[7] = context.Rsp;
// r8,r9,r10,r11,r12,r13,r14,r15
t.m_reg[8] = context.R8;
t.m_reg[9] = context.R9;
t.m_reg[10] = context.R10;
t.m_reg[11] = context.R11;
t.m_reg[12] = context.R12;
t.m_reg[13] = context.R13;
t.m_reg[14] = context.R14;
t.m_reg[15] = context.R15;
}
else
{
static assert(false, "Architecture not supported." );
}
// a thread might change the stack, e.g. using non-D fibers, so we must not
// rely on the stack bottom saved when attaching/starting. Multiple fiber stacks cannot be
// captured, but make sure scanning does not crash accessing invalid memory ranges
// between stacks
if ( !t.m_lock )
t.m_curr.bstack = getThreadStackBottom( t.m_tdescr.hndl );
}
else version (Darwin)
{
version (X86)
{
x86_thread_state32_t state = void;
mach_msg_type_number_t count = x86_THREAD_STATE32_COUNT;

if ( thread_get_state( t.m_tdescr.tmach, x86_THREAD_STATE32, &state, &count ) != KERN_SUCCESS )
onThreadError( "Unable to load thread state" );
if ( !t.m_lock )
t.m_curr.tstack = cast(void*) state.esp;
// eax,ebx,ecx,edx,edi,esi,ebp,esp
t.m_reg[0] = state.eax;
t.m_reg[1] = state.ebx;
t.m_reg[2] = state.ecx;
t.m_reg[3] = state.edx;
t.m_reg[4] = state.edi;
t.m_reg[5] = state.esi;
t.m_reg[6] = state.ebp;
t.m_reg[7] = state.esp;
}
else version (X86_64)
{
x86_thread_state64_t state = void;
mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;

if ( thread_get_state( t.m_tdescr.tmach, x86_THREAD_STATE64, &state, &count ) != KERN_SUCCESS )
onThreadError( "Unable to load thread state" );
if ( !t.m_lock )
t.m_curr.tstack = cast(void*) state.rsp;
// rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp
t.m_reg[0] = state.rax;
t.m_reg[1] = state.rbx;
t.m_reg[2] = state.rcx;
t.m_reg[3] = state.rdx;
t.m_reg[4] = state.rdi;
t.m_reg[5] = state.rsi;
t.m_reg[6] = state.rbp;
t.m_reg[7] = state.rsp;
// r8,r9,r10,r11,r12,r13,r14,r15
t.m_reg[8] = state.r8;
t.m_reg[9] = state.r9;
t.m_reg[10] = state.r10;
t.m_reg[11] = state.r11;
t.m_reg[12] = state.r12;
t.m_reg[13] = state.r13;
t.m_reg[14] = state.r14;
t.m_reg[15] = state.r15;
}
else version (AArch64)
{
arm_thread_state64_t state = void;
mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT;

if (thread_get_state(t.m_tdescr.tmach, ARM_THREAD_STATE64, &state, &count) != KERN_SUCCESS)
onThreadError("Unable to load thread state");
// TODO: ThreadException here recurses forever! Does it
//still using onThreadError?
//printf("state count %d (expect %d)\n", count ,ARM_THREAD_STATE64_COUNT);
if (!t.m_lock)
t.m_curr.tstack = cast(void*) state.sp;

t.m_reg[0..29] = state.x; // x0-x28
t.m_reg[29] = state.fp; // x29
t.m_reg[30] = state.lr; // x30
t.m_reg[31] = state.sp; // x31
t.m_reg[32] = state.pc;
}
else version (ARM)
{
arm_thread_state32_t state = void;
mach_msg_type_number_t count = ARM_THREAD_STATE32_COUNT;

// Thought this would be ARM_THREAD_STATE32, but that fails.
// Mystery
if (thread_get_state(t.m_tdescr.tmach, ARM_THREAD_STATE, &state, &count) != KERN_SUCCESS)
onThreadError("Unable to load thread state");
// TODO: in past, ThreadException here recurses forever! Does it
//still using onThreadError?
//printf("state count %d (expect %d)\n", count ,ARM_THREAD_STATE32_COUNT);
if (!t.m_lock)
t.m_curr.tstack = cast(void*) state.sp;

t.m_reg[0..13] = state.r; // r0 - r13
t.m_reg[13] = state.sp;
t.m_reg[14] = state.lr;
t.m_reg[15] = state.pc;
}
else version (PPC)
{
ppc_thread_state_t state = void;
mach_msg_type_number_t count = PPC_THREAD_STATE_COUNT;

if (thread_get_state(t.m_tdescr.tmach, PPC_THREAD_STATE, &state, &count) != KERN_SUCCESS)
onThreadError("Unable to load thread state");
if (!t.m_lock)
t.m_curr.tstack = cast(void*) state.r[1];
t.m_reg[] = state.r[];
}
else version (PPC64)
{
ppc_thread_state64_t state = void;
mach_msg_type_number_t count = PPC_THREAD_STATE64_COUNT;

if (thread_get_state(t.m_tdescr.tmach, PPC_THREAD_STATE64, &state, &count) != KERN_SUCCESS)
onThreadError("Unable to load thread state");
if (!t.m_lock)
t.m_curr.tstack = cast(void*) state.r[1];
t.m_reg[] = state.r[];
}
else
{
static assert(false, "Architecture not supported." );
}
}
else version (Solaris)
{
if (!sameThread)
{
static int getLwpStatus(ulong lwpid, out lwpstatus_t status)
{
import core.sys.posix.fcntl : open, O_RDONLY;
import core.sys.posix.unistd : pread, close;
import core.internal.string : unsignedToTempString;

char[100] path = void;
auto pslice = path[0 .. $];
immutable n = unsignedToTempString(lwpid);
immutable ndigits = n.length;

// Construct path "/proc/self/lwp/%u/lwpstatus"
pslice[0 .. 15] = "/proc/self/lwp/";
pslice = pslice[15 .. $];
pslice[0 .. ndigits] = n[];
pslice = pslice[ndigits .. $];
pslice[0 .. 10] = "/lwpstatus";
pslice[10] = '\0';

// Read in lwpstatus data
int fd = open(path.ptr, O_RDONLY, 0);
if (fd >= 0)
{
while (pread(fd, &status, status.sizeof, 0) == status.sizeof)
{
// Should only attempt to read the thread state once it
// has been stopped by thr_suspend
if (status.pr_flags & PR_STOPPED)
{
close(fd);
return 0;
}
// Give it a chance to stop
thread_yield();
}
close(fd);
}
return -1;
}

lwpstatus_t status = void;
if (getLwpStatus(t.m_tdescr.tid, status) != 0)
onThreadError("Unable to load thread state");

version (X86)
{
import core.sys.solaris.sys.regset; // REG_xxx

if (!t.m_lock)
t.m_curr.tstack = cast(void*) status.pr_reg[REG_ESP];
// eax,ebx,ecx,edx,edi,esi,ebp,esp
t.m_reg[0] = status.pr_reg[REG_EAX];
t.m_reg[1] = status.pr_reg[REG_EBX];
t.m_reg[2] = status.pr_reg[REG_ECX];
t.m_reg[3] = status.pr_reg[REG_EDX];
t.m_reg[4] = status.pr_reg[REG_EDI];
t.m_reg[5] = status.pr_reg[REG_ESI];
t.m_reg[6] = status.pr_reg[REG_EBP];
t.m_reg[7] = status.pr_reg[REG_ESP];
}
else version (X86_64)
{
import core.sys.solaris.sys.regset; // REG_xxx

if (!t.m_lock)
t.m_curr.tstack = cast(void*) status.pr_reg[REG_RSP];
// rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp
t.m_reg[0] = status.pr_reg[REG_RAX];
t.m_reg[1] = status.pr_reg[REG_RBX];
t.m_reg[2] = status.pr_reg[REG_RCX];
t.m_reg[3] = status.pr_reg[REG_RDX];
t.m_reg[4] = status.pr_reg[REG_RDI];
t.m_reg[5] = status.pr_reg[REG_RSI];
t.m_reg[6] = status.pr_reg[REG_RBP];
t.m_reg[7] = status.pr_reg[REG_RSP];
// r8,r9,r10,r11,r12,r13,r14,r15
t.m_reg[8] = status.pr_reg[REG_R8];
t.m_reg[9] = status.pr_reg[REG_R9];
t.m_reg[10] = status.pr_reg[REG_R10];
t.m_reg[11] = status.pr_reg[REG_R11];
t.m_reg[12] = status.pr_reg[REG_R12];
t.m_reg[13] = status.pr_reg[REG_R13];
t.m_reg[14] = status.pr_reg[REG_R14];
t.m_reg[15] = status.pr_reg[REG_R15];
}
else version (SPARC)
{
import core.sys.solaris.sys.procfs : R_SP, R_PC;

if (!t.m_lock)
t.m_curr.tstack = cast(void*) status.pr_reg[R_SP];
// g0..g7, o0..o7, l0..l7, i0..i7
t.m_reg[0 .. 32] = status.pr_reg[0 .. 32];
// pc
t.m_reg[32] = status.pr_reg[R_PC];
}
else version (SPARC64)
{
import core.sys.solaris.sys.procfs : R_SP, R_PC;

if (!t.m_lock)
{
// SPARC V9 has a stack bias of 2047 bytes which must be added to get
// the actual data of the stack frame.
auto tstack = status.pr_reg[R_SP] + 2047;
assert(tstack % 16 == 0);
t.m_curr.tstack = cast(void*) tstack;
}
// g0..g7, o0..o7, l0..l7, i0..i7
t.m_reg[0 .. 32] = status.pr_reg[0 .. 32];
// pc
t.m_reg[32] = status.pr_reg[R_PC];
}
else
{
static assert(false, "Architecture not supported.");
}
}
else if (!t.m_lock)
{
t.m_curr.tstack = getStackTop();
}
}
else version (Posix)
{
if (sameThread && !t.m_lock)
{
t.m_curr.tstack = getStackTop();
}
}
else
static assert(0, "unsupported os");
}

/**
* Runs the necessary operations required before stopping the world.
*/
Expand Down
Loading
Loading