1 The following patch comes from the upstream 0.4.2 distribution and |
|
2 addresses the stated problem. It will be removed here once we update to |
|
3 a later version of greenlet. |
|
4 |
|
5 commit 3b03825089384f86842032ec1476ad3031908d43 |
|
6 Author: Floris Bruynooghe <[email protected]> |
|
7 Date: Mon Sep 2 10:25:14 2013 +0100 |
|
8 |
|
9 Fix slp_switch on SPARC for multi-threaded environments |
|
10 |
|
11 The CLEAN_WINDOWS trap was wrongly removed previously. It is not |
|
12 required in a single-threaded environment but does need to be present |
|
13 for the switching code to not mess up the register windows in a multi- |
|
14 threaded environment. |
|
15 |
|
16 diff --git a/platform/switch_sparc_sun_gcc.h b/platform/switch_sparc_sun_gcc.h |
|
17 index 1f701a2..5c67205 100644 |
|
18 --- a/platform/switch_sparc_sun_gcc.h |
|
19 +++ b/platform/switch_sparc_sun_gcc.h |
|
20 @@ -2,6 +2,11 @@ |
|
21 * this is the internal transfer function. |
|
22 * |
|
23 * HISTORY |
|
24 + * 30-Aug-13 Floris Bruynooghe <[email protected]> |
|
25 + Clean the register windows again before returning. |
|
26 + This does not clobber the PIC register as it leaves |
|
27 + the current window intact and is required for multi- |
|
28 + threaded code to work correctly. |
|
29 * 08-Mar-11 Floris Bruynooghe <[email protected]> |
|
30 * No need to set return value register explicitly |
|
31 * before the stack and framepointer are adjusted |
|
32 @@ -28,7 +33,8 @@ |
|
33 |
|
34 |
|
35 #define STACK_MAGIC 0 |
|
36 -#define ST_FLUSH_WINDOWS 3 |
|
37 +#define ST_FLUSH_WINDOWS 0x03 |
|
38 +#define ST_CLEAN_WINDOWS 0x04 |
|
39 |
|
40 static int |
|
41 slp_switch(void) |
|
42 @@ -37,7 +43,17 @@ slp_switch(void) |
|
43 |
|
44 /* Flush SPARC register windows onto the stack, so they can be used to |
|
45 * restore the registers after the stack has been switched out and |
|
46 - * restored. Then put the stack pointer into stackref. */ |
|
47 + * restored. This also ensures the current window (pointed at by |
|
48 + * the CWP register) is the only window left in the registers |
|
49 + * (CANSAVE=0, CANRESTORE=0), that means the registers of our |
|
50 + * caller are no longer there and when we return they will always |
|
51 + * be loaded from the stack by a window underflow/fill trap. |
|
52 + * |
|
53 + * On SPARC v9 and above it might be more efficient to use the |
|
54 + * FLUSHW instruction instead of TA ST_FLUSH_WINDOWS. But that |
|
55 + * requires the correct -mcpu flag to gcc. |
|
56 + * |
|
57 + * Then put the stack pointer into stackref. */ |
|
58 __asm__ volatile ( |
|
59 "ta %1\n\t" |
|
60 "mov %%sp, %0" |
|
61 @@ -57,11 +73,13 @@ slp_switch(void) |
|
62 /* Copy new stack from it's save store on the heap */ |
|
63 SLP_RESTORE_STATE(); |
|
64 |
|
65 - /* No need to restore any registers from the stack nor clear them: the |
|
66 - * frame pointer has just been set and the return value register is |
|
67 - * also being set by the return statement below. After returning a |
|
68 - * restore instruction is given and the frame below us will load all |
|
69 - * it's registers using a fill_trap if required. */ |
|
70 + /* No need to set the return value register, the return |
|
71 + * statement below does this just fine. After returning a restore |
|
72 + * instruction is given and a fill-trap will load all the registers |
|
73 + * from the stack if needed. However in a multi-threaded environment |
|
74 + * we can't guarantee the other register windows are fine to use by |
|
75 + * their threads anymore, so tell the CPU to clean them. */ |
|
76 + __asm__ volatile ("ta %0" : : "i" (ST_CLEAN_WINDOWS)); |
|
77 |
|
78 return 0; |
|
79 } |
|
80 |
|