Skip to content

Commit

Permalink
Fix slp_switch on SPARC for multi-threaded environments
Browse files Browse the repository at this point in the history
The CLEAN_WINDOWS trap was wrongly removed previously.  It is not
required in a single-threaded environment but does need to be present
for the switching code to not mess up the register windows in a multi-
threaded environment.
  • Loading branch information
flub committed Sep 2, 2013
1 parent 2030b42 commit 3b03825
Showing 1 changed file with 25 additions and 7 deletions.
32 changes: 25 additions & 7 deletions platform/switch_sparc_sun_gcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
* this is the internal transfer function.
*
* HISTORY
* 30-Aug-13 Floris Bruynooghe <[email protected]>
Clean the register windows again before returning.
This does not clobber the PIC register as it leaves
the current window intact and is required for multi-
threaded code to work correctly.
* 08-Mar-11 Floris Bruynooghe <[email protected]>
* No need to set return value register explicitly
* before the stack and framepointer are adjusted
Expand All @@ -28,7 +33,8 @@


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

static int
slp_switch(void)
Expand All @@ -37,7 +43,17 @@ slp_switch(void)

/* 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. Then put the stack pointer into stackref. */
* 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"
Expand All @@ -57,11 +73,13 @@ slp_switch(void)
/* Copy new stack from it's save store on the heap */
SLP_RESTORE_STATE();

/* No need to restore any registers from the stack nor clear them: the
* frame pointer has just been set and the return value register is
* also being set by the return statement below. After returning a
* restore instruction is given and the frame below us will load all
* it's registers using a fill_trap if required. */
/* 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));

return 0;
}
Expand Down

0 comments on commit 3b03825

Please sign in to comment.