1/** 2 * \file 3 * \brief Argument processing for distributed services 4 */ 5 6/* 7 * Copyright (c) 2010-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, 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 <dist/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 that 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 dist_args process_dist_args(int *argc, char **argv[]) 185{ 186 errval_t err; 187 188 debug_printf("process_dist_args: start\n"); 189 190 struct dist_args res = (struct dist_args) { 191 .path = (*argv)[0], 192 .cores = NULL, 193 .cores_len = 0, 194 // .exclude = NULL, 195 // .exclude_len = 0, 196 .num_cores = -1, 197 // .all_cores = false, 198 .master = false, 199 }; 200 201 coreid_t *exclude = NULL; 202 int exclude_len = 0; 203 bool all_cores = false; 204 205 int opt; 206 207 while ((opt = getopt(*argc, *argv, ":wmax:c:n:")) != -1) { 208 209 switch (opt) { 210 case 'w': 211 // be a worker 212 res.master = false; 213 break; 214 case 'm': 215 // be a master 216 res.master = true; 217 break; 218 case 'a': 219 // use all available cores 220 all_cores = true; 221 break; 222 case 'c': 223 // use the cores given in the list argument 224 parse_list(optarg, &res.cores, &res.cores_len); 225 if (res.cores == NULL) { 226 goto fail; 227 } 228 break; 229 case 'x': 230 // exclude the cores given in the list argument 231 parse_list(optarg, &exclude, &exclude_len); 232 if (exclude == NULL) { 233 goto fail; 234 } 235 break; 236 case 'n': 237 // total number of cores to use 238 res.num_cores = strtol(optarg, NULL, 10); 239 break; 240 default: 241 // ignore 242 break; 243 } 244 } 245 246 247 debug_printf("pda: after getopt loop\n"); 248 249 if (all_cores) { 250 err = get_cores_skb(&res.cores, &res.cores_len); 251 if (err_is_fail(err)) { 252 DEBUG_ERR(err, "in get_cores_skb"); 253 goto fail; 254 } 255 /* 256 print_list("res.cores with all cores: \n", res.cores, res.cores_len); 257 */ 258 } 259 260 debug_printf("pda: after all cores\n"); 261 262 // by this point we must have a list of cores, either because one was 263 // provided explicitly or because all_cores were requested. 264 if ((res.cores == NULL) || (res.cores_len <= 0)) { 265 goto fail; 266 } 267 268 if (res.cores != NULL) { 269 coreid_t *cores; 270 int cores_len; 271 272 make_core_list(res.cores, res.cores_len, exclude, exclude_len, 273 res.num_cores, &cores, &cores_len); 274 275 debug_printf("pda: after make_core_list\n"); 276 277 free(res.cores); 278 if (exclude != NULL) { 279 free(exclude); 280 } 281 282 if (cores == NULL) { 283 goto fail; 284 } 285 286 res.cores = cores; 287 res.cores_len = cores_len; 288 } 289 290 *argc = *argc - optind; 291 *argv = &((*argv)[optind]); 292 293 debug_printf("pda: after modifying argv\n"); 294 295 return res; 296 297 fail: 298 if (exclude != NULL) { 299 free(exclude); 300 } 301 printf("Usage: %s [-mw] [-a] [-c list] [-x list] [-n num_cores]\n", 302 (*argv)[0]); 303 exit(EXIT_FAILURE); 304 return res; 305} 306 307