~ubuntu-branches/ubuntu/trusty/numactl/trusty

« back to all changes in this revision

Viewing changes to distance.c

  • Committer: Bazaar Package Importer
  • Author(s): Ian Wienand
  • Date: 2006-01-04 10:25:27 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104102527-1seu1f5eafl9iuoc
Tags: 0.9-1
* New upstream
* Most patches accepted into upstream; see upstream changelog or
  debian/patches/README in source package for history

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Discover distances
 
2
   Copyright (C) 2005 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 <stdio.h>
 
21
#include <stdlib.h>
 
22
#include <errno.h>
 
23
#include "numa.h"
 
24
#include "numaint.h"
 
25
 
 
26
static int distance_numnodes;
 
27
static int *distance_table; 
 
28
 
 
29
static int count_numbers(char *s)
 
30
{
 
31
        int n = 0;
 
32
        for (;;) {
 
33
                char *end;  
 
34
                strtoul(s, &end, 0);
 
35
                if (s == end)
 
36
                        return n;
 
37
                s = end;
 
38
                n++; 
 
39
        }
 
40
}
 
41
 
 
42
static void parse_numbers(char *s, int *iptr, int n)
 
43
{
 
44
        int i;
 
45
        char *end;
 
46
        for (i = 0; i < n; i++) { 
 
47
                *iptr++ = strtoul(s, &end, 0);
 
48
                if (s == end)
 
49
                        break;
 
50
                s = end; 
 
51
        } 
 
52
}
 
53
 
 
54
static int read_distance_table(void) 
 
55
 
56
        int nd, len; 
 
57
        char *line = NULL;
 
58
        size_t linelen = 0; 
 
59
        int numnodes = 0; 
 
60
        int *table = NULL; 
 
61
        int err = -1;
 
62
        
 
63
        for (nd = 0;; nd++) { 
 
64
                char fn[100]; 
 
65
                FILE *dfh;
 
66
                sprintf(fn, "/sys/devices/system/node/node%d/distance", nd);
 
67
                dfh = fopen(fn, "r"); 
 
68
                if (!dfh) { 
 
69
                        if (errno == ENOENT && nd > 0)
 
70
                                err = 0;
 
71
                        break;
 
72
                }
 
73
                len = getdelim(&line, &linelen, '\n', dfh);
 
74
                fclose(dfh);
 
75
                if (len <= 0)
 
76
                        break;
 
77
 
 
78
                if (!table) { 
 
79
                        numnodes = count_numbers(line); 
 
80
                        table = calloc(numnodes * numnodes, sizeof(int)); 
 
81
                        if (!table) {
 
82
                                errno = ENOMEM; 
 
83
                                break;
 
84
                        }
 
85
                } 
 
86
 
 
87
                parse_numbers(line, table + nd * numnodes, numnodes);
 
88
        }
 
89
        free(line); 
 
90
        if (err)  { 
 
91
                numa_warn(W_distance,
 
92
                          "Cannot parse distance information in sysfs: %s",
 
93
                          strerror(errno));
 
94
                free(table); 
 
95
                return err;
 
96
        }
 
97
        /* Update the global table pointer.  Race window here with
 
98
           other threads, but in the worst case we leak one distance
 
99
           array one time, which is tolerable. This avoids a
 
100
           dependency on pthreads. */
 
101
        if (distance_table) { 
 
102
                free(table);
 
103
                return 0;
 
104
        }
 
105
        distance_numnodes = numnodes;
 
106
        distance_table = table;
 
107
        return 0;               
 
108
}  
 
109
 
 
110
int numa_distance(int a, int b) 
 
111
 
112
        if (!distance_table) { 
 
113
                int err = read_distance_table();
 
114
                if (err < 0)
 
115
                        return 0;
 
116
        }
 
117
        return distance_table[a * distance_numnodes + b];
 
118