Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84d88d5d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'sched-fixes-for-linus' of...

Merge branch 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  sched_clock: Fix atomicity/continuity bug by using cmpxchg64()
  x86: Provide an alternative() based cmpxchg64()
parents e399835c 152f9d07
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
@@ -315,16 +315,20 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
#define cmpxchg64(ptr, o, n)					\
({								\
	__typeof__(*(ptr)) __ret;				\
	if (likely(boot_cpu_data.x86 > 4))				\
		__ret = (__typeof__(*(ptr)))__cmpxchg64((ptr),		\
				(unsigned long long)(o),		\
				(unsigned long long)(n));		\
	else								\
		__ret = (__typeof__(*(ptr)))cmpxchg_486_u64((ptr),	\
				(unsigned long long)(o),		\
				(unsigned long long)(n));		\
	__ret;								\
})
	__typeof__(*(ptr)) __old = (o);				\
	__typeof__(*(ptr)) __new = (n);				\
	alternative_io("call cmpxchg8b_emu",			\
			"lock; cmpxchg8b (%%esi)" ,		\
		       X86_FEATURE_CX8,				\
		       "=A" (__ret),				\
		       "S" ((ptr)), "0" (__old),		\
		       "b" ((unsigned int)__new),		\
		       "c" ((unsigned int)(__new>>32))		\
		       : "memory");				\
	__ret; })



#define cmpxchg64_local(ptr, o, n)					\
({									\
	__typeof__(*(ptr)) __ret;					\
+8 −0
Original line number Diff line number Diff line
@@ -10,6 +10,14 @@
EXPORT_SYMBOL(mcount);
#endif

/*
 * Note, this is a prototype to get at the symbol for
 * the export, but dont use it from C code, it is used
 * by assembly code and is not using C calling convention!
 */
extern void cmpxchg8b_emu(void);
EXPORT_SYMBOL(cmpxchg8b_emu);

/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy_generic);

+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ ifeq ($(CONFIG_X86_32),y)
        obj-y += atomic64_32.o
        lib-y += checksum_32.o
        lib-y += strstr_32.o
        lib-y += semaphore_32.o string_32.o
        lib-y += semaphore_32.o string_32.o cmpxchg8b_emu.o

        lib-$(CONFIG_X86_USE_3DNOW) += mmx_32.o
else
+57 −0
Original line number Diff line number Diff line
/*
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; version 2
 *	of the License.
 *
 */

#include <linux/linkage.h>
#include <asm/alternative-asm.h>
#include <asm/frame.h>
#include <asm/dwarf2.h>


.text

/*
 * Inputs:
 * %esi : memory location to compare
 * %eax : low 32 bits of old value
 * %edx : high 32 bits of old value
 * %ebx : low 32 bits of new value
 * %ecx : high 32 bits of new value
 */
ENTRY(cmpxchg8b_emu)
CFI_STARTPROC

#
# Emulate 'cmpxchg8b (%esi)' on UP except we don't
# set the whole ZF thing (caller will just compare
# eax:edx with the expected value)
#
cmpxchg8b_emu:
	pushfl
	cli

	cmpl  (%esi), %eax
	jne not_same
	cmpl 4(%esi), %edx
	jne half_same

	movl %ebx,  (%esi)
	movl %ecx, 4(%esi)

	popfl
	ret

 not_same:
	movl  (%esi), %eax
 half_same:
	movl 4(%esi), %edx

	popfl
	ret

CFI_ENDPROC
ENDPROC(cmpxchg8b_emu)
+2 −2
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ static u64 sched_clock_local(struct sched_clock_data *scd)
	clock = wrap_max(clock, min_clock);
	clock = wrap_min(clock, max_clock);

	if (cmpxchg(&scd->clock, old_clock, clock) != old_clock)
	if (cmpxchg64(&scd->clock, old_clock, clock) != old_clock)
		goto again;

	return clock;
@@ -163,7 +163,7 @@ static u64 sched_clock_remote(struct sched_clock_data *scd)
		val = remote_clock;
	}

	if (cmpxchg(ptr, old_val, val) != old_val)
	if (cmpxchg64(ptr, old_val, val) != old_val)
		goto again;

	return val;