1/******************************************************************************* 2 3 D binding for Linux specific scheduler control and thread spawning 4 methods. 5 6 Defines functions sched_setaffinity and sched_getaffinity and the data 7 types they operate on, as well as clone and unshare and their related 8 constants. 9 10 Copyright: Copyright (c) 2016 Sociomantic Labs. All rights reserved. 11 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 12 Authors: Nemanja Boric 13 14*******************************************************************************/ 15 16 17module core.sys.linux.sched; 18 19import core.bitop : popcnt; 20import core.stdc.stdlib : malloc, free; 21import core.sys.posix.sched; 22import core.sys.posix.config; 23import core.sys.posix.sys.types; 24 25version (linux): 26extern (C): 27@nogc: 28nothrow: 29@system: 30 31 32private // helpers 33{ 34 35 /* Size definition for CPU sets. */ 36 enum 37 { 38 __CPU_SETSIZE = 1024, 39 __NCPUBITS = 8 * cpu_mask.sizeof, 40 } 41 42 /* Macros */ 43 44 /* Basic access functions. */ 45 size_t __CPUELT(size_t cpu) pure 46 { 47 return cpu / __NCPUBITS; 48 } 49 cpu_mask __CPUMASK(size_t cpu) pure 50 { 51 return 1UL << (cpu % __NCPUBITS); 52 } 53 54 cpu_set_t* __CPU_ALLOC(size_t count) 55 { 56 return cast(cpu_set_t*) malloc(__CPU_ALLOC_SIZE(count)); 57 } 58 59 size_t __CPU_ALLOC_SIZE(size_t count) pure 60 { 61 return ((count + __NCPUBITS - 1) / __NCPUBITS) * cpu_mask.sizeof; 62 } 63 64 void __CPU_FREE(cpu_set_t* set) 65 { 66 free(cast(void*) set); 67 } 68 69 cpu_mask __CPU_SET_S(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure 70 { 71 if (cpu < 8 * setsize) 72 { 73 cpusetp.__bits[__CPUELT(cpu)] |= __CPUMASK(cpu); 74 return __CPUMASK(cpu); 75 } 76 77 return 0; 78 } 79 80 bool __CPU_ISSET_S(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure 81 { 82 if (cpu < 8 * setsize) 83 return (cpusetp.__bits[__CPUELT(cpu)] & __CPUMASK(cpu)) != 0; 84 return false; 85 } 86 87 int __CPU_COUNT_S(size_t setsize, cpu_set_t* cpusetp) pure 88 { 89 int s = 0; 90 foreach (i; cpusetp.__bits[0 .. (setsize / cpu_mask.sizeof)]) 91 s += popcnt(i); 92 return s; 93 } 94} 95 96/// Type for array elements in 'cpu_set_t'. 97alias c_ulong cpu_mask; 98 99/// Data structure to describe CPU mask. 100struct cpu_set_t 101{ 102 cpu_mask[__CPU_SETSIZE / __NCPUBITS] __bits; 103} 104 105/// Access macros for 'cpu_set' (missing a lot of them) 106 107cpu_set_t* CPU_ALLOC(size_t count) 108{ 109 return __CPU_ALLOC(count); 110} 111 112size_t CPU_ALLOC_SIZE(size_t count) pure 113{ 114 return __CPU_ALLOC_SIZE(count); 115} 116 117void CPU_FREE(cpu_set_t* set) 118{ 119 __CPU_FREE(set); 120} 121 122cpu_mask CPU_SET(size_t cpu, cpu_set_t* cpusetp) pure 123{ 124 return __CPU_SET_S(cpu, cpu_set_t.sizeof, cpusetp); 125} 126 127bool CPU_ISSET(size_t cpu, cpu_set_t* cpusetp) pure 128{ 129 return __CPU_ISSET_S(cpu, cpu_set_t.sizeof, cpusetp); 130} 131 132int CPU_COUNT(cpu_set_t* cpusetp) pure 133{ 134 return __CPU_COUNT_S(cpu_set_t.sizeof, cpusetp); 135} 136 137int CPU_COUNT_S(size_t setsize, cpu_set_t* cpusetp) pure 138{ 139 return __CPU_COUNT_S(setsize, cpusetp); 140} 141 142/* Scheduler control functions */ 143int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); 144int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask); 145 146/* Clone and related functions and constants */ 147int clone(int function(void*), void* child_stack, int flags, void* arg, ...); 148int unshare(int flags) @trusted; 149 150version (CRuntime_Glibc) 151{ 152 /* Determine CPU on which the calling thread is running */ 153 int sched_getcpu(); 154} 155 156/* Reassociate the calling thread with namespace referred to by fd */ 157int setns(int fd, int nstype); 158 159enum CLONE_FILES = 0x400; 160enum CLONE_FS = 0x200; 161enum CLONE_NEWCGROUP = 0x2000000; 162enum CLONE_NEWIPC = 0x8000000; 163enum CLONE_NEWNET = 0x40000000; 164enum CLONE_NEWNS = 0x20000; 165enum CLONE_NEWPID = 0x20000000; 166enum CLONE_NEWUSER = 0x10000000; 167enum CLONE_NEWUTS = 0x4000000; 168enum CLONE_SIGHAND = 0x800; 169enum CLONE_SYSVSEM = 0x40000; 170enum CLONE_THREAD = 0x10000; 171enum CLONE_VFORK = 0x4000; 172enum CLONE_VM = 0x100; 173