summaryrefslogtreecommitdiff
path: root/libphobos/libdruntime/core/sys/linux/sched.d
blob: 5cd512e826301a4d36551e935608983c7062c197 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*******************************************************************************

    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;