Skip to content

Commit

Permalink
acpi: fix bogus preemption logic
Browse files Browse the repository at this point in the history
The ACPI_PREEMPTION_POINT() logic was introduced in commit 8bd108d
(ACPICA: add preemption point after each opcode parse).  The follow up
commits abe1dfa, 138d156, c084ca7 tried to fix the preemption logic
back and forth, but nobody noticed that the usage of
in_atomic_preempt_off() in that context is wrong.

The check which guards the call of cond_resched() is:

    if (!in_atomic_preempt_off() && !irqs_disabled())

in_atomic_preempt_off() is not intended for general use as the comment
above the macro definition clearly says:

 * Check whether we were atomic before we did preempt_disable():
 * (used by the scheduler, *after* releasing the kernel lock)

On a CONFIG_PREEMPT=n kernel the usage of in_atomic_preempt_off() works by
accident, but with CONFIG_PREEMPT=y it's just broken.

The whole purpose of the ACPI_PREEMPTION_POINT() is to reduce the latency
on a CONFIG_PREEMPT=n kernel, so make ACPI_PREEMPTION_POINT() depend on
CONFIG_PREEMPT=n and remove the in_atomic_preempt_off() check.

Addresses https://bugzilla.kernel.org/show_bug.cgi?id=16210

[[email protected]: fix build]
Signed-off-by: Thomas Gleixner <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Francois Valenduc <[email protected]>
Cc: Lin Ming <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
KAGA-KOKO authored and torvalds committed Aug 12, 2010
1 parent d78a3ed commit 0a7992c
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 3 deletions.
1 change: 1 addition & 0 deletions drivers/acpi/apei/erst.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/uaccess.h>
#include <linux/cper.h>
#include <linux/nmi.h>
#include <linux/hardirq.h>
#include <acpi/apei.h>

#include "apei-internal.h"
Expand Down
10 changes: 7 additions & 3 deletions include/acpi/platform/aclinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,17 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache)
#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a)
#define ACPI_FREE(a) kfree(a)

/* Used within ACPICA to show where it is safe to preempt execution */
#include <linux/hardirq.h>
#ifndef CONFIG_PREEMPT
/*
* Used within ACPICA to show where it is safe to preempt execution
* when CONFIG_PREEMPT=n
*/
#define ACPI_PREEMPTION_POINT() \
do { \
if (!in_atomic_preempt_off() && !irqs_disabled()) \
if (!irqs_disabled()) \
cond_resched(); \
} while (0)
#endif

#endif /* __KERNEL__ */

Expand Down

0 comments on commit 0a7992c

Please sign in to comment.