Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Merge pull request #195 from alexrp/call-with-stack-shell
Browse files Browse the repository at this point in the history
Expose a thread_callWithStackShell() function.
  • Loading branch information
complexmath committed Apr 23, 2012
2 parents f544545 + b6711a4 commit 88ca7b2
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 159 deletions.
188 changes: 108 additions & 80 deletions src/core/thread.d
Expand Up @@ -488,49 +488,11 @@ else version( Posix )
}
body
{
version( D_InlineAsm_X86 )
{
asm
{
pushad;
}
}
else version ( D_InlineAsm_X86_64 )
{
asm
{
// Not sure what goes here, pushad is invalid in 64 bit code
push RAX ;
push RBX ;
push RCX ;
push RDX ;
push RSI ;
push RDI ;
push RBP ;
push R8 ;
push R9 ;
push R10 ;
push R11 ;
push R12 ;
push R13 ;
push R14 ;
push R15 ;
push RAX ; // 16 byte align the stack
}
}
else version( GNU )
{
__builtin_unwind_init();
}
else
{
static assert( false, "Architecture not supported." );
}

// NOTE: Since registers are being pushed and popped from the
// stack, any other stack data used by this function should
// be gone before the stack cleanup code is called below.
void op(void* sp)
{
// NOTE: Since registers are being pushed and popped from the
// stack, any other stack data used by this function should
// be gone before the stack cleanup code is called below.
Thread obj = Thread.getThis();

// NOTE: The thread reference returned by getThis is set within
Expand Down Expand Up @@ -564,44 +526,7 @@ else version( Posix )
}
}

version( D_InlineAsm_X86 )
{
asm
{
popad;
}
}
else version ( D_InlineAsm_X86_64 )
{
asm
{
// Not sure what goes here, popad is invalid in 64 bit code
pop RAX ; // 16 byte align the stack
pop R15 ;
pop R14 ;
pop R13 ;
pop R12 ;
pop R11 ;
pop R10 ;
pop R9 ;
pop R8 ;
pop RBP ;
pop RDI ;
pop RSI ;
pop RDX ;
pop RCX ;
pop RBX ;
pop RAX ;
}
}
else version( GNU )
{
// registers will be popped automatically
}
else
{
static assert( false, "Architecture not supported." );
}
thread_callWithStackShell(&op);
}


Expand Down Expand Up @@ -2251,6 +2176,109 @@ extern (C) bool thread_needLock() nothrow
}


alias void delegate(void*) StackShellFn;

/**
* Calls the given delegate, passing the current thread's stack pointer
* to it.
*
* Params:
* fn = The function to call with the stack pointer.
*/
extern (C) void thread_callWithStackShell(scope StackShellFn fn)
in
{
assert(fn);
}
body
{
// The purpose of the 'shell' is to ensure all the registers
// get put on the stack so they'll be scanned
void *sp;

version (GNU)
{
__builtin_unwind_init();
sp = & sp;
}
else version (D_InlineAsm_X86)
{
asm
{
pushad ;
mov sp[EBP],ESP ;
}
}
else version (D_InlineAsm_X86_64)
{
asm
{
push RAX ;
push RBX ;
push RCX ;
push RDX ;
push RSI ;
push RDI ;
push RBP ;
push R8 ;
push R9 ;
push R10 ;
push R11 ;
push R12 ;
push R13 ;
push R14 ;
push R15 ;
push RAX ; // 16 byte align the stack
mov sp[RBP],RSP ;
}
}
else
{
static assert(false, "Architecture not supported.");
}

fn(sp);

version (GNU)
{
// registers will be popped automatically
}
else version (D_InlineAsm_X86)
{
asm
{
popad;
}
}
else version (D_InlineAsm_X86_64)
{
asm
{
pop RAX ; // 16 byte align the stack
pop R15 ;
pop R14 ;
pop R13 ;
pop R12 ;
pop R11 ;
pop R10 ;
pop R9 ;
pop R8 ;
pop RBP ;
pop RDI ;
pop RSI ;
pop RDX ;
pop RCX ;
pop RBX ;
pop RAX ;
}
}
else
{
static assert(false, "Architecture not supported.");
}
}


// Used for suspendAll/resumeAll below.
private __gshared uint suspendDepth = 0;

Expand Down
12 changes: 12 additions & 0 deletions src/core/thread.di
Expand Up @@ -549,6 +549,18 @@ shared static ~this();
extern (C) bool thread_needLock() nothrow;


alias void delegate(void*) StackShellFn;

/**
* Calls the given delegate, passing the current thread's stack pointer
* to it.
*
* Params:
* fn = The function to call with the stack pointer.
*/
extern (C) void thread_callWithStackShell(scope StackShellFn fn);


/**
* Suspend all threads but the calling thread for "stop the world" garbage
* collection runs. This function may be called multiple times, and must
Expand Down
86 changes: 7 additions & 79 deletions src/gc/gcx.d
Expand Up @@ -122,6 +122,9 @@ private

alias void delegate(void*, void*) scanFn;
extern (C) void thread_scanAll(scope scanFn fn, void* curStackTop = null);

alias void delegate(void*) StackShellFn;
extern (C) void thread_callWithStackShell(scope StackShellFn fn);
}

extern (C) void onOutOfMemoryError();
Expand Down Expand Up @@ -2614,90 +2617,15 @@ struct Gcx
*/
size_t fullcollectshell()
{
// The purpose of the 'shell' is to ensure all the registers
// get put on the stack so they'll be scanned
void *sp;
size_t result;
version (GNU)
{
__builtin_unwind_init();
sp = & sp;
}
else version (D_InlineAsm_X86)
{
asm
{
pushad ;
mov sp[EBP],ESP ;
}
}
else version (D_InlineAsm_X86_64)
{
asm
{
push RAX ;
push RBX ;
push RCX ;
push RDX ;
push RSI ;
push RDI ;
push RBP ;
push R8 ;
push R9 ;
push R10 ;
push R11 ;
push R12 ;
push R13 ;
push R14 ;
push R15 ;
push RAX ; // 16 byte align the stack
mov sp[RBP],RSP ;
}
}
else

void op(void* sp)
{
static assert(false, "Architecture not supported.");
result = fullcollect(sp);
}

result = fullcollect(sp);
thread_callWithStackShell(&op);

version (GNU)
{
// registers will be popped automatically
}
else version (D_InlineAsm_X86)
{
asm
{
popad;
}
}
else version (D_InlineAsm_X86_64)
{
asm
{
pop RAX ; // 16 byte align the stack
pop R15 ;
pop R14 ;
pop R13 ;
pop R12 ;
pop R11 ;
pop R10 ;
pop R9 ;
pop R8 ;
pop RBP ;
pop RDI ;
pop RSI ;
pop RDX ;
pop RCX ;
pop RBX ;
pop RAX ;
}
}
else
{
static assert(false, "Architecture not supported.");
}
return result;
}

Expand Down

0 comments on commit 88ca7b2

Please sign in to comment.