1/**
2 * \file
3 * \brief Calling and processing results from SKB
4 */
5
6/*
7 * Copyright (c) 2007-2011, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <stdlib.h>
16#include <stdio.h>
17
18#include <string.h>
19
20#include <barrelfish/barrelfish.h>
21
22#include <skb/skb.h>
23
24#include "skb.h"
25
26#if 0
27static void get_range(char *result, genpaddr_t *base, genpaddr_t *limit)
28{
29    //    debug_printf("got affinity range results %s\n", result);
30
31    // example expected format:
32    // [range(0, 655360), range(1048576, 3355443200),
33    //  range(4294967296, 5234491392)]
34    // this functions creates a range using the first (lowest - e.g. 0) value
35    // and the last (highest - e.g. 5234491392) values.
36    // FIXME: yes it is a fragile hack.
37
38    *base = 0xf;
39    *limit = 0;
40    char *p = result;
41    while(true) {
42        p = strchr(p, '(');
43        if (!p) {
44            break;
45        }
46        p++;
47
48        if (*base == 0xf) {
49            *base = strtol(p, &p, 10);
50        } else {
51            strtol(p, &p, 10);
52        }
53        p++;p++;
54        *limit = strtol(p, &p, 10);
55    }
56    // debug_printf("got range %"PRIuGENPADDR", %"PRIuGENPADDR"\n",
57    //*base, *limit);
58}
59#endif
60
61// NOTE: the skb query currently returns the wrong output on qemu. However, in
62// that case this function returns base 0, limit 0, which is a good result.
63errval_t get_percore_affinity(coreid_t core, genpaddr_t *base, genpaddr_t *limit)
64{
65    assert(base != NULL);
66    assert(limit != NULL);
67
68    errval_t err;
69
70    *base = -1;
71    *limit = 0;
72
73    /* get the local memory affinity from SKB */
74
75    err = skb_client_connect();
76    if (err_is_fail(err)) {
77        DEBUG_ERR(err, "skb_client_connect failed");
78        return err;
79    }
80
81    struct list_parser_status status;
82    int myerr = skb_execute_query("local_memory_affinity(%d, Limit), "
83             "write(Limit).", core);
84    if (myerr != 0) {
85        return SKB_ERR_EXECUTION;
86    }
87
88    //    debug_printf("output: %s\n", res);
89    //    debug_printf("error_output: %s\n", skb_get_error_output());
90
91    genpaddr_t b, l;
92    skb_read_list_init(&status);
93    while (skb_read_list(&status, "range(%"PRIuGENPADDR", %"PRIuGENPADDR")",
94                         &b, &l)) {
95        // debug_printf("b: %lu l: %lu\n", b, l);
96        if (*base == -1 || b < *base) {
97            *base = b;
98        }
99        if (l > *limit) {
100            *limit = l;
101        }
102    }
103    if (*base == -1) {
104        *base = 0;
105    }
106
107    //    debug_printf("base: %lu limit %lu\n", *base, *limit);
108
109#if 0
110    // Adrian says not to use skb_evaluate anymore
111    char *result, *str_err;
112    int int_err;
113    char input[128];
114    snprintf(input, sizeof(input), "local_memory_affinity(%d, Limit), "
115             "write(Limit).", core);
116    err = skb_evaluate(input, &result, &str_err, &int_err);
117    if (err_is_fail(err)) {
118        DEBUG_ERR(err, "skb_evaluate failed");
119        return err_push(err, SKB_ERR_EVALUATE);
120    }
121
122    get_range(result, base, limit);
123
124    free(result);
125    free(str_err);
126#endif
127
128    return SYS_ERR_OK;
129}
130
131
132
133static errval_t parse_core_id_list(char *s, coreid_t *cores, int n)
134{
135    assert(cores != NULL);
136
137    // a list looks like this: [0, 1, 2, 3, 4, 5]
138
139    int i;
140    char *p = s;
141    char *tok = p;
142    for (i = 0; (i < n) && (tok != NULL); i++, p = NULL) {
143        tok = strtok(p, "[,]");
144        if (tok != NULL) {
145            cores[i] = strtol(tok, NULL, 10);
146        } else {
147            break;
148        }
149    }
150
151    if (i != n) {
152        return MS_ERR_SKB;
153    }
154
155    return SYS_ERR_OK;
156}
157
158errval_t get_cores_skb(coreid_t **cores, int *n_cores)
159{
160    assert(cores != NULL);
161    assert(n_cores != NULL);
162
163    errval_t err;
164
165    char *result, *str_err;
166    int32_t int_err;
167
168    err = skb_client_connect();
169    if (err_is_fail(err)) {
170        DEBUG_ERR(err, "skb_client_connect failed");
171        return err;
172    }
173
174    err = skb_evaluate("available_nr_cores(Nr), write(Nr)."
175                       , &result, &str_err, &int_err);
176    if (err_is_fail(err)) {
177        DEBUG_ERR(err, "skb_evaluate failed");
178        return err_push(err, SKB_ERR_EVALUATE);
179    }
180
181    // parse #cores
182    *n_cores = strtol(result, NULL, 10);
183
184    // request all coreids
185    err = skb_evaluate("get_core_id_list(L), write(L)."
186                       , &result, &str_err, &int_err);
187    if (err_is_fail(err)) {
188        DEBUG_ERR(err, "skb_evaluate failed");
189        return err_push(err, SKB_ERR_EVALUATE);
190    }
191
192    // allocate result array
193    // parse result into result array
194
195    *cores = (coreid_t*)malloc(sizeof(coreid_t) * *n_cores);
196    if (*cores == NULL) {
197        return err_push(err, LIB_ERR_MALLOC_FAIL);
198    }
199
200    err = parse_core_id_list(result, *cores, *n_cores);
201    if (err_is_fail(err)) {
202        DEBUG_ERR(err, "parse_list failed");
203        free(*cores);
204        return err;
205    }
206
207    return SYS_ERR_OK;
208}
209
210