Skip to content

Commit

Permalink
Try to fix stack switching on sparc
Browse files Browse the repository at this point in the history
  • Loading branch information
snaury committed May 10, 2015
1 parent 80b5b33 commit 081fd2e
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 26 deletions.
14 changes: 14 additions & 0 deletions greenlet.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,13 @@ static void GREENLET_NOINLINE(slp_restore_state)(void)
PyGreenlet* g = ts_target;
PyGreenlet* owner = ts_current;

/* On sparc we need to spill register windows */
#if defined(__sparcv9)
__asm__ volatile ("flushw");
#elif defined(sparc)
__asm__ volatile ("ta 3"); /* ST_FLUSH_WINDOWS */
#endif

/* Restore the heap copy back into the C stack */
if (g->stack_saved != 0) {
memcpy(g->stack_start, g->stack_copy, g->stack_saved);
Expand All @@ -366,6 +373,13 @@ static int GREENLET_NOINLINE(slp_save_state)(char* stackref)
else
owner->stack_start = stackref;

/* On sparc we need to spill register windows */
#if defined(__sparcv9)
__asm__ volatile ("flushw");
#elif defined(sparc)
__asm__ volatile ("ta 3"); /* ST_FLUSH_WINDOWS */
#endif

while (owner->stack_stop < target_stop) {
/* ts_current is entierely within the area to free */
if (g_save(owner, owner->stack_stop))
Expand Down
31 changes: 5 additions & 26 deletions platform/switch_sparc_sun_gcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,32 +33,18 @@


#define STACK_MAGIC 0
#define ST_FLUSH_WINDOWS 0x03
#define ST_CLEAN_WINDOWS 0x04


static int
slp_switch(void)
{
register int err;
register int *stackref, stsizediff;

/* Flush SPARC register windows onto the stack, so they can be used to
* restore the registers after the stack has been switched out and
* restored. This also ensures the current window (pointed at by
* the CWP register) is the only window left in the registers
* (CANSAVE=0, CANRESTORE=0), that means the registers of our
* caller are no longer there and when we return they will always
* be loaded from the stack by a window underflow/fill trap.
*
* On SPARC v9 and above it might be more efficient to use the
* FLUSHW instruction instead of TA ST_FLUSH_WINDOWS. But that
* requires the correct -mcpu flag to gcc.
*
* Then put the stack pointer into stackref. */
__asm__ volatile (
"ta %1\n\t"
"mov %%sp, %0"
: "=r" (stackref) : "i" (ST_FLUSH_WINDOWS));
/* Put current stack pointer into stackref.
* Register spilling is done in save/restore.
*/
__asm__ volatile ("mov %%sp, %0" : "=r" (stackref));

{
/* Thou shalt put SLP_SAVE_STATE into a local block */
Expand All @@ -74,13 +60,6 @@ slp_switch(void)
/* Copy new stack from it's save store on the heap */
SLP_RESTORE_STATE();

/* No need to set the return value register, the return
* statement below does this just fine. After returning a restore
* instruction is given and a fill-trap will load all the registers
* from the stack if needed. However in a multi-threaded environment
* we can't guarantee the other register windows are fine to use by
* their threads anymore, so tell the CPU to clean them. */
__asm__ volatile ("ta %0" : : "i" (ST_CLEAN_WINDOWS));
__asm__ volatile ("mov %1, %0" : "=r" (err) : "i" (0));
return err;
}
Expand Down

0 comments on commit 081fd2e

Please sign in to comment.