~ubuntu-branches/ubuntu/utopic/numactl/utopic

« back to all changes in this revision

Viewing changes to libnuma.c

  • Committer: Bazaar Package Importer
  • Author(s): Ian Wienand
  • Date: 2005-11-25 17:04:25 UTC
  • Revision ID: james.westby@ubuntu.com-20051125170425-62ged0kz3ztiqazq
Tags: upstream-0.7pre2
ImportĀ upstreamĀ versionĀ 0.7pre2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Simple NUMA library.
 
2
   Copyright (C) 2003,2004 Andi Kleen, SuSE Labs.
 
3
 
 
4
   libnuma is free software; you can redistribute it and/or
 
5
   modify it under the terms of the GNU Lesser General Public
 
6
   License as published by the Free Software Foundation; version
 
7
   2.1.
 
8
 
 
9
   libnuma is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
   Lesser General Public License for more details.
 
13
 
 
14
   You should find a copy of v2.1 of the GNU Lesser General Public License
 
15
   somewhere on your Linux system; if not, write to the Free Software 
 
16
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 
17
 
 
18
   All calls are undefined when numa_available returns an error. */
 
19
#define _GNU_SOURCE 1
 
20
#include <stdlib.h>
 
21
#include <stdio.h>
 
22
#include <unistd.h>
 
23
#include <string.h>
 
24
#include <sched.h>
 
25
#include <dirent.h>
 
26
#include <errno.h>
 
27
#include <stdarg.h>
 
28
#include <ctype.h>
 
29
 
 
30
#include <sys/mman.h>
 
31
#include <limits.h>
 
32
 
 
33
#include "numaif.h"
 
34
#include "numa.h"
 
35
#include "numaint.h"
 
36
#include "util.h"
 
37
 
 
38
#define WEAK __attribute__((weak))
 
39
 
 
40
#define CPU_BUFFER_SIZE 4096     /* This limits you to 32768 CPUs */
 
41
 
 
42
nodemask_t numa_no_nodes;
 
43
nodemask_t numa_all_nodes;
 
44
 
 
45
#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
 
46
#warning "not threadsafe"
 
47
#define __thread
 
48
#endif
 
49
 
 
50
static __thread int bind_policy = MPOL_BIND; 
 
51
static __thread int mbind_flags = 0;
 
52
 
 
53
int numa_exit_on_error = 0;
 
54
 
 
55
make_internal_alias(numa_exit_on_error);
 
56
 
 
57
enum numa_warn { 
 
58
        W_nosysfs,
 
59
        W_noproc,
 
60
        W_badmeminfo,
 
61
        W_nosysfs2,
 
62
        W_cpumap,
 
63
        W_numcpus,
 
64
        W_noderunmask,
 
65
}; 
 
66
 
 
67
/* Next two can be overwritten by the application for different error handling */
 
68
WEAK void numa_error(char *where) 
 
69
 
70
        int olde = errno;
 
71
        perror(where); 
 
72
        if (numa_exit_on_error_int)
 
73
                exit(1); 
 
74
        errno = olde;
 
75
 
76
 
 
77
make_internal_alias(numa_error);
 
78
 
 
79
WEAK void numa_warn(int num, char *fmt, ...) 
 
80
 
81
        static unsigned warned;
 
82
        va_list ap;
 
83
        int olde = errno;
 
84
        
 
85
        /* Give each warning only once */
 
86
        if ((1<<num) & warned)
 
87
                return; 
 
88
        warned |= (1<<num); 
 
89
 
 
90
        va_start(ap,fmt);
 
91
        fprintf(stderr, "libnuma: Warning: "); 
 
92
        vfprintf(stderr, fmt, ap);
 
93
        fputc('\n', stderr);
 
94
        va_end(ap);
 
95
 
 
96
        errno = olde;
 
97
 
98
 
 
99
make_internal_alias(numa_warn);
 
100
 
 
101
 
 
102
static void setpol(int policy, nodemask_t mask) 
 
103
 
104
        if (set_mempolicy_int(policy, &mask.n[0], NUMA_NUM_NODES+1) < 0) 
 
105
                numa_error_int("set_mempolicy");
 
106
 
107
 
 
108
static void getpol(int *oldpolicy, nodemask_t *oldmask)
 
109
 
110
        if (get_mempolicy_int(oldpolicy, oldmask->n, NUMA_NUM_NODES+1, 0, 0) < 0) 
 
111
                numa_error_int("get_mempolicy");
 
112
 
113
 
 
114
static void dombind(void *mem, size_t size, int pol, nodemask_t *nodes)
 
115
 
116
        if (mbind_int(mem, size, pol, nodes->n, nodes ? NUMA_NUM_NODES+1 : 0, mbind_flags) 
 
117
            < 0) 
 
118
                numa_error_int("mbind"); 
 
119
 
120
 
 
121
/* (undocumented) */
 
122
/* gives the wrong answer for hugetlbfs mappings. */
 
123
int numa_pagesize(void)
 
124
 
125
        static int pagesize;
 
126
        if (pagesize > 0) 
 
127
                return pagesize;
 
128
        pagesize = getpagesize();
 
129
        return pagesize;
 
130
 
131
 
 
132
make_internal_alias(numa_pagesize);
 
133
 
 
134
static int maxnode = -1; 
 
135
static int maxcpus = -1; 
 
136
 
 
137
static int number_of_cpus(void)
 
138
 
139
        char *line = NULL;
 
140
        size_t len = 0;
 
141
        char *s;
 
142
        FILE *f;
 
143
        int cpu;
 
144
        
 
145
        if (maxcpus >= 0) 
 
146
                return maxcpus;
 
147
 
 
148
        f = fopen("/proc/cpuinfo","r"); 
 
149
        if (!f) {
 
150
                int n;
 
151
                unsigned long buffer[CPU_WORDS(8192)];
 
152
                memset(buffer, 0, sizeof(buffer));
 
153
                n = numa_sched_getaffinity_int(getpid(), sizeof(buffer), buffer);
 
154
                if (n >= 0) { 
 
155
                        int i, k;
 
156
                        for (i = 0; i < n / sizeof(long); i++) {
 
157
                                if (!buffer[i])
 
158
                                        continue;
 
159
                                for (k = 0; k< 8; k++) 
 
160
                                        if (buffer[i] & (1<<k))
 
161
                                                maxcpus = i+k;
 
162
                        }
 
163
                        return maxcpus;
 
164
                }
 
165
                numa_warn_int(W_noproc, "/proc not mounted. Assuming zero nodes: %s", 
 
166
                          strerror(errno)); 
 
167
                return 0;
 
168
        }
 
169
        maxcpus = 0;
 
170
        while (getdelim(&line, &len, '\n', f) > 0) { 
 
171
                if (strncmp(line,"processor",9))
 
172
                        continue;
 
173
                s = line + strcspn(line, "0123456789"); 
 
174
                if (sscanf(s, "%d", &cpu) == 1 && cpu > maxcpus) 
 
175
                        maxcpus = cpu;
 
176
        } 
 
177
        free(line);
 
178
        fclose(f); 
 
179
        return maxcpus;
 
180
 
181
 
 
182
static int fallback_max_node(void)
 
183
{
 
184
        numa_warn_int(W_nosysfs, "/sys not mounted or no numa system. Assuming one node per CPU: %s",
 
185
                  strerror(errno));
 
186
        maxnode = number_of_cpus();     
 
187
        return maxnode;
 
188
}
 
189
 
 
190
int numa_max_node(void)
 
191
{
 
192
        DIR *d;
 
193
        struct dirent *de;
 
194
        int found;
 
195
 
 
196
        /* No hotplug yet. */
 
197
        if (maxnode >= 0) 
 
198
                return maxnode;
 
199
        d = opendir("/sys/devices/system/node"); 
 
200
        if (!d)
 
201
                return fallback_max_node();
 
202
        found = 0;
 
203
        while ((de = readdir(d)) != NULL) { 
 
204
                int nd;
 
205
                if (strncmp(de->d_name, "node", 4))
 
206
                        continue;
 
207
                found++;
 
208
                nd = strtoul(de->d_name+4, NULL, 0); 
 
209
                if (maxnode < nd) 
 
210
                        maxnode = nd; 
 
211
        } 
 
212
        closedir(d); 
 
213
        if (found == 0) 
 
214
                return fallback_max_node();
 
215
        return maxnode;
 
216
 
217
 
 
218
make_internal_alias(numa_max_node);
 
219
 
 
220
/* (cache the result?) */
 
221
long long numa_node_size64(int node, long long *freep)
 
222
 
223
        size_t len = 0;
 
224
        char *line = NULL;
 
225
        long long size = -1;
 
226
        FILE *f; 
 
227
        char fn[64];
 
228
        int ok = 0;
 
229
        int required = freep ? 2 : 1; 
 
230
 
 
231
        if (freep) 
 
232
                *freep = -1; 
 
233
        sprintf(fn,"/sys/devices/system/node/node%d/meminfo", node); 
 
234
        f = fopen(fn, "r");
 
235
        if (!f)
 
236
                return -1; 
 
237
        while (getdelim(&line, &len, '\n', f) > 0) { 
 
238
                char *end;
 
239
                char *s = strcasestr(line, "kB"); 
 
240
                if (!s) 
 
241
                        continue; 
 
242
                --s; 
 
243
                while (s > line && isspace(*s))
 
244
                        --s;
 
245
                while (s > line && isdigit(*s))
 
246
                        --s; 
 
247
                if (strstr(line, "MemTotal")) { 
 
248
                        size = strtoull(s,&end,0) << 10; 
 
249
                        if (end == s) 
 
250
                                size = -1;
 
251
                        else
 
252
                                ok++; 
 
253
                }
 
254
                if (freep && strstr(line, "MemFree")) { 
 
255
                        *freep = strtoull(s,&end,0) << 10; 
 
256
                        if (end == s) 
 
257
                                *freep = -1;
 
258
                        else
 
259
                                ok++; 
 
260
                }
 
261
        } 
 
262
        fclose(f); 
 
263
        free(line);
 
264
        if (ok != required)
 
265
                numa_warn_int(W_badmeminfo, "Cannot parse sysfs meminfo (%d)", ok);
 
266
        return size;
 
267
}
 
268
 
 
269
make_internal_alias(numa_node_size64);
 
270
 
 
271
long numa_node_size(int node, long *freep)
 
272
{       
 
273
        long long f2;   
 
274
        long sz = numa_node_size64_int(node, &f2);
 
275
        if (freep) 
 
276
                *freep = f2; 
 
277
        return sz;      
 
278
}
 
279
 
 
280
int numa_available(void)
 
281
{
 
282
        int max,i;
 
283
        if (get_mempolicy_int(NULL, NULL, 0, 0, 0) < 0 && errno == ENOSYS) 
 
284
                return -1; 
 
285
        max = numa_max_node_int();
 
286
        for (i = 0; i <= max; i++) 
 
287
                nodemask_set(&numa_all_nodes, i); 
 
288
        return 0;
 
289
 
290
 
 
291
void numa_interleave_memory(void *mem, size_t size, nodemask_t *mask)
 
292
 
293
        dombind(mem, size, MPOL_INTERLEAVE, mask);
 
294
 
295
 
 
296
void numa_tonode_memory(void *mem, size_t size, int node)
 
297
{
 
298
        nodemask_t nodes;
 
299
        nodemask_zero(&nodes); 
 
300
        nodemask_set(&nodes, node); 
 
301
        dombind(mem, size,  bind_policy, &nodes); 
 
302
}
 
303
 
 
304
void numa_tonodemask_memory(void *mem, size_t size, nodemask_t *mask)
 
305
{
 
306
        dombind(mem, size,  bind_policy, mask); 
 
307
}
 
308
 
 
309
void numa_setlocal_memory(void *mem, size_t size)
 
310
{
 
311
        dombind(mem, size, MPOL_PREFERRED, NULL);
 
312
}
 
313
 
 
314
void numa_police_memory(void *mem, size_t size)
 
315
{
 
316
        int pagesize = numa_pagesize_int();
 
317
        unsigned long i; 
 
318
        for (i = 0; i < size; i += pagesize)
 
319
                asm volatile("" :: "r" (((volatile unsigned char *)mem)[i]));
 
320
}
 
321
 
 
322
make_internal_alias(numa_police_memory);
 
323
 
 
324
void *numa_alloc(size_t size)
 
325
{
 
326
        char *mem;
 
327
        mem = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
 
328
                   0, 0); 
 
329
        if (mem == (char *)-1)
 
330
                return NULL;
 
331
        numa_police_memory_int(mem, size);
 
332
        return mem;
 
333
 
334
 
 
335
void *numa_alloc_interleaved_subset(size_t size, nodemask_t *mask) 
 
336
 
337
        char *mem;      
 
338
 
 
339
        mem = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
 
340
                   0, 0); 
 
341
        if (mem == (char *)-1) 
 
342
                return NULL;
 
343
        dombind(mem, size, MPOL_INTERLEAVE, mask);
 
344
        return mem;
 
345
 
346
 
 
347
make_internal_alias(numa_alloc_interleaved_subset);
 
348
 
 
349
void *numa_alloc_interleaved(size_t size)
 
350
 
351
        return numa_alloc_interleaved_subset_int(size, &numa_all_nodes); 
 
352
 
353
 
 
354
void numa_set_interleave_mask(nodemask_t *mask)
 
355
 
356
        if (nodemask_equal(mask, &numa_no_nodes))
 
357
                setpol(MPOL_DEFAULT, *mask); 
 
358
        else
 
359
                setpol(MPOL_INTERLEAVE, *mask);
 
360
 
361
 
 
362
nodemask_t numa_get_interleave_mask(void)
 
363
 
364
        int oldpolicy;
 
365
        nodemask_t mask; 
 
366
        getpol(&oldpolicy, &mask); 
 
367
        if (oldpolicy == MPOL_INTERLEAVE)
 
368
                return mask;
 
369
        return numa_no_nodes; 
 
370
 
371
 
 
372
/* (undocumented) */
 
373
int numa_get_interleave_node(void)
 
374
 
375
        int nd;
 
376
        if (get_mempolicy_int(&nd, NULL, 0, 0, MPOL_F_NODE) == 0)
 
377
                return nd;
 
378
        return 0;       
 
379
 
380
 
 
381
void *numa_alloc_onnode(size_t size, int node) 
 
382
 
383
        char *mem; 
 
384
        nodemask_t nodes;
 
385
        nodemask_zero(&nodes); 
 
386
        nodemask_set(&nodes, node); 
 
387
        mem = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
 
388
                   0, 0);  
 
389
        if (mem == (char *)-1)
 
390
                return NULL;            
 
391
        dombind(mem, size, bind_policy, &nodes); 
 
392
        return mem;     
 
393
 
394
 
 
395
void *numa_alloc_local(size_t size) 
 
396
 
397
        char *mem; 
 
398
        mem = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
 
399
                   0, 0); 
 
400
        if (mem == (char *)-1)
 
401
                return NULL;
 
402
        dombind(mem, size, MPOL_DEFAULT, NULL); 
 
403
        return mem;     
 
404
 
405
 
 
406
void numa_set_bind_policy(int strict) 
 
407
 
408
        if (strict) 
 
409
                bind_policy = MPOL_BIND; 
 
410
        else
 
411
                bind_policy = MPOL_PREFERRED;
 
412
 
413
 
 
414
void numa_set_membind(nodemask_t *mask) 
 
415
 
416
        setpol(MPOL_BIND, *mask);
 
417
 
418
 
 
419
make_internal_alias(numa_set_membind);
 
420
 
 
421
nodemask_t numa_get_membind(void)
 
422
{
 
423
        int oldpolicy;
 
424
        nodemask_t nodes;
 
425
        getpol(&oldpolicy, &nodes);
 
426
        if (oldpolicy == MPOL_BIND)
 
427
                return nodes;
 
428
        return numa_all_nodes;  
 
429
 
430
 
 
431
void numa_free(void *mem, size_t size)
 
432
 
433
        munmap(mem, size); 
 
434
 
435
 
 
436
static unsigned long *node_cpu_mask[NUMA_NUM_NODES];  
 
437
 
 
438
/* This would be better with some locking, but I don't want to make libnuma
 
439
   dependent on pthreads right now. The races are relatively harmless. */
 
440
int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) 
 
441
{
 
442
        char fn[64];
 
443
        FILE *f; 
 
444
        char *line = NULL; 
 
445
        size_t len = 0; 
 
446
        char *s;
 
447
        int n;
 
448
        int buflen_needed;
 
449
        unsigned *mask, prev;
 
450
        int ncpus = number_of_cpus();
 
451
 
 
452
        buflen_needed = CPU_BYTES(ncpus);
 
453
        if ((unsigned)node > maxnode || bufferlen < buflen_needed) { 
 
454
                errno = ERANGE;
 
455
                return -1;
 
456
        }
 
457
 
 
458
        if (node_cpu_mask[node]) { 
 
459
                if (bufferlen > buflen_needed)
 
460
                        memset(buffer, 0, bufferlen); 
 
461
                memcpy(buffer, node_cpu_mask[node], buflen_needed);
 
462
                return 0;
 
463
        }
 
464
 
 
465
        mask = malloc(buflen_needed);
 
466
        if (!mask) 
 
467
                mask = (unsigned *)buffer; 
 
468
        memset(mask, 0, buflen_needed); 
 
469
                        
 
470
        sprintf(fn, "/sys/devices/system/node/node%d/cpumap", node); 
 
471
        f = fopen(fn, "r"); 
 
472
        if (!f || getdelim(&line, &len, '\n', f) < 1) { 
 
473
                numa_warn_int(W_nosysfs2,
 
474
                   "/sys not mounted or invalid. Assuming nodes equal CPU: %s",
 
475
                          strerror(errno)); 
 
476
                set_bit(node, (unsigned long *)mask);
 
477
                goto out;
 
478
        } 
 
479
        n = 0;
 
480
        s = line;
 
481
        prev = 0; 
 
482
        while (*s) {
 
483
                unsigned num; 
 
484
                int i;
 
485
                num = 0;
 
486
                for (i = 0; s[i] && s[i] != ','; i++) { 
 
487
                        static const char hexdigits[] = "0123456789abcdef";
 
488
                        char *w = strchr(hexdigits, tolower(s[i]));
 
489
                        if (!w) { 
 
490
                                if (isspace(s[i]))
 
491
                                        break;
 
492
                                numa_warn_int(W_cpumap, 
 
493
                                          "Unexpected character `%c' in sysfs cpumap", s[i]);
 
494
                                set_bit(node, mask);
 
495
                                goto out;
 
496
                        }
 
497
                        num = (num*16) + (w - hexdigits); 
 
498
                }
 
499
                if (i == 0) 
 
500
                        break; 
 
501
                s += i;
 
502
                if (*s == ',')
 
503
                        s++;
 
504
                /* skip leading zeros */
 
505
                if (num == 0 && prev == 0) 
 
506
                        continue;
 
507
                prev |= num; 
 
508
                memmove(mask + 1, mask, buflen_needed - sizeof(unsigned)); 
 
509
                mask[0] = num; 
 
510
        }
 
511
 out:
 
512
        if (f) 
 
513
                fclose(f);
 
514
        memcpy(buffer, mask, buflen_needed);
 
515
 
 
516
        /* slightly racy, see above */ 
 
517
        if (node_cpu_mask[node]) {
 
518
                if (mask != (unsigned *)buffer)
 
519
                        free(mask);            
 
520
        } else {
 
521
                node_cpu_mask[node] = (unsigned long *)mask; 
 
522
        } 
 
523
        return 0; 
 
524
 
525
 
 
526
make_internal_alias(numa_node_to_cpus);
 
527
 
 
528
int numa_run_on_node_mask(nodemask_t *mask)
 
529
{       
 
530
        int ncpus = number_of_cpus();
 
531
        int i, k, err;
 
532
        unsigned long cpus[CPU_WORDS(ncpus)], nodecpus[CPU_WORDS(ncpus)];
 
533
        memset(cpus, 0, CPU_BYTES(ncpus));
 
534
        for (i = 0; i < NUMA_NUM_NODES; i++) { 
 
535
                if (mask->n[i / BITS_PER_LONG] == 0)
 
536
                        continue;
 
537
                if (nodemask_isset(mask, i)) { 
 
538
                        if (numa_node_to_cpus_int(i, nodecpus, CPU_BYTES(ncpus)) < 0) { 
 
539
                                numa_warn_int(W_noderunmask, 
 
540
                                          "Cannot read node cpumask from sysfs");
 
541
                                continue;
 
542
                        }
 
543
                        for (k = 0; k < CPU_WORDS(ncpus); k++)
 
544
                                cpus[k] |= nodecpus[k];
 
545
                }       
 
546
        }
 
547
        err = numa_sched_setaffinity_int(getpid(), CPU_BYTES(ncpus), cpus);
 
548
 
 
549
        /* The sched_setaffinity API is broken because it expects
 
550
           the user to guess the kernel cpuset size. Do this in a
 
551
           brute force way. */
 
552
        if (err < 0 && errno == EINVAL) { 
 
553
                int savederrno = errno;
 
554
                int me = getpid();
 
555
                char *bigbuf;
 
556
                static int size = -1;
 
557
                if (size == -1) 
 
558
                        size = CPU_BYTES(ncpus) * 2; 
 
559
                bigbuf = malloc(CPU_BUFFER_SIZE);
 
560
                if (!bigbuf) {
 
561
                        errno = ENOMEM; 
 
562
                        return -1;
 
563
                }
 
564
                errno = savederrno;
 
565
                while (size <= CPU_BUFFER_SIZE) { 
 
566
                        memcpy(bigbuf, cpus, CPU_BYTES(ncpus)); 
 
567
                        memset(bigbuf + CPU_BYTES(ncpus), 0,
 
568
                               CPU_BUFFER_SIZE - CPU_BYTES(ncpus));
 
569
                        err = numa_sched_setaffinity_int(me, size, (unsigned long *)bigbuf);
 
570
                        if (err == 0 || errno != EINVAL)
 
571
                                break;
 
572
                        size *= 2;
 
573
                }
 
574
                savederrno = errno;
 
575
                free(bigbuf);
 
576
                errno = savederrno;
 
577
        } 
 
578
        return err;
 
579
 
580
 
 
581
make_internal_alias(numa_run_on_node_mask);
 
582
 
 
583
nodemask_t numa_get_run_node_mask(void)
 
584
 
585
        int ncpus = number_of_cpus();
 
586
        nodemask_t mask;
 
587
        int i, k;
 
588
        unsigned long cpus[CPU_WORDS(ncpus)], nodecpus[CPU_WORDS(ncpus)];
 
589
 
 
590
        memset(cpus, 0, CPU_BYTES(ncpus));
 
591
        nodemask_zero(&mask);
 
592
        if (numa_sched_getaffinity_int(getpid(), CPU_BYTES(ncpus), cpus) < 0) 
 
593
                return numa_no_nodes; 
 
594
        /* somewhat dumb algorithm */
 
595
        for (i = 0; i < NUMA_NUM_NODES; i++) {
 
596
                if (numa_node_to_cpus_int(i, nodecpus, CPU_BYTES(ncpus)) < 0) {
 
597
                        numa_warn_int(W_noderunmask, "Cannot read node cpumask from sysfs");
 
598
                        continue;
 
599
                }
 
600
                for (k = 0; k < NUMA_NUM_NODES/BITS_PER_LONG; k++) {
 
601
                        if (nodecpus[k] & cpus[k])
 
602
                                nodemask_set(&mask, i); 
 
603
                }
 
604
        }               
 
605
        return mask;
 
606
 
607
 
 
608
int numa_run_on_node(int node)
 
609
 
610
        int ncpus = number_of_cpus();
 
611
        unsigned long cpus[CPU_WORDS(ncpus)];
 
612
 
 
613
        if (node == -1)
 
614
                memset(cpus, 0xff, CPU_BYTES(ncpus));
 
615
        else if (node < NUMA_NUM_NODES) {
 
616
                if (numa_node_to_cpus_int(node, cpus, CPU_BYTES(ncpus)) < 0) {
 
617
                        numa_warn_int(W_noderunmask, "Cannot read node cpumask from sysfs");
 
618
                        return -1; 
 
619
                }               
 
620
        } else { 
 
621
                errno = EINVAL;
 
622
                return -1; 
 
623
        }
 
624
        return numa_sched_setaffinity_int(getpid(), CPU_BYTES(ncpus), cpus);
 
625
 
626
 
 
627
int numa_preferred(void)
 
628
 
629
        int policy;
 
630
        nodemask_t nodes;
 
631
        getpol(&policy, &nodes);
 
632
        if (policy == MPOL_PREFERRED || policy == MPOL_BIND) { 
 
633
                int i;
 
634
                int max = NUMA_NUM_NODES;
 
635
                for (i = 0; i < max ; i++) 
 
636
                        if (nodemask_isset(&nodes, i))
 
637
                                return i; 
 
638
        }
 
639
        /* could read the current CPU from /proc/self/status. Probably 
 
640
           not worth it. */
 
641
        return 0; /* or random one? */
 
642
}
 
643
 
 
644
void numa_set_preferred(int node)
 
645
 
646
        nodemask_t n;
 
647
        if (node == -1) {
 
648
                nodemask_t empty;
 
649
                nodemask_zero(&empty);
 
650
                setpol(MPOL_DEFAULT, empty);
 
651
                return;
 
652
        }
 
653
        nodemask_zero(&n);
 
654
        nodemask_set(&n, node); 
 
655
        setpol(MPOL_PREFERRED, n);
 
656
 
657
 
 
658
void numa_set_localalloc(void) 
 
659
{       
 
660
        nodemask_t empty;
 
661
        nodemask_zero(&empty);
 
662
        setpol(MPOL_PREFERRED, empty);
 
663
 
664
 
 
665
void numa_bind(nodemask_t *nodemask)
 
666
{
 
667
        numa_run_on_node_mask_int(nodemask); 
 
668
        numa_set_membind_int(nodemask);
 
669
}
 
670
 
 
671
void numa_set_strict(int flag)
 
672
{
 
673
        if (flag)
 
674
                mbind_flags |= MPOL_MF_STRICT;
 
675
        else
 
676
                mbind_flags &= ~MPOL_MF_STRICT;
 
677
}