Home | History | Annotate | Download | only in src
      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