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 <sys/cdefs.h>
37  
38  #include <bits/timespec.h>
39  #include <linux/sched.h>
40  
41  __BEGIN_DECLS
42  
43  /*
44   * @def SCHED_NORMAL
45   * The standard (as opposed to real-time) round-robin scheduling policy.
46   *
47   * (Linux's name for POSIX's SCHED_OTHER.)
48   *
49   * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
50   */
51  
52  /*
53   * @def SCHED_FIFO
54   * The real-time first-in/first-out scheduling policy.
55   *
56   * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
57   */
58  
59  /*
60   * @def SCHED_RR
61   * The real-time round-robin policy. (See also SCHED_NORMAL/SCHED_OTHER.)
62   *
63   * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
64   */
65  
66  /*
67   * @def SCHED_BATCH
68   * The batch scheduling policy.
69   *
70   * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
71   */
72  
73  /*
74   * @def SCHED_IDLE
75   * The low priority "only when otherwise idle" scheduling priority.
76   *
77   * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
78   */
79  
80  /*
81   * @def SCHED_DEADLINE
82   * The deadline scheduling policy.
83   *
84   * See [sched(7)](https://man7.org/linux/man-pages/man7/sched.7.html)
85   */
86  
87  /*
88   * The standard (as opposed to real-time) round-robin scheduling policy.
89   *
90   * (POSIX's name for Linux's SCHED_NORMAL.)
91   */
92  #define SCHED_OTHER SCHED_NORMAL
93  
94  /**
95   * See sched_getparam()/sched_setparam() and
96   * sched_getscheduler()/sched_setscheduler().
97   */
98  struct sched_param {
99    int sched_priority;
100  };
101  
102  /**
103   * [sched_setscheduler(2)](https://man7.org/linux/man-pages/man2/sched_setscheduler.2.html)
104   * sets the scheduling policy and associated parameters for the given thread.
105   *
106   * Returns 0 on success and returns -1 and sets `errno` on failure.
107   */
108  int sched_setscheduler(pid_t __pid, int __policy, const struct sched_param* _Nonnull __param);
109  
110  /**
111   * [sched_getscheduler(2)](https://man7.org/linux/man-pages/man2/sched_getscheduler.2)
112   * gets the scheduling policy for the given thread.
113   *
114   * Returns a non-negative thread policy on success and returns -1 and sets
115   * `errno` on failure.
116   */
117  int sched_getscheduler(pid_t __pid);
118  
119  /**
120   * [sched_yield(2)](https://man7.org/linux/man-pages/man2/sched_yield.2.html)
121   * voluntarily gives up using the CPU so that another thread can run.
122   *
123   * Returns 0 on success and returns -1 and sets `errno` on failure.
124   */
125  int sched_yield(void);
126  
127  /**
128   * [sched_get_priority_max(2)](https://man7.org/linux/man-pages/man2/sched_get_priority_max.2.html)
129   * gets the maximum priority value allowed for the given scheduling policy.
130   *
131   * Returns a priority on success and returns -1 and sets `errno` on failure.
132   */
133  int sched_get_priority_max(int __policy);
134  
135  /**
136   * [sched_get_priority_min(2)](https://man7.org/linux/man-pages/man2/sched_get_priority_min.2.html)
137   * gets the minimum priority value allowed for the given scheduling policy.
138   *
139   * Returns a priority on success and returns -1 and sets `errno` on failure.
140   */
141  int sched_get_priority_min(int __policy);
142  
143  /**
144   * [sched_setparam(2)](https://man7.org/linux/man-pages/man2/sched_setparam.2.html)
145   * sets the scheduling parameters for the given thread.
146   *
147   * Returns 0 on success and returns -1 and sets `errno` on failure.
148   */
149  int sched_setparam(pid_t __pid, const struct sched_param* _Nonnull __param);
150  
151  /**
152   * [sched_getparam(2)](https://man7.org/linux/man-pages/man2/sched_getparam.2.html)
153   * gets the scheduling parameters for the given thread.
154   *
155   * Returns 0 on success and returns -1 and sets `errno` on failure.
156   */
157  int sched_getparam(pid_t __pid, struct sched_param* _Nonnull __param);
158  
159  /**
160   * [sched_rr_get_interval(2)](https://man7.org/linux/man-pages/man2/sched_rr_get_interval.2.html)
161   * queries the round-robin time quantum for the given thread.
162   *
163   * Returns 0 on success and returns -1 and sets `errno` on failure.
164   */
165  int sched_rr_get_interval(pid_t __pid, struct timespec* _Nonnull __quantum);
166  
167  #if defined(__USE_GNU)
168  
169  /**
170   * [clone(2)](https://man7.org/linux/man-pages/man2/clone.2.html)
171   * creates a new child process.
172   *
173   * Returns the pid of the child to the caller on success and
174   * returns -1 and sets `errno` on failure.
175   */
176  int clone(int (* __BIONIC_COMPLICATED_NULLNESS __fn)(void* __BIONIC_COMPLICATED_NULLNESS ), void* __BIONIC_COMPLICATED_NULLNESS __child_stack, int __flags, void* _Nullable __arg, ...);
177  
178  /**
179   * [unshare(2)](https://man7.org/linux/man-pages/man2/unshare.2.html)
180   * disassociates part of the caller's execution context.
181   *
182   * Returns 0 on success and returns -1 and sets `errno` on failure.
183   */
184  int unshare(int __flags);
185  
186  /**
187   * [setns(2)](https://man7.org/linux/man-pages/man2/setns.2.html)
188   * reassociates a thread with a different namespace.
189   *
190   * Returns 0 on success and returns -1 and sets `errno` on failure.
191   */
192  int setns(int __fd, int __ns_type);
193  
194  /**
195   * [sched_getcpu(3)](https://man7.org/linux/man-pages/man3/sched_getcpu.3.html)
196   * reports which CPU the caller is running on.
197   *
198   * Returns a non-negative CPU number on success and returns -1 and sets
199   * `errno` on failure.
200   */
201  int sched_getcpu(void);
202  
203  #ifdef __LP64__
204  #define CPU_SETSIZE 1024
205  #else
206  #define CPU_SETSIZE 32
207  #endif
208  
209  #define __CPU_BITTYPE  unsigned long int  /* mandated by the kernel  */
210  #define __CPU_BITS     (8 * sizeof(__CPU_BITTYPE))
211  #define __CPU_ELT(x)   ((x) / __CPU_BITS)
212  #define __CPU_MASK(x)  ((__CPU_BITTYPE)1 << ((x) & (__CPU_BITS - 1)))
213  
214  /**
215   * [cpu_set_t](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) is a
216   * statically-sized CPU set. See `CPU_ALLOC` for dynamically-sized CPU sets.
217   */
218  typedef struct {
219    __CPU_BITTYPE  __bits[ CPU_SETSIZE / __CPU_BITS ];
220  } cpu_set_t;
221  
222  /**
223   * [sched_setaffinity(2)](https://man7.org/linux/man-pages/man2/sched_setaffinity.2.html)
224   * sets the CPU affinity mask for the given thread.
225   *
226   * Returns 0 on success and returns -1 and sets `errno` on failure.
227   */
228  int sched_setaffinity(pid_t __pid, size_t __set_size, const cpu_set_t* _Nonnull __set);
229  
230  /**
231   * [sched_getaffinity(2)](https://man7.org/linux/man-pages/man2/sched_getaffinity.2.html)
232   * gets the CPU affinity mask for the given thread.
233   *
234   * Returns 0 on success and returns -1 and sets `errno` on failure.
235   */
236  int sched_getaffinity(pid_t __pid, size_t __set_size, cpu_set_t* _Nonnull __set);
237  
238  /**
239   * [CPU_ZERO](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears all
240   * bits in a static CPU set.
241   */
242  #define CPU_ZERO(set)          CPU_ZERO_S(sizeof(cpu_set_t), set)
243  /**
244   * [CPU_ZERO_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears all
245   * bits in a dynamic CPU set allocated by `CPU_ALLOC`.
246   */
247  #define CPU_ZERO_S(setsize, set)  __builtin_memset(set, 0, setsize)
248  
249  /**
250   * [CPU_SET](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) sets one
251   * bit in a static CPU set.
252   */
253  #define CPU_SET(cpu, set)      CPU_SET_S(cpu, sizeof(cpu_set_t), set)
254  /**
255   * [CPU_SET_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) sets one
256   * bit in a dynamic CPU set allocated by `CPU_ALLOC`.
257   */
258  #define CPU_SET_S(cpu, setsize, set) \
259    do { \
260      size_t __cpu = (cpu); \
261      if (__cpu < 8 * (setsize)) \
262        (set)->__bits[__CPU_ELT(__cpu)] |= __CPU_MASK(__cpu); \
263    } while (0)
264  
265  /**
266   * [CPU_CLR](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears one
267   * bit in a static CPU set.
268   */
269  #define CPU_CLR(cpu, set)      CPU_CLR_S(cpu, sizeof(cpu_set_t), set)
270  /**
271   * [CPU_CLR_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) clears one
272   * bit in a dynamic CPU set allocated by `CPU_ALLOC`.
273   */
274  #define CPU_CLR_S(cpu, setsize, set) \
275    do { \
276      size_t __cpu = (cpu); \
277      if (__cpu < 8 * (setsize)) \
278        (set)->__bits[__CPU_ELT(__cpu)] &= ~__CPU_MASK(__cpu); \
279    } while (0)
280  
281  /**
282   * [CPU_ISSET](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
283   * whether the given bit is set in a static CPU set.
284   */
285  #define CPU_ISSET(cpu, set)    CPU_ISSET_S(cpu, sizeof(cpu_set_t), set)
286  /**
287   * [CPU_ISSET_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
288   * whether the given bit is set in a dynamic CPU set allocated by `CPU_ALLOC`.
289   */
290  #define CPU_ISSET_S(cpu, setsize, set) \
291    (__extension__ ({ \
292      size_t __cpu = (cpu); \
293      (__cpu < 8 * (setsize)) \
294        ? ((set)->__bits[__CPU_ELT(__cpu)] & __CPU_MASK(__cpu)) != 0 \
295        : 0; \
296    }))
297  
298  /**
299   * [CPU_COUNT](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) counts
300   * how many bits are set in a static CPU set.
301   */
302  #define CPU_COUNT(set)         CPU_COUNT_S(sizeof(cpu_set_t), set)
303  /**
304   * [CPU_COUNT_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) counts
305   * how many bits are set in a dynamic CPU set allocated by `CPU_ALLOC`.
306   */
307  #define CPU_COUNT_S(setsize, set)  __sched_cpucount((setsize), (set))
308  int __sched_cpucount(size_t __set_size, const cpu_set_t* _Nonnull __set);
309  
310  /**
311   * [CPU_EQUAL](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
312   * whether two static CPU sets have the same bits set and cleared as each other.
313   */
314  #define CPU_EQUAL(set1, set2)  CPU_EQUAL_S(sizeof(cpu_set_t), set1, set2)
315  /**
316   * [CPU_EQUAL_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) tests
317   * whether two dynamic CPU sets allocated by `CPU_ALLOC` have the same bits
318   * set and cleared as each other.
319   */
320  #define CPU_EQUAL_S(setsize, set1, set2)  (__builtin_memcmp(set1, set2, setsize) == 0)
321  
322  /**
323   * [CPU_AND](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ands two
324   * static CPU sets.
325   */
326  #define CPU_AND(dst, set1, set2)  __CPU_OP(dst, set1, set2, &)
327  /**
328   * [CPU_AND_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ands two
329   * dynamic CPU sets allocated by `CPU_ALLOC`.
330   */
331  #define CPU_AND_S(setsize, dst, set1, set2)  __CPU_OP_S(setsize, dst, set1, set2, &)
332  
333  /**
334   * [CPU_OR](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ors two
335   * static CPU sets.
336   */
337  #define CPU_OR(dst, set1, set2)   __CPU_OP(dst, set1, set2, |)
338  /**
339   * [CPU_OR_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html) ors two
340   * dynamic CPU sets allocated by `CPU_ALLOC`.
341   */
342  #define CPU_OR_S(setsize, dst, set1, set2)   __CPU_OP_S(setsize, dst, set1, set2, |)
343  
344  /**
345   * [CPU_XOR](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
346   * exclusive-ors two static CPU sets.
347   */
348  #define CPU_XOR(dst, set1, set2)  __CPU_OP(dst, set1, set2, ^)
349  /**
350   * [CPU_XOR_S](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
351   * exclusive-ors two dynamic CPU sets allocated by `CPU_ALLOC`.
352   */
353  #define CPU_XOR_S(setsize, dst, set1, set2)  __CPU_OP_S(setsize, dst, set1, set2, ^)
354  
355  #define __CPU_OP(dst, set1, set2, op)  __CPU_OP_S(sizeof(cpu_set_t), dst, set1, set2, op)
356  
357  #define __CPU_OP_S(setsize, dstset, srcset1, srcset2, op) \
358    do { \
359      cpu_set_t* __dst = (dstset); \
360      const __CPU_BITTYPE* __src1 = (srcset1)->__bits; \
361      const __CPU_BITTYPE* __src2 = (srcset2)->__bits; \
362      size_t __nn = 0, __nn_max = (setsize)/sizeof(__CPU_BITTYPE); \
363      for (; __nn < __nn_max; __nn++) \
364        (__dst)->__bits[__nn] = __src1[__nn] op __src2[__nn]; \
365    } while (0)
366  
367  /**
368   * [CPU_ALLOC_SIZE](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
369   * returns the size of a CPU set large enough for CPUs in the range 0..count-1.
370   */
371  #define CPU_ALLOC_SIZE(count) \
372    __CPU_ELT((count) + (__CPU_BITS - 1)) * sizeof(__CPU_BITTYPE)
373  
374  /**
375   * [CPU_ALLOC](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
376   * allocates a CPU set large enough for CPUs in the range 0..count-1.
377   */
378  #define CPU_ALLOC(count)  __sched_cpualloc((count))
379  cpu_set_t* _Nullable __sched_cpualloc(size_t __count);
380  
381  /**
382   * [CPU_FREE](https://man7.org/linux/man-pages/man3/CPU_SET.3.html)
383   * deallocates a CPU set allocated by `CPU_ALLOC`.
384   */
385  #define CPU_FREE(set)     __sched_cpufree((set))
386  void __sched_cpufree(cpu_set_t* _Nonnull __set);
387  
388  #endif /* __USE_GNU */
389  
390  __END_DECLS
391