[RFC/PATCH 5/7] ARM: Move get_thread_info macro definition to <asm/assembler.h>

Russell King - ARM Linux linux at arm.linux.org.uk
Thu Oct 13 10:34:20 EDT 2011


On Wed, Oct 12, 2011 at 02:04:33AM -0400, gdavis at mvista.com wrote:
> diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
> index 78397d0..eaf4939 100644
> --- a/arch/arm/include/asm/assembler.h
> +++ b/arch/arm/include/asm/assembler.h
> @@ -36,6 +36,20 @@
>  	.endm
>  #endif  /* !CONFIG_THUMB2_KERNEL */
>  
> +	.macro	preempt_disable, tsk, cnt
> +	get_thread_info \tsk
> +	ldr	\cnt, [\tsk, #TI_PREEMPT]
> +	add	\cnt, \cnt, #1
> +	str	\cnt, [\tsk, #TI_PREEMPT]
> +	.endm
> +
> +	.macro	preempt_enable, tsk, cnt
> +	get_thread_info \tsk
> +	ldr	\cnt, [\tsk, #TI_PREEMPT]
> +	sub	\cnt, \cnt, #1
> +	str	\cnt, [\tsk, #TI_PREEMPT]
> +	.endm
> +
>  /*
>   * Endian independent macros for shifting bytes within registers.
>   */
> 
> 
> Not as efficient as it could be but I imagine the macros could
> be written to support optional load of \tsk and/or optional \tmp
> parameters to cover other common cases.

It's actually not that simple either: if you disable preemption, then you
need to check for a preempt event after re-enabling preemption.  The
C level code does this:

#define preempt_enable_no_resched() \
do { \
        barrier(); \
        dec_preempt_count(); \
} while (0)

#define preempt_check_resched() \
do { \
        if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
                preempt_schedule(); \
} while (0)

#define preempt_enable() \
do { \
        preempt_enable_no_resched(); \
        barrier(); \
        preempt_check_resched(); \
} while (0)

Note that preempt_schedule() will check the preempt count itself and
return immediately if non-zero or irqs are disabled.



More information about the linux-arm-kernel mailing list