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