1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #pragma once
30 
31 /**
32  * @file sched.h
33  * @brief Thread execution scheduling.
34  */
35 
36 #include <bits/timespec.h>
37 #include <linux/sched.h>
38 #include <sys/cdefs.h>
39 
40 __BEGIN_DECLS
41 
42 /*
43  * @def SCHED_NORMAL
44  * The standard (as opposed to real-time) round-robin scheduling policy.
45  *
46  * (Linux's name for POSIX's SCHED_OTHER.)
47  *
48  * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
49  */
50 
51 /*
52  * @def SCHED_FIFO
53  * The real-time first-in/first-out scheduling policy.
54  *
55  * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
56  */
57 
58 /*
59  * @def SCHED_RR
60  * The real-time round-robin policy. (See also SCHED_NORMAL/SCHED_OTHER.)
61  *
62  * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
63  */
64 
65 /*
66  * @def SCHED_BATCH
67  * The batch scheduling policy.
68  *
69  * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
70  */
71 
72 /*
73  * @def SCHED_IDLE
74  * The low priority "only when otherwise idle" scheduling priority.
75  *
76  * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
77  */
78 
79 /*
80  * @def SCHED_DEADLINE
81  * The deadline scheduling policy.
82  *
83  * See [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html)
84  */
85 
86 /*
87  * The standard (as opposed to real-time) round-robin scheduling policy.
88  *
89  * (POSIX's name for Linux's SCHED_NORMAL.)
90  */
91 #define SCHED_OTHER SCHED_NORMAL
92 
93 /**
94  * See sched_getparam()/sched_setparam() and
95  * sched_getscheduler()/sched_setscheduler().
96  */
97 struct sched_param {
98   int sched_priority;
99 };
100 
101 /**
102  * [sched_setscheduler(2)](http://man7.org/linux/man-pages/man2/sched_getcpu.2.html)
103  * sets the scheduling policy and associated parameters for the given thread.
104  *
105  * Returns 0 on success and returns -1 and sets `errno` on failure.
106  */
107 int sched_setscheduler(pid_t __pid, int __policy, const struct sched_param* _Nonnull __param);
108 
109 /**
110  * [sched_getscheduler(2)](http://man7.org/linux/man-pages/man2/sched_getcpu.2.html)
111  * gets the scheduling policy for the given thread.
112  *
113  * Returns a non-negative thread policy on success and returns -1 and sets
114  * `errno` on failure.
115  */
116 int sched_getscheduler(pid_t __pid);
117 
118 /**
119  * [sched_yield(2)](http://man7.org/linux/man-pages/man2/sched_yield.2.html)
120  * voluntarily gives up using the CPU so that another thread can run.
121  *
122  * Returns 0 on success and returns -1 and sets `errno` on failure.
123  */
124 int sched_yield(void);
125 
126 /**
127  * [sched_get_priority_max(2)](http://man7.org/linux/man-pages/man2/sched_get_priority_max.2.html)
128  * gets the maximum priority value allowed for the given scheduling policy.
129  *
130  * Returns a priority on success and returns -1 and sets `errno` on failure.
131  */
132 int sched_get_priority_max(int __policy);
133 
134 /**
135  * [sched_get_priority_min(2)](http://man7.org/linux/man-pages/man2/sched_get_priority_min.2.html)
136  * gets the minimum priority value allowed for the given scheduling policy.
137  *
138  * Returns a priority on success and returns -1 and sets `errno` on failure.
139  */
140 int sched_get_priority_min(int __policy);
141 
142 /**
143  * [sched_setparam(2)](http://man7.org/linux/man-pages/man2/sched_setparam.2.html)
144  * sets the scheduling parameters for the given thread.
145  *
146  * Returns 0 on success and returns -1 and sets `errno` on failure.
147  */
148 int sched_setparam(pid_t __pid, const struct sched_param* _Nonnull __param);
149 
150 /**
151  * [sched_getparam(2)](http://man7.org/linux/man-pages/man2/sched_getparam.2.html)
152  * gets the scheduling parameters for the given thread.
153  *
154  * Returns 0 on success and returns -1 and sets `errno` on failure.
155  */
156 int sched_getparam(pid_t __pid, struct sched_param* _Nonnull __param);
157 
158 /**
159  * [sched_rr_get_interval(2)](http://man7.org/linux/man-pages/man2/sched_rr_get_interval.2.html)
160  * queries the round-robin time quantum for the given thread.
161  *
162  * Returns 0 on success and returns -1 and sets `errno` on failure.
163  */
164 int sched_rr_get_interval(pid_t __pid, struct timespec* _Nonnull __quantum);
165 
166 #if defined(__USE_GNU)
167 
168 /**
169  * [clone(2)](http://man7.org/linux/man-pages/man2/clone.2.html)
170  * creates a new child process.
171  *
172  * Returns the pid of the child to the caller on success and
173  * returns -1 and sets `errno` on failure.
174  */
175 
176 #if (defined(__LP64__)) || (defined(__arm__)) || (defined(__i386__) && __ANDROID_API__ >= 17)
177 int clone(int (* __BIONIC_COMPLICATED_NULLNESS __fn)(void* __BIONIC_COMPLICATED_NULLNESS ), void* __BIONIC_COMPLICATED_NULLNESS __child_stack, int __flags, void* _Nullable __arg, ...) __INTRODUCED_IN_ARM(9) __INTRODUCED_IN_X86(17);
178 #endif /* (defined(__LP64__)) || (defined(__arm__)) || (defined(__i386__) && __ANDROID_API__ >= 17) */
179 
180 
181 /**
182  * [unshare(2)](http://man7.org/linux/man-pages/man2/unshare.2.html)
183  * disassociates part of the caller's execution context.
184  *
185  * Returns 0 on success and returns -1 and sets `errno` on failure.
186  *
187  * Available since API level 17.
188  */
189 
190 #if __ANDROID_API__ >= 17
191 int unshare(int __flags) __INTRODUCED_IN(17);
192 #endif /* __ANDROID_API__ >= 17 */
193 
194 
195 /**
196  * [setns(2)](http://man7.org/linux/man-pages/man2/setns.2.html)
197  * reassociates a thread with a different namespace.
198  *
199  * Returns 0 on success and returns -1 and sets `errno` on failure.
200  *
201  * Available since API level 21.
202  */
203 
204 #if __ANDROID_API__ >= 21
205 int setns(int __fd, int __ns_type) __INTRODUCED_IN(21);
206 #endif /* __ANDROID_API__ >= 21 */
207 
208 
209 /**
210  * [sched_getcpu(3)](http://man7.org/linux/man-pages/man3/sched_getcpu.3.html)
211  * reports which CPU the caller is running on.
212  *
213  * Returns a non-negative CPU number on success and returns -1 and sets
214  * `errno` on failure.
215  */
216 int sched_getcpu(void);
217 
218 #ifdef __LP64__
219 #define CPU_SETSIZE 1024
220 #else
221 #define CPU_SETSIZE 32
222 #endif
223 
224 #define __CPU_BITTYPE  unsigned long int  /* mandated by the kernel  */
225 #define __CPU_BITS     (8 * sizeof(__CPU_BITTYPE))
226 #define __CPU_ELT(x)   ((x) / __CPU_BITS)
227 #define __CPU_MASK(x)  ((__CPU_BITTYPE)1 << ((x) & (__CPU_BITS - 1)))
228 
229 /**
230  * [cpu_set_t](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) is a
231  * statically-sized CPU set. See `CPU_ALLOC` for dynamically-sized CPU sets.
232  */
233 typedef struct {
234   __CPU_BITTYPE  __bits[ CPU_SETSIZE / __CPU_BITS ];
235 } cpu_set_t;
236 
237 /**
238  * [sched_setaffinity(2)](http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html)
239  * sets the CPU affinity mask for the given thread.
240  *
241  * Returns 0 on success and returns -1 and sets `errno` on failure.
242  */
243 int sched_setaffinity(pid_t __pid, size_t __set_size, const cpu_set_t* _Nonnull __set);
244 
245 /**
246  * [sched_getaffinity(2)](http://man7.org/linux/man-pages/man2/sched_getaffinity.2.html)
247  * gets the CPU affinity mask for the given thread.
248  *
249  * Returns 0 on success and returns -1 and sets `errno` on failure.
250  */
251 int sched_getaffinity(pid_t __pid, size_t __set_size, cpu_set_t* _Nonnull __set);
252 
253 /**
254  * [CPU_ZERO](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears all
255  * bits in a static CPU set.
256  */
257 #define CPU_ZERO(set)          CPU_ZERO_S(sizeof(cpu_set_t), set)
258 /**
259  * [CPU_ZERO_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears all
260  * bits in a dynamic CPU set allocated by `CPU_ALLOC`.
261  */
262 #define CPU_ZERO_S(setsize, set)  __builtin_memset(set, 0, setsize)
263 
264 /**
265  * [CPU_SET](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) sets one
266  * bit in a static CPU set.
267  */
268 #define CPU_SET(cpu, set)      CPU_SET_S(cpu, sizeof(cpu_set_t), set)
269 /**
270  * [CPU_SET_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) sets one
271  * bit in a dynamic CPU set allocated by `CPU_ALLOC`.
272  */
273 #define CPU_SET_S(cpu, setsize, set) \
274   do { \
275     size_t __cpu = (cpu); \
276     if (__cpu < 8 * (setsize)) \
277       (set)->__bits[__CPU_ELT(__cpu)] |= __CPU_MASK(__cpu); \
278   } while (0)
279 
280 /**
281  * [CPU_CLR](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears one
282  * bit in a static CPU set.
283  */
284 #define CPU_CLR(cpu, set)      CPU_CLR_S(cpu, sizeof(cpu_set_t), set)
285 /**
286  * [CPU_CLR_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears one
287  * bit in a dynamic CPU set allocated by `CPU_ALLOC`.
288  */
289 #define CPU_CLR_S(cpu, setsize, set) \
290   do { \
291     size_t __cpu = (cpu); \
292     if (__cpu < 8 * (setsize)) \
293       (set)->__bits[__CPU_ELT(__cpu)] &= ~__CPU_MASK(__cpu); \
294   } while (0)
295 
296 /**
297  * [CPU_ISSET](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
298  * whether the given bit is set in a static CPU set.
299  */
300 #define CPU_ISSET(cpu, set)    CPU_ISSET_S(cpu, sizeof(cpu_set_t), set)
301 /**
302  * [CPU_ISSET_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
303  * whether the given bit is set in a dynamic CPU set allocated by `CPU_ALLOC`.
304  */
305 #define CPU_ISSET_S(cpu, setsize, set) \
306   (__extension__ ({ \
307     size_t __cpu = (cpu); \
308     (__cpu < 8 * (setsize)) \
309       ? ((set)->__bits[__CPU_ELT(__cpu)] & __CPU_MASK(__cpu)) != 0 \
310       : 0; \
311   }))
312 
313 /**
314  * [CPU_COUNT](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) counts
315  * how many bits are set in a static CPU set.
316  */
317 #define CPU_COUNT(set)         CPU_COUNT_S(sizeof(cpu_set_t), set)
318 /**
319  * [CPU_COUNT_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) counts
320  * how many bits are set in a dynamic CPU set allocated by `CPU_ALLOC`.
321  */
322 #define CPU_COUNT_S(setsize, set)  __sched_cpucount((setsize), (set))
323 int __sched_cpucount(size_t __set_size, const cpu_set_t* _Nonnull __set);
324 
325 /**
326  * [CPU_EQUAL](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
327  * whether two static CPU sets have the same bits set and cleared as each other.
328  */
329 #define CPU_EQUAL(set1, set2)  CPU_EQUAL_S(sizeof(cpu_set_t), set1, set2)
330 /**
331  * [CPU_EQUAL_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
332  * whether two dynamic CPU sets allocated by `CPU_ALLOC` have the same bits
333  * set and cleared as each other.
334  */
335 #define CPU_EQUAL_S(setsize, set1, set2)  (__builtin_memcmp(set1, set2, setsize) == 0)
336 
337 /**
338  * [CPU_AND](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ands two
339  * static CPU sets.
340  */
341 #define CPU_AND(dst, set1, set2)  __CPU_OP(dst, set1, set2, &)
342 /**
343  * [CPU_AND_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ands two
344  * dynamic CPU sets allocated by `CPU_ALLOC`.
345  */
346 #define CPU_AND_S(setsize, dst, set1, set2)  __CPU_OP_S(setsize, dst, set1, set2, &)
347 
348 /**
349  * [CPU_OR](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ors two
350  * static CPU sets.
351  */
352 #define CPU_OR(dst, set1, set2)   __CPU_OP(dst, set1, set2, |)
353 /**
354  * [CPU_OR_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ors two
355  * dynamic CPU sets allocated by `CPU_ALLOC`.
356  */
357 #define CPU_OR_S(setsize, dst, set1, set2)   __CPU_OP_S(setsize, dst, set1, set2, |)
358 
359 /**
360  * [CPU_XOR](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
361  * exclusive-ors two static CPU sets.
362  */
363 #define CPU_XOR(dst, set1, set2)  __CPU_OP(dst, set1, set2, ^)
364 /**
365  * [CPU_XOR_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
366  * exclusive-ors two dynamic CPU sets allocated by `CPU_ALLOC`.
367  */
368 #define CPU_XOR_S(setsize, dst, set1, set2)  __CPU_OP_S(setsize, dst, set1, set2, ^)
369 
370 #define __CPU_OP(dst, set1, set2, op)  __CPU_OP_S(sizeof(cpu_set_t), dst, set1, set2, op)
371 
372 #define __CPU_OP_S(setsize, dstset, srcset1, srcset2, op) \
373   do { \
374     cpu_set_t* __dst = (dstset); \
375     const __CPU_BITTYPE* __src1 = (srcset1)->__bits; \
376     const __CPU_BITTYPE* __src2 = (srcset2)->__bits; \
377     size_t __nn = 0, __nn_max = (setsize)/sizeof(__CPU_BITTYPE); \
378     for (; __nn < __nn_max; __nn++) \
379       (__dst)->__bits[__nn] = __src1[__nn] op __src2[__nn]; \
380   } while (0)
381 
382 /**
383  * [CPU_ALLOC_SIZE](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
384  * returns the size of a CPU set large enough for CPUs in the range 0..count-1.
385  */
386 #define CPU_ALLOC_SIZE(count) \
387   __CPU_ELT((count) + (__CPU_BITS - 1)) * sizeof(__CPU_BITTYPE)
388 
389 /**
390  * [CPU_ALLOC](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
391  * allocates a CPU set large enough for CPUs in the range 0..count-1.
392  */
393 #define CPU_ALLOC(count)  __sched_cpualloc((count))
394 cpu_set_t* _Nullable __sched_cpualloc(size_t __count);
395 
396 /**
397  * [CPU_FREE](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
398  * deallocates a CPU set allocated by `CPU_ALLOC`.
399  */
400 #define CPU_FREE(set)     __sched_cpufree((set))
401 void __sched_cpufree(cpu_set_t* _Nonnull __set);
402 
403 #endif /* __USE_GNU */
404 
405 __END_DECLS
406