1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30#include <linux/gfp.h>
31#include "sched_cpupri.h"
32
33
34static int convert_prio(int prio)
35{
36 int cpupri;
37
38 if (prio == CPUPRI_INVALID)
39 cpupri = CPUPRI_INVALID;
40 else if (prio == MAX_PRIO)
41 cpupri = CPUPRI_IDLE;
42 else if (prio >= MAX_RT_PRIO)
43 cpupri = CPUPRI_NORMAL;
44 else
45 cpupri = MAX_RT_PRIO - prio + 1;
46
47 return cpupri;
48}
49
50#define for_each_cpupri_active(array, idx) \
51 for_each_set_bit(idx, array, CPUPRI_NR_PRIORITIES)
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68int cpupri_find(struct cpupri *cp, struct task_struct *p,
69 struct cpumask *lowest_mask)
70{
71 int idx = 0;
72 int task_pri = convert_prio(p->prio);
73
74 for_each_cpupri_active(cp->pri_active, idx) {
75 struct cpupri_vec *vec = &cp->pri_to_cpu[idx];
76
77 if (idx >= task_pri)
78 break;
79
80 if (cpumask_any_and(&p->cpus_allowed, vec->mask) >= nr_cpu_ids)
81 continue;
82
83 if (lowest_mask) {
84 cpumask_and(lowest_mask, &p->cpus_allowed, vec->mask);
85
86
87
88
89
90
91
92
93
94 if (cpumask_any(lowest_mask) >= nr_cpu_ids)
95 continue;
96 }
97
98 return 1;
99 }
100
101 return 0;
102}
103
104
105
106
107
108
109
110
111
112
113
114void cpupri_set(struct cpupri *cp, int cpu, int newpri)
115{
116 int *currpri = &cp->cpu_to_pri[cpu];
117 int oldpri = *currpri;
118 unsigned long flags;
119
120 newpri = convert_prio(newpri);
121
122 BUG_ON(newpri >= CPUPRI_NR_PRIORITIES);
123
124 if (newpri == oldpri)
125 return;
126
127
128
129
130
131
132
133
134 if (likely(newpri != CPUPRI_INVALID)) {
135 struct cpupri_vec *vec = &cp->pri_to_cpu[newpri];
136
137 raw_spin_lock_irqsave(&vec->lock, flags);
138
139 cpumask_set_cpu(cpu, vec->mask);
140 vec->count++;
141 if (vec->count == 1)
142 set_bit(newpri, cp->pri_active);
143
144 raw_spin_unlock_irqrestore(&vec->lock, flags);
145 }
146 if (likely(oldpri != CPUPRI_INVALID)) {
147 struct cpupri_vec *vec = &cp->pri_to_cpu[oldpri];
148
149 raw_spin_lock_irqsave(&vec->lock, flags);
150
151 vec->count--;
152 if (!vec->count)
153 clear_bit(oldpri, cp->pri_active);
154 cpumask_clear_cpu(cpu, vec->mask);
155
156 raw_spin_unlock_irqrestore(&vec->lock, flags);
157 }
158
159 *currpri = newpri;
160}
161
162
163
164
165
166
167
168
169int cpupri_init(struct cpupri *cp, bool bootmem)
170{
171 gfp_t gfp = GFP_KERNEL;
172 int i;
173
174 if (bootmem)
175 gfp = GFP_NOWAIT;
176
177 memset(cp, 0, sizeof(*cp));
178
179 for (i = 0; i < CPUPRI_NR_PRIORITIES; i++) {
180 struct cpupri_vec *vec = &cp->pri_to_cpu[i];
181
182 raw_spin_lock_init(&vec->lock);
183 vec->count = 0;
184 if (!zalloc_cpumask_var(&vec->mask, gfp))
185 goto cleanup;
186 }
187
188 for_each_possible_cpu(i)
189 cp->cpu_to_pri[i] = CPUPRI_INVALID;
190 return 0;
191
192cleanup:
193 for (i--; i >= 0; i--)
194 free_cpumask_var(cp->pri_to_cpu[i].mask);
195 return -ENOMEM;
196}
197
198
199
200
201
202void cpupri_cleanup(struct cpupri *cp)
203{
204 int i;
205
206 for (i = 0; i < CPUPRI_NR_PRIORITIES; i++)
207 free_cpumask_var(cp->pri_to_cpu[i].mask);
208}
209