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