SMP: Fix and optimize thread dispatching

According to the C11 and C++11 memory models only a read-modify-write
operation guarantees that we read the last value written in modification
order.  Avoid the sequential consistent thread fence and instead use the
inter-processor interrupt to set the thread dispatch necessary
indicator.
This commit is contained in:
Sebastian Huber
2015-09-25 14:34:24 +02:00
parent aee6a1d05f
commit 258ad71e96
11 changed files with 101 additions and 100 deletions

View File

@@ -413,12 +413,12 @@ check_is_executing:
addi r6, r5, PPC_CONTEXT_OFFSET_IS_EXECUTING
lwarx r7, r0, r6
cmpwi r7, 0
bne check_thread_dispatch_necessary
bne get_potential_new_heir
/* Try to update the is executing indicator of the heir context */
li r7, 1
stwcx. r7, r0, r6
bne check_thread_dispatch_necessary
bne get_potential_new_heir
isync
#endif
@@ -536,26 +536,23 @@ PROC (_CPU_Context_restore):
b restore_context
#ifdef RTEMS_SMP
check_thread_dispatch_necessary:
get_potential_new_heir:
GET_SELF_CPU_CONTROL r6
/* Check if a thread dispatch is necessary */
lbz r7, PER_CPU_DISPATCH_NEEDED(r6)
cmpwi r7, 0
beq check_is_executing
/* We have a new heir */
/* Clear the thread dispatch necessary flag */
li r7, 0
stb r7, PER_CPU_DISPATCH_NEEDED(r6)
msync
/* We may have a new heir */
/* Read the executing and heir */
lwz r7, PER_CPU_OFFSET_EXECUTING(r6)
lwz r8, PER_CPU_OFFSET_HEIR(r6)
/*
* Update the executing only if necessary to avoid cache line
* monopolization.
*/
cmpw r7, r8
beq check_is_executing
/* Calculate the heir context pointer */
sub r7, r4, r7
add r4, r8, r7

View File

@@ -8,7 +8,7 @@
*/
/*
* Copyright (c) 2008-2014 embedded brains GmbH.
* Copyright (c) 2008-2015 embedded brains GmbH.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -206,6 +206,13 @@ static inline void ppc_synchronize_data(void)
__asm__ volatile ("sync");
}
static inline void ppc_light_weight_synchronize(void)
{
RTEMS_COMPILER_MEMORY_BARRIER();
__asm__ volatile ("lwsync");
}
static inline void ppc_synchronize_instructions(void)
{
RTEMS_COMPILER_MEMORY_BARRIER();