diff options
Diffstat (limited to 'cpukit/score/cpu/i386')
-rw-r--r-- | cpukit/score/cpu/i386/cpu.c | 18 | ||||
-rw-r--r-- | cpukit/score/cpu/i386/cpu_asm.S | 29 | ||||
-rw-r--r-- | cpukit/score/cpu/i386/rtems/score/cpu.h | 27 |
3 files changed, 67 insertions, 7 deletions
diff --git a/cpukit/score/cpu/i386/cpu.c b/cpukit/score/cpu/i386/cpu.c index ba7501a246..38b84e6750 100644 --- a/cpukit/score/cpu/i386/cpu.c +++ b/cpukit/score/cpu/i386/cpu.c @@ -26,6 +26,24 @@ #include <rtems/bspIo.h> #include <rtems/score/thread.h> +#define I386_ASSERT_OFFSET(field, off) \ + RTEMS_STATIC_ASSERT( \ + offsetof(Context_Control, field) \ + == I386_CONTEXT_CONTROL_ ## off ## _OFFSET, \ + Context_Control_ ## field \ + ) + +I386_ASSERT_OFFSET(eflags, EFLAGS); +I386_ASSERT_OFFSET(esp, ESP); +I386_ASSERT_OFFSET(ebp, EBP); +I386_ASSERT_OFFSET(ebx, EBX); +I386_ASSERT_OFFSET(esi, ESI); +I386_ASSERT_OFFSET(edi, EDI); + +#ifdef RTEMS_SMP + I386_ASSERT_OFFSET(is_executing, IS_EXECUTING); +#endif + void _CPU_Initialize(void) { #if CPU_HARDWARE_FP diff --git a/cpukit/score/cpu/i386/cpu_asm.S b/cpukit/score/cpu/i386/cpu_asm.S index 73a4c143b4..cc08312f33 100644 --- a/cpukit/score/cpu/i386/cpu_asm.S +++ b/cpukit/score/cpu/i386/cpu_asm.S @@ -26,13 +26,12 @@ * Format of i386 Register structure */ -.set REG_EFLAGS, 0 -.set REG_ESP, REG_EFLAGS + 4 -.set REG_EBP, REG_ESP + 4 -.set REG_EBX, REG_EBP + 4 -.set REG_ESI, REG_EBX + 4 -.set REG_EDI, REG_ESI + 4 -.set SIZE_REGS, REG_EDI + 4 +.set REG_EFLAGS, I386_CONTEXT_CONTROL_EFLAGS_OFFSET +.set REG_ESP, I386_CONTEXT_CONTROL_ESP_OFFSET +.set REG_EBP, I386_CONTEXT_CONTROL_EBP_OFFSET +.set REG_EBX, I386_CONTEXT_CONTROL_EBX_OFFSET +.set REG_ESI, I386_CONTEXT_CONTROL_ESI_OFFSET +.set REG_EDI, I386_CONTEXT_CONTROL_EDI_OFFSET BEGIN_CODE @@ -58,9 +57,25 @@ SYM (_CPU_Context_switch): movl esi,REG_ESI(eax) /* save source register */ movl edi,REG_EDI(eax) /* save destination register */ +#ifdef RTEMS_SMP + /* Indicate that this context is no longer executing */ + movb $0, I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET(eax) +#endif + movl HEIRCONTEXT_ARG(esp),eax /* eax = heir threads context */ restore: +#ifdef RTEMS_SMP + /* Wait for context to stop execution if necessary */ +1: + movb I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET(eax), bl + testb bl, bl + jne 1b + + /* Indicate that this context is executing */ + movb $1, I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET(eax) +#endif + pushl REG_EFLAGS(eax) /* push eflags */ popf /* restore eflags */ movl REG_ESP(eax),esp /* restore stack pointer */ diff --git a/cpukit/score/cpu/i386/rtems/score/cpu.h b/cpukit/score/cpu/i386/rtems/score/cpu.h index a9957cbe62..ba731b0666 100644 --- a/cpukit/score/cpu/i386/rtems/score/cpu.h +++ b/cpukit/score/cpu/i386/rtems/score/cpu.h @@ -128,6 +128,17 @@ extern "C" { #define CPU_PER_CPU_CONTROL_SIZE 0 +#define I386_CONTEXT_CONTROL_EFLAGS_OFFSET 0 +#define I386_CONTEXT_CONTROL_ESP_OFFSET 4 +#define I386_CONTEXT_CONTROL_EBP_OFFSET 8 +#define I386_CONTEXT_CONTROL_EBX_OFFSET 12 +#define I386_CONTEXT_CONTROL_ESI_OFFSET 16 +#define I386_CONTEXT_CONTROL_EDI_OFFSET 20 + +#ifdef RTEMS_SMP + #define I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 24 +#endif + /* structures */ #ifndef ASM @@ -147,11 +158,19 @@ typedef struct { uint32_t ebx; /* extended bx register */ uint32_t esi; /* extended source index register */ uint32_t edi; /* extended destination index flags register */ +#ifdef RTEMS_SMP + volatile bool is_executing; +#endif } Context_Control; #define _CPU_Context_Get_SP( _context ) \ (_context)->esp +#ifdef RTEMS_SMP + #define _CPU_Context_Get_is_executing( _context ) \ + (_context)->is_executing +#endif + /* * FP context save area for the i387 numeric coprocessors. */ @@ -435,6 +454,13 @@ uint32_t _CPU_ISR_Get_level( void ); */ +#ifdef RTEMS_SMP + #define _I386_Context_Initialize_is_executing( _the_context ) \ + (_the_context)->is_executing = false +#else + #define _I386_Context_Initialize_is_executing( _the_context ) +#endif + #define _CPU_Context_Initialize( _the_context, _stack_base, _size, \ _isr, _entry_point, _is_fp, _tls_area ) \ do { \ @@ -449,6 +475,7 @@ uint32_t _CPU_ISR_Get_level( void ); *((proc_ptr *)(_stack)) = (_entry_point); \ (_the_context)->ebp = (void *) 0; \ (_the_context)->esp = (void *) _stack; \ + _I386_Context_Initialize_is_executing( _the_context ); \ } while (0) #define _CPU_Context_Restart_self( _the_context ) \ |