forked from Imagelibrary/rtems
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:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 embedded brains GmbH. All rights reserved.
|
||||
* Copyright (c) 2013-2015 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
@@ -62,6 +62,7 @@ void _CPU_SMP_Prepare_start_multitasking( void )
|
||||
|
||||
void _CPU_SMP_Send_interrupt( uint32_t target_processor_index )
|
||||
{
|
||||
_ARM_Data_memory_barrier();
|
||||
arm_gic_irq_generate_software_irq(
|
||||
ARM_GIC_IRQ_SGI_0,
|
||||
ARM_GIC_IRQ_SOFTWARE_IRQ_TO_ALL_IN_LIST,
|
||||
|
||||
@@ -235,5 +235,10 @@ void _CPU_SMP_Prepare_start_multitasking(void)
|
||||
|
||||
void _CPU_SMP_Send_interrupt(uint32_t target_processor_index)
|
||||
{
|
||||
#ifdef __PPC_CPU_E6500__
|
||||
ppc_light_weight_synchronize();
|
||||
#else
|
||||
ppc_synchronize_data();
|
||||
#endif
|
||||
qoriq.pic.ipidr [IPI_INDEX].reg = 1U << target_processor_index;
|
||||
}
|
||||
|
||||
@@ -236,24 +236,18 @@ check_is_executing:
|
||||
beq try_update_is_executing
|
||||
mov 1, %g1
|
||||
|
||||
! Check if a thread dispatch is necessary
|
||||
ldub [%g6 + PER_CPU_DISPATCH_NEEDED], %g1
|
||||
cmp %g1, 0
|
||||
beq check_is_executing
|
||||
nop
|
||||
|
||||
! We have a new heir
|
||||
|
||||
! Clear the thread dispatch necessary flag
|
||||
stub %g0, [%g6 + PER_CPU_DISPATCH_NEEDED]
|
||||
|
||||
! Here we assume a strong memory order, otherwise a memory barrier must
|
||||
! be inserted here
|
||||
! We may have a new heir
|
||||
|
||||
! Read the executing and heir
|
||||
ld [%g6 + PER_CPU_OFFSET_EXECUTING], %g1
|
||||
ld [%g6 + PER_CPU_OFFSET_HEIR], %g2
|
||||
|
||||
! Update the executing only if necessary to avoid cache line
|
||||
! monopolization.
|
||||
cmp %g1, %g2
|
||||
beq try_update_is_executing
|
||||
mov 1, %g1
|
||||
|
||||
! Calculate the heir context pointer
|
||||
sub %o1, %g1, %g1
|
||||
add %g1, %g2, %o1
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user