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