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