| /******************************************************************************* |
| |
| 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 c_ulong cpu_mask; |
| |
| /// 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(); |
| } |
| |
| /* 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; |