| /******************************************************************************* | |
| D binding for Linux specific scheduler control and thread spawning | |
| methods. | |
| Defines functions sched_setaffinity and sched_getaffinity and the data | |
| types they operate on, as well as clone and unshare and their related | |
| constants. | |
| Copyright: Copyright (c) 2016 Sociomantic Labs. All rights reserved. | |
| License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). | |
| Authors: Nemanja Boric | |
| *******************************************************************************/ | |
| module core.sys.linux.sched; | |
| import core.bitop : popcnt; | |
| import core.stdc.stdlib : malloc, free; | |
| import core.sys.posix.sched; | |
| import core.sys.posix.config; | |
| import core.sys.posix.sys.types; | |
| version (linux): | |
| extern (C): | |
| @nogc: | |
| nothrow: | |
| private // helpers | |
| { | |
| /* Size definition for CPU sets. */ | |
| enum | |
| { | |
| __CPU_SETSIZE = 1024, | |
| __NCPUBITS = 8 * cpu_mask.sizeof, | |
| } | |
| /* Macros */ | |
| /* Basic access functions. */ | |
| size_t __CPUELT()(size_t cpu) pure | |
| { | |
| return cpu / __NCPUBITS; | |
| } | |
| cpu_mask __CPUMASK()(size_t cpu) pure | |
| { | |
| return 1UL << (cpu % __NCPUBITS); | |
| } | |
| cpu_set_t* __CPU_ALLOC()(size_t count) | |
| { | |
| return cast(cpu_set_t*) malloc(__CPU_ALLOC_SIZE(count)); | |
| } | |
| size_t __CPU_ALLOC_SIZE()(size_t count) pure | |
| { | |
| return ((count + __NCPUBITS - 1) / __NCPUBITS) * cpu_mask.sizeof; | |
| } | |
| void __CPU_FREE()(cpu_set_t* set) | |
| { | |
| free(cast(void*) set); | |
| } | |
| cpu_mask __CPU_SET_S()(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure | |
| { | |
| if (cpu < 8 * setsize) | |
| { | |
| cpusetp.__bits[__CPUELT(cpu)] |= __CPUMASK(cpu); | |
| return __CPUMASK(cpu); | |
| } | |
| return 0; | |
| } | |
| bool __CPU_ISSET_S()(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure | |
| { | |
| if (cpu < 8 * setsize) | |
| return (cpusetp.__bits[__CPUELT(cpu)] & __CPUMASK(cpu)) != 0; | |
| return false; | |
| } | |
| int __CPU_COUNT_S()(size_t setsize, cpu_set_t* cpusetp) pure | |
| { | |
| int s = 0; | |
| foreach (i; cpusetp.__bits[0 .. (setsize / cpu_mask.sizeof)]) | |
| s += popcnt(i); | |
| return s; | |
| } | |
| } | |
| /// Type for array elements in 'cpu_set_t'. | |
| alias cpu_mask = c_ulong; | |
| /// Data structure to describe CPU mask. | |
| struct cpu_set_t | |
| { | |
| cpu_mask[__CPU_SETSIZE / __NCPUBITS] __bits; | |
| } | |
| /// Access macros for 'cpu_set' (missing a lot of them) | |
| cpu_set_t* CPU_ALLOC()(size_t count) | |
| { | |
| return __CPU_ALLOC(count); | |
| } | |
| size_t CPU_ALLOC_SIZE()(size_t count) pure | |
| { | |
| return __CPU_ALLOC_SIZE(count); | |
| } | |
| void CPU_FREE()(cpu_set_t* set) | |
| { | |
| __CPU_FREE(set); | |
| } | |
| cpu_mask CPU_SET()(size_t cpu, cpu_set_t* cpusetp) pure | |
| { | |
| return __CPU_SET_S(cpu, cpu_set_t.sizeof, cpusetp); | |
| } | |
| bool CPU_ISSET()(size_t cpu, cpu_set_t* cpusetp) pure | |
| { | |
| return __CPU_ISSET_S(cpu, cpu_set_t.sizeof, cpusetp); | |
| } | |
| int CPU_COUNT()(cpu_set_t* cpusetp) pure | |
| { | |
| return __CPU_COUNT_S(cpu_set_t.sizeof, cpusetp); | |
| } | |
| int CPU_COUNT_S()(size_t setsize, cpu_set_t* cpusetp) pure | |
| { | |
| return __CPU_COUNT_S(setsize, cpusetp); | |
| } | |
| /* Scheduler control functions */ | |
| int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); | |
| int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); | |
| /* Clone and related functions and constants */ | |
| int clone(int function(void*), void* child_stack, int flags, void* arg, ...); | |
| int unshare(int flags) @trusted; | |
| version (CRuntime_Glibc) | |
| { | |
| /* Determine CPU on which the calling thread is running */ | |
| int sched_getcpu(); | |
| } | |
| else version (CRuntime_Musl) | |
| { | |
| int sched_getcpu(); | |
| } | |
| /* Reassociate the calling thread with namespace referred to by fd */ | |
| int setns(int fd, int nstype); | |
| enum CLONE_FILES = 0x400; | |
| enum CLONE_FS = 0x200; | |
| enum CLONE_NEWCGROUP = 0x2000000; | |
| enum CLONE_NEWIPC = 0x8000000; | |
| enum CLONE_NEWNET = 0x40000000; | |
| enum CLONE_NEWNS = 0x20000; | |
| enum CLONE_NEWPID = 0x20000000; | |
| enum CLONE_NEWUSER = 0x10000000; | |
| enum CLONE_NEWUTS = 0x4000000; | |
| enum CLONE_SIGHAND = 0x800; | |
| enum CLONE_SYSVSEM = 0x40000; | |
| enum CLONE_THREAD = 0x10000; | |
| enum CLONE_VFORK = 0x4000; | |
| enum CLONE_VM = 0x100; |