• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
preempt_disable(void)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 
preempt_enable(void)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