1 // SPDX-License-Identifier: GPL-2.0 2 #include <config.h> 3 4 #include "preempt.h" 5 6 #include "assume.h" 7 #include "locks.h" 8 9 /* Support NR_CPUS of at most 64 */ 10 #define CPU_PREEMPTION_LOCKS_INIT0 LOCK_IMPL_INITIALIZER 11 #define CPU_PREEMPTION_LOCKS_INIT1 \ 12 CPU_PREEMPTION_LOCKS_INIT0, CPU_PREEMPTION_LOCKS_INIT0 13 #define CPU_PREEMPTION_LOCKS_INIT2 \ 14 CPU_PREEMPTION_LOCKS_INIT1, CPU_PREEMPTION_LOCKS_INIT1 15 #define CPU_PREEMPTION_LOCKS_INIT3 \ 16 CPU_PREEMPTION_LOCKS_INIT2, CPU_PREEMPTION_LOCKS_INIT2 17 #define CPU_PREEMPTION_LOCKS_INIT4 \ 18 CPU_PREEMPTION_LOCKS_INIT3, CPU_PREEMPTION_LOCKS_INIT3 19 #define CPU_PREEMPTION_LOCKS_INIT5 \ 20 CPU_PREEMPTION_LOCKS_INIT4, CPU_PREEMPTION_LOCKS_INIT4 21 22 /* 23 * Simulate disabling preemption by locking a particular cpu. NR_CPUS 24 * should be the actual number of cpus, not just the maximum. 25 */ 26 struct lock_impl cpu_preemption_locks[NR_CPUS] = { 27 CPU_PREEMPTION_LOCKS_INIT0 28 #if (NR_CPUS - 1) & 1 29 , CPU_PREEMPTION_LOCKS_INIT0 30 #endif 31 #if (NR_CPUS - 1) & 2 32 , CPU_PREEMPTION_LOCKS_INIT1 33 #endif 34 #if (NR_CPUS - 1) & 4 35 , CPU_PREEMPTION_LOCKS_INIT2 36 #endif 37 #if (NR_CPUS - 1) & 8 38 , CPU_PREEMPTION_LOCKS_INIT3 39 #endif 40 #if (NR_CPUS - 1) & 16 41 , CPU_PREEMPTION_LOCKS_INIT4 42 #endif 43 #if (NR_CPUS - 1) & 32 44 , CPU_PREEMPTION_LOCKS_INIT5 45 #endif 46 }; 47 48 #undef CPU_PREEMPTION_LOCKS_INIT0 49 #undef CPU_PREEMPTION_LOCKS_INIT1 50 #undef CPU_PREEMPTION_LOCKS_INIT2 51 #undef CPU_PREEMPTION_LOCKS_INIT3 52 #undef CPU_PREEMPTION_LOCKS_INIT4 53 #undef CPU_PREEMPTION_LOCKS_INIT5 54 55 __thread int thread_cpu_id; 56 __thread int preempt_disable_count; 57 58 void preempt_disable(void) 59 { 60 BUG_ON(preempt_disable_count < 0 || preempt_disable_count == INT_MAX); 61 62 if (preempt_disable_count++) 63 return; 64 65 thread_cpu_id = nondet_int(); 66 assume(thread_cpu_id >= 0); 67 assume(thread_cpu_id < NR_CPUS); 68 lock_impl_lock(&cpu_preemption_locks[thread_cpu_id]); 69 } 70 71 void preempt_enable(void) 72 { 73 BUG_ON(preempt_disable_count < 1); 74 75 if (--preempt_disable_count) 76 return; 77 78 lock_impl_unlock(&cpu_preemption_locks[thread_cpu_id]); 79 } 80