• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)](https://man7.org/linux/man-pages/man2/sched_setscheduler.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)](https://man7.org/linux/man-pages/man2/sched_getscheduler.2)
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 int clone(int (* __BIONIC_COMPLICATED_NULLNESS __fn)(void* __BIONIC_COMPLICATED_NULLNESS ), void* __BIONIC_COMPLICATED_NULLNESS __child_stack, int __flags, void* _Nullable __arg, ...);
176 
177 /**
178  * [unshare(2)](http://man7.org/linux/man-pages/man2/unshare.2.html)
179  * disassociates part of the caller's execution context.
180  *
181  * Returns 0 on success and returns -1 and sets `errno` on failure.
182  */
183 int unshare(int __flags);
184 
185 /**
186  * [setns(2)](http://man7.org/linux/man-pages/man2/setns.2.html)
187  * reassociates a thread with a different namespace.
188  *
189  * Returns 0 on success and returns -1 and sets `errno` on failure.
190  */
191 int setns(int __fd, int __ns_type);
192 
193 /**
194  * [sched_getcpu(3)](http://man7.org/linux/man-pages/man3/sched_getcpu.3.html)
195  * reports which CPU the caller is running on.
196  *
197  * Returns a non-negative CPU number on success and returns -1 and sets
198  * `errno` on failure.
199  */
200 int sched_getcpu(void);
201 
202 #ifdef __LP64__
203 #define CPU_SETSIZE 1024
204 #else
205 #define CPU_SETSIZE 32
206 #endif
207 
208 #define __CPU_BITTYPE  unsigned long int  /* mandated by the kernel  */
209 #define __CPU_BITS     (8 * sizeof(__CPU_BITTYPE))
210 #define __CPU_ELT(x)   ((x) / __CPU_BITS)
211 #define __CPU_MASK(x)  ((__CPU_BITTYPE)1 << ((x) & (__CPU_BITS - 1)))
212 
213 /**
214  * [cpu_set_t](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) is a
215  * statically-sized CPU set. See `CPU_ALLOC` for dynamically-sized CPU sets.
216  */
217 typedef struct {
218   __CPU_BITTYPE  __bits[ CPU_SETSIZE / __CPU_BITS ];
219 } cpu_set_t;
220 
221 /**
222  * [sched_setaffinity(2)](http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html)
223  * sets the CPU affinity mask for the given thread.
224  *
225  * Returns 0 on success and returns -1 and sets `errno` on failure.
226  */
227 int sched_setaffinity(pid_t __pid, size_t __set_size, const cpu_set_t* _Nonnull __set);
228 
229 /**
230  * [sched_getaffinity(2)](http://man7.org/linux/man-pages/man2/sched_getaffinity.2.html)
231  * gets the CPU affinity mask for the given thread.
232  *
233  * Returns 0 on success and returns -1 and sets `errno` on failure.
234  */
235 int sched_getaffinity(pid_t __pid, size_t __set_size, cpu_set_t* _Nonnull __set);
236 
237 /**
238  * [CPU_ZERO](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears all
239  * bits in a static CPU set.
240  */
241 #define CPU_ZERO(set)          CPU_ZERO_S(sizeof(cpu_set_t), set)
242 /**
243  * [CPU_ZERO_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears all
244  * bits in a dynamic CPU set allocated by `CPU_ALLOC`.
245  */
246 #define CPU_ZERO_S(setsize, set)  __builtin_memset(set, 0, setsize)
247 
248 /**
249  * [CPU_SET](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) sets one
250  * bit in a static CPU set.
251  */
252 #define CPU_SET(cpu, set)      CPU_SET_S(cpu, sizeof(cpu_set_t), set)
253 /**
254  * [CPU_SET_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) sets one
255  * bit in a dynamic CPU set allocated by `CPU_ALLOC`.
256  */
257 #define CPU_SET_S(cpu, setsize, set) \
258   do { \
259     size_t __cpu = (cpu); \
260     if (__cpu < 8 * (setsize)) \
261       (set)->__bits[__CPU_ELT(__cpu)] |= __CPU_MASK(__cpu); \
262   } while (0)
263 
264 /**
265  * [CPU_CLR](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears one
266  * bit in a static CPU set.
267  */
268 #define CPU_CLR(cpu, set)      CPU_CLR_S(cpu, sizeof(cpu_set_t), set)
269 /**
270  * [CPU_CLR_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears one
271  * bit in a dynamic CPU set allocated by `CPU_ALLOC`.
272  */
273 #define CPU_CLR_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_ISSET](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
282  * whether the given bit is set in a static CPU set.
283  */
284 #define CPU_ISSET(cpu, set)    CPU_ISSET_S(cpu, sizeof(cpu_set_t), set)
285 /**
286  * [CPU_ISSET_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
287  * whether the given bit is set in a dynamic CPU set allocated by `CPU_ALLOC`.
288  */
289 #define CPU_ISSET_S(cpu, setsize, set) \
290   (__extension__ ({ \
291     size_t __cpu = (cpu); \
292     (__cpu < 8 * (setsize)) \
293       ? ((set)->__bits[__CPU_ELT(__cpu)] & __CPU_MASK(__cpu)) != 0 \
294       : 0; \
295   }))
296 
297 /**
298  * [CPU_COUNT](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) counts
299  * how many bits are set in a static CPU set.
300  */
301 #define CPU_COUNT(set)         CPU_COUNT_S(sizeof(cpu_set_t), set)
302 /**
303  * [CPU_COUNT_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) counts
304  * how many bits are set in a dynamic CPU set allocated by `CPU_ALLOC`.
305  */
306 #define CPU_COUNT_S(setsize, set)  __sched_cpucount((setsize), (set))
307 int __sched_cpucount(size_t __set_size, const cpu_set_t* _Nonnull __set);
308 
309 /**
310  * [CPU_EQUAL](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
311  * whether two static CPU sets have the same bits set and cleared as each other.
312  */
313 #define CPU_EQUAL(set1, set2)  CPU_EQUAL_S(sizeof(cpu_set_t), set1, set2)
314 /**
315  * [CPU_EQUAL_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
316  * whether two dynamic CPU sets allocated by `CPU_ALLOC` have the same bits
317  * set and cleared as each other.
318  */
319 #define CPU_EQUAL_S(setsize, set1, set2)  (__builtin_memcmp(set1, set2, setsize) == 0)
320 
321 /**
322  * [CPU_AND](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ands two
323  * static CPU sets.
324  */
325 #define CPU_AND(dst, set1, set2)  __CPU_OP(dst, set1, set2, &)
326 /**
327  * [CPU_AND_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ands two
328  * dynamic CPU sets allocated by `CPU_ALLOC`.
329  */
330 #define CPU_AND_S(setsize, dst, set1, set2)  __CPU_OP_S(setsize, dst, set1, set2, &)
331 
332 /**
333  * [CPU_OR](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ors two
334  * static CPU sets.
335  */
336 #define CPU_OR(dst, set1, set2)   __CPU_OP(dst, set1, set2, |)
337 /**
338  * [CPU_OR_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ors two
339  * dynamic CPU sets allocated by `CPU_ALLOC`.
340  */
341 #define CPU_OR_S(setsize, dst, set1, set2)   __CPU_OP_S(setsize, dst, set1, set2, |)
342 
343 /**
344  * [CPU_XOR](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
345  * exclusive-ors two static CPU sets.
346  */
347 #define CPU_XOR(dst, set1, set2)  __CPU_OP(dst, set1, set2, ^)
348 /**
349  * [CPU_XOR_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
350  * exclusive-ors two dynamic CPU sets allocated by `CPU_ALLOC`.
351  */
352 #define CPU_XOR_S(setsize, dst, set1, set2)  __CPU_OP_S(setsize, dst, set1, set2, ^)
353 
354 #define __CPU_OP(dst, set1, set2, op)  __CPU_OP_S(sizeof(cpu_set_t), dst, set1, set2, op)
355 
356 #define __CPU_OP_S(setsize, dstset, srcset1, srcset2, op) \
357   do { \
358     cpu_set_t* __dst = (dstset); \
359     const __CPU_BITTYPE* __src1 = (srcset1)->__bits; \
360     const __CPU_BITTYPE* __src2 = (srcset2)->__bits; \
361     size_t __nn = 0, __nn_max = (setsize)/sizeof(__CPU_BITTYPE); \
362     for (; __nn < __nn_max; __nn++) \
363       (__dst)->__bits[__nn] = __src1[__nn] op __src2[__nn]; \
364   } while (0)
365 
366 /**
367  * [CPU_ALLOC_SIZE](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
368  * returns the size of a CPU set large enough for CPUs in the range 0..count-1.
369  */
370 #define CPU_ALLOC_SIZE(count) \
371   __CPU_ELT((count) + (__CPU_BITS - 1)) * sizeof(__CPU_BITTYPE)
372 
373 /**
374  * [CPU_ALLOC](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
375  * allocates a CPU set large enough for CPUs in the range 0..count-1.
376  */
377 #define CPU_ALLOC(count)  __sched_cpualloc((count))
378 cpu_set_t* _Nullable __sched_cpualloc(size_t __count);
379 
380 /**
381  * [CPU_FREE](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
382  * deallocates a CPU set allocated by `CPU_ALLOC`.
383  */
384 #define CPU_FREE(set)     __sched_cpufree((set))
385 void __sched_cpufree(cpu_set_t* _Nonnull __set);
386 
387 #endif /* __USE_GNU */
388 
389 __END_DECLS
390