1/** 2 * \file 3 * \brief Argument processing 4 */ 5 6/* 7 * Copyright (c) 2007-2010, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <string.h> 17 18#include <getopt.h> 19 20#include <barrelfish/barrelfish.h> 21 22#include "skb.h" 23 24#include "args.h" 25 26static bool is_excluded(coreid_t core, coreid_t *exclude, int exclude_len) 27{ 28 // assume exclude list isn't sorted 29 for (int i = 0; i < exclude_len; i++) { 30 if (core == exclude[i]) { 31 return true; 32 } 33 } 34 return false; 35} 36 37// mallocs res_cores 38static void make_core_list(coreid_t *cores, int cores_len, 39 coreid_t *exclude, int exclude_len, 40 int num_cores, 41 coreid_t **res_cores, int *res_len) 42{ 43 assert(cores != NULL); 44 assert(res_cores != NULL); 45 assert(res_len != NULL); 46 47 if ((exclude == NULL) || (exclude_len <= 0)) { 48 // nothing to exclude, simply copy cores to res_cores 49 *res_len = cores_len; 50 *res_cores = malloc(*res_len * sizeof(coreid_t)); 51 if (*res_cores != NULL) { 52 if (memcpy(*res_cores, cores, cores_len*sizeof(coreid_t)) == NULL) { 53 *res_cores = NULL; 54 } 55 } else { 56 DEBUG_ERR(LIB_ERR_MALLOC_FAIL,"when processing core list argument"); 57 } 58 return; 59 } 60 61 // otherwise deal with exclusions 62 63 *res_len = cores_len - exclude_len; 64 *res_cores = malloc(*res_len * sizeof(coreid_t)); 65 if (*res_cores == NULL) { 66 DEBUG_ERR(LIB_ERR_MALLOC_FAIL,"when processing core list argument"); 67 return; 68 } 69 70 int r_i = 0; 71 for (int i = 0; i < cores_len; i++) { 72 if (!is_excluded(cores[i], exclude, exclude_len)) { 73 (*res_cores)[r_i] = cores[i]; 74 r_i++; 75 } 76 if ((num_cores > 0) && (r_i >= num_cores)) { 77 break; 78 } 79 } 80 81 *res_len = r_i; 82} 83 84// mallocs *list 85static void parse_list(char *optargs, coreid_t **list, int *len) 86{ 87 assert(optargs != NULL); 88 assert(list != NULL); 89 assert(len != NULL); 90 91 *list = NULL; 92 93 // a list looks like this: 0,1,2,3,4,5 94 95 // make extra copy bcause strtok clobbers it 96 char *p = malloc(strlen(optargs) + 1); 97 if (p == NULL) { 98 DEBUG_ERR(LIB_ERR_MALLOC_FAIL, "when parsing core list"); 99 return; 100 } 101 strcpy(p, optargs); 102 103 // first get the number of elements 104 int i; 105 char *tok = p; 106 for (i = 0; tok != NULL; i++, p = NULL) { 107 tok = strtok(p, ","); 108 } 109 free(p); 110 *len = --i; 111 *list = malloc(sizeof(coreid_t)*i); 112 if (*list == NULL) { 113 DEBUG_ERR(LIB_ERR_MALLOC_FAIL, "when parsing core list"); 114 return; 115 } 116 117 // now get the actual elements 118 p = optargs; 119 tok = p; 120 for (i = 0; tok != NULL; i++, p = NULL) { 121 tok = strtok(p, ","); 122 if (tok != NULL) { 123 (*list)[i] = strtol(tok, NULL, 10); 124 } else { 125 break; 126 } 127 } 128} 129 130 131#if 0 132static void print_list(char *s, coreid_t *list, int len) 133{ 134 debug_printf("%s", s); 135 if ((s == NULL) || (len <= 0)) { 136 debug_printf("\tList is empty\n"); 137 } else { 138 for (int i = 0; i < len; i++) { 139 debug_printf("\t%d: %d\n", i, list[i]); 140 } 141 } 142} 143#endif 144 145 146// mallocs return string 147char *list_to_string(coreid_t *list, size_t l_len) 148{ 149 /* Guess we need up to 4 bytes per entry. */ 150 int n, size = 4 * l_len; 151 char *s, *ns; 152 153 if ((s = malloc(size)) == NULL) { 154 DEBUG_ERR(LIB_ERR_MALLOC_FAIL, "when converting core list to string"); 155 return NULL; 156 } 157 158 int out_len = 0; 159 for (int i = 0; i < l_len; i++) { 160 n = snprintf(&s[out_len], size - out_len, "%d,", list[i]); 161 if (out_len + n < size) { 162 out_len += n; 163 } else { 164 // ran out of space; 165 size *= 2; 166 ns = realloc(s, size); 167 if (ns == NULL) { 168 free(s); 169 DEBUG_ERR(LIB_ERR_MALLOC_FAIL, 170 "when converting core list to string"); 171 return NULL; 172 } else { 173 s = ns; 174 i--; // try again 175 continue; 176 } 177 } 178 } 179 return s; 180} 181 182 183// mallocs list elements of struct. but not path 184struct args process_args(int argc, char *argv[]) 185{ 186 errval_t err; 187 188 struct args res = (struct args) { 189 .path = argv[0], 190 .cores = NULL, 191 .cores_len = 0, 192 .exclude = NULL, 193 .exclude_len = 0, 194 .num_cores = -1, 195 .all_cores = false, 196 .master = false, 197 .ram = 0, 198 }; 199 200 int opt; 201 202 while ((opt = getopt(argc, argv, "wmax:c:n:r:")) != -1) { 203 204 switch (opt) { 205 case 'w': 206 // be a worker 207 res.master = false; 208 break; 209 case 'm': 210 // be a master 211 res.master = true; 212 break; 213 case 'a': 214 // use all available cores 215 res.all_cores = true; 216 break; 217 case 'c': 218 // use the cores given in the list argument 219 parse_list(optarg, &res.cores, &res.cores_len); 220 if (res.cores == NULL) { 221 goto fail; 222 } 223 break; 224 case 'x': 225 // exclude the cores given in the list argument 226 parse_list(optarg, &res.exclude, &res.exclude_len); 227 if (res.exclude == NULL) { 228 goto fail; 229 } 230 break; 231 case 'n': 232 // total number of cores to use 233 res.num_cores = strtol(optarg, NULL, 10); 234 break; 235 case 'r': 236 // memory to use per core 237 res.ram = (genpaddr_t) strtoll(optarg, NULL, 10); 238 break; 239 default: 240 goto fail; 241 } 242 } 243 244 if (res.all_cores) { 245 err = get_cores_skb(&res.cores, &res.cores_len); 246 if (err_is_fail(err)) { 247 DEBUG_ERR(err, "in get_cores_skb"); 248 goto fail; 249 } 250 /* 251 print_list("res.cores with all cores: \n", res.cores, res.cores_len); 252 */ 253 } 254 255 // by this point we must have a list of cores, either because one was 256 // provided explicitly or because all_cores were requested. 257 if ((res.cores == NULL) || (res.cores_len <= 0)) { 258 goto fail; 259 } 260 261 if (res.cores != NULL) { 262 coreid_t *cores; 263 int cores_len; 264 265 make_core_list(res.cores, res.cores_len, res.exclude, res.exclude_len, 266 res.num_cores, &cores, &cores_len); 267 268 free(res.cores); 269 270 if (cores == NULL) { 271 goto fail; 272 } 273 274 res.cores = cores; 275 res.cores_len = cores_len; 276 } 277 278 return res; 279 280 fail: 281 printf("Usage: %s [-mw] [-a] [-c list] [-x list] [-n num_cores]\n", 282 argv[0]); 283 exit(EXIT_FAILURE); 284 return res; 285} 286 287