// SPDX-License-Identifier: GPL-2.0
|
#include <config.h>
|
|
#include "preempt.h"
|
|
#include "assume.h"
|
#include "locks.h"
|
|
/* Support NR_CPUS of at most 64 */
|
#define CPU_PREEMPTION_LOCKS_INIT0 LOCK_IMPL_INITIALIZER
|
#define CPU_PREEMPTION_LOCKS_INIT1 \
|
CPU_PREEMPTION_LOCKS_INIT0, CPU_PREEMPTION_LOCKS_INIT0
|
#define CPU_PREEMPTION_LOCKS_INIT2 \
|
CPU_PREEMPTION_LOCKS_INIT1, CPU_PREEMPTION_LOCKS_INIT1
|
#define CPU_PREEMPTION_LOCKS_INIT3 \
|
CPU_PREEMPTION_LOCKS_INIT2, CPU_PREEMPTION_LOCKS_INIT2
|
#define CPU_PREEMPTION_LOCKS_INIT4 \
|
CPU_PREEMPTION_LOCKS_INIT3, CPU_PREEMPTION_LOCKS_INIT3
|
#define CPU_PREEMPTION_LOCKS_INIT5 \
|
CPU_PREEMPTION_LOCKS_INIT4, CPU_PREEMPTION_LOCKS_INIT4
|
|
/*
|
* Simulate disabling preemption by locking a particular cpu. NR_CPUS
|
* should be the actual number of cpus, not just the maximum.
|
*/
|
struct lock_impl cpu_preemption_locks[NR_CPUS] = {
|
CPU_PREEMPTION_LOCKS_INIT0
|
#if (NR_CPUS - 1) & 1
|
, CPU_PREEMPTION_LOCKS_INIT0
|
#endif
|
#if (NR_CPUS - 1) & 2
|
, CPU_PREEMPTION_LOCKS_INIT1
|
#endif
|
#if (NR_CPUS - 1) & 4
|
, CPU_PREEMPTION_LOCKS_INIT2
|
#endif
|
#if (NR_CPUS - 1) & 8
|
, CPU_PREEMPTION_LOCKS_INIT3
|
#endif
|
#if (NR_CPUS - 1) & 16
|
, CPU_PREEMPTION_LOCKS_INIT4
|
#endif
|
#if (NR_CPUS - 1) & 32
|
, CPU_PREEMPTION_LOCKS_INIT5
|
#endif
|
};
|
|
#undef CPU_PREEMPTION_LOCKS_INIT0
|
#undef CPU_PREEMPTION_LOCKS_INIT1
|
#undef CPU_PREEMPTION_LOCKS_INIT2
|
#undef CPU_PREEMPTION_LOCKS_INIT3
|
#undef CPU_PREEMPTION_LOCKS_INIT4
|
#undef CPU_PREEMPTION_LOCKS_INIT5
|
|
__thread int thread_cpu_id;
|
__thread int preempt_disable_count;
|
|
void preempt_disable(void)
|
{
|
BUG_ON(preempt_disable_count < 0 || preempt_disable_count == INT_MAX);
|
|
if (preempt_disable_count++)
|
return;
|
|
thread_cpu_id = nondet_int();
|
assume(thread_cpu_id >= 0);
|
assume(thread_cpu_id < NR_CPUS);
|
lock_impl_lock(&cpu_preemption_locks[thread_cpu_id]);
|
}
|
|
void preempt_enable(void)
|
{
|
BUG_ON(preempt_disable_count < 1);
|
|
if (--preempt_disable_count)
|
return;
|
|
lock_impl_unlock(&cpu_preemption_locks[thread_cpu_id]);
|
}
|