From patchwork Fri Nov 9 07:10:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amitay Isaacs X-Patchwork-Id: 995368 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42rrs52Nz5z9sBZ for ; Fri, 9 Nov 2018 18:10:33 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ozlabs.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.b="HK3+VR3q"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 42rrs45WFyzF3Zq for ; Fri, 9 Nov 2018 18:10:32 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=ozlabs.org Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.b="HK3+VR3q"; dkim-atps=neutral X-Original-To: pdbg@lists.ozlabs.org Delivered-To: pdbg@lists.ozlabs.org Received: from ozlabs.org (bilbo.ozlabs.org [IPv6:2401:3900:2:1::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 42rrrw2hQ1zF3Zc for ; Fri, 9 Nov 2018 18:10:24 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=ozlabs.org Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.b="HK3+VR3q"; dkim-atps=neutral Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPSA id 42rrrv6h79z9sCX; Fri, 9 Nov 2018 18:10:23 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ozlabs.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; t=1541747423; bh=mrWgXav+uddVLDPvRFNawqt982+BZdBD+lI/nw/wbAo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HK3+VR3qVOKuzjE+DIOZXur04sbs1BOmivYvi4/hAaMzcmsTiGDOyxbiXBiV7Y9Q6 LUkS3zR34dximO/KygwknVs0Q4fFHEbd0+h9xY3zrMC7ORYJ87k8DF105Tj9BlwUPf soQq7Bk2mXO1ojGuitok0eEG8jHaC8yO88xkehNgAlczp1ZhrUBoAM24rsZ8CAtLVr nBDFJUjg0CUCi3ET/j4sW4TlSb9uFPnoffR9j2PyW/ygxiIqqvU/egGczDcPN1B0/q 0Ti+WvaXTjcyiSJw1qPlY1vPSJqpOBrEc7XU69+fh6uOEeXsMATTPKzk9pJqctQbn7 mGkeiVindCxUw== From: Amitay Isaacs To: pdbg@lists.ozlabs.org Date: Fri, 9 Nov 2018 18:10:00 +1100 Message-Id: <20181109071011.253734-5-amitay@ozlabs.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181109071011.253734-1-amitay@ozlabs.org> References: <20181109071011.253734-1-amitay@ozlabs.org> MIME-Version: 1.0 Subject: [Pdbg] [PATCH v2 04/15] path: Add device tree path based targeting X-BeenThere: pdbg@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "mailing list for https://github.com/open-power/pdbg development" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Amitay Isaacs Errors-To: pdbg-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Pdbg" Signed-off-by: Amitay Isaacs Reviewed-by: Alistair Popple --- Makefile.am | 2 + src/path.c | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/path.h | 109 +++++++++++++++++ 3 files changed, 443 insertions(+) create mode 100644 src/path.c create mode 100644 src/path.h diff --git a/Makefile.am b/Makefile.am index c8f100e..2a687ca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -78,6 +78,8 @@ pdbg_SOURCES = \ src/options.h \ src/parsers.c \ src/parsers.h \ + src/path.c \ + src/path.h \ src/pdbgproxy.c \ src/pdbgproxy.h \ src/progress.c \ diff --git a/src/path.c b/src/path.c new file mode 100644 index 0000000..6b4e29b --- /dev/null +++ b/src/path.c @@ -0,0 +1,332 @@ +/* Copyright 2018 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "path.h" +#include "util.h" + +#define MAX_PATH_COMP_LEN 32 +#define MAX_PATH_COMPONENTS 16 +#define MAX_PATH_LEN (MAX_PATH_COMP_LEN * MAX_PATH_COMPONENTS) + +/* This is max(MAX_PROCESSORS, MAX_CHIPS, MAX_THREADS) */ +#define MAX_PATH_INDEX 64 + +struct path_pattern { + char prefix[MAX_PATH_COMP_LEN]; + int index[MAX_PATH_INDEX]; + bool match_full; + bool match_index; +}; + +/* Start with max threads, rather than defining arbitrary number */ +#define MAX_TARGETS (64 * 24 * 8) + +static struct pdbg_target *path_target[MAX_TARGETS]; +static unsigned int path_target_count; + +static void safe_strcpy(char *dest, size_t n, const char *src) +{ + assert(strlen(src) + 1 <= n); + + strcpy(dest, src); +} + +/* + * Parse string components of following forms: + * pib0 + * core[1-3,11-13] + * thread* + * adu@123000 + */ +static bool path_pattern_parse(const char *arg, struct path_pattern *pat) +{ + char tmp[strlen(arg)+1]; + char *tok; + bool ok; + + safe_strcpy(tmp, sizeof(tmp), arg); + + memset(pat, 0, sizeof(*pat)); + + if (strchr(tmp, '@')) { + safe_strcpy(pat->prefix, sizeof(pat->prefix), tmp); + pat->match_full = true; + + } else if (strchr(tmp, '*')) { + tok = strtok(tmp, "*"); + if (!tok) + safe_strcpy(pat->prefix, sizeof(pat->prefix), "all"); + else + safe_strcpy(pat->prefix, sizeof(pat->prefix), tok); + + } else if (strchr(tmp, '[')) { + tok = strtok(tmp, "["); + if (tok == NULL) { + fprintf(stderr, "Invalid pattern '%s'\n", arg); + return false; + } + safe_strcpy(pat->prefix, sizeof(pat->prefix), tok); + + tok = strtok(NULL, "]"); + if (!tok) { + fprintf(stderr, "Invalid pattern '%s'\n", arg); + return false; + } + + ok = parse_list(tok, MAX_PATH_INDEX, pat->index, NULL); + if (!ok) + return false; + + pat->match_index = true; + + } else { + size_t n = strlen(tmp) - 1; + while (n >= 0 && isdigit(tmp[n])) + n--; + n++; + + if (n != strlen(tmp)) { + int index; + + index = atoi(&tmp[n]); + if (index < 0 || index >= MAX_PATH_INDEX) { + fprintf(stderr, "Invalid index '%s'\n", &tmp[n]); + return false; + } + tmp[n] = '\0'; + pat->index[index] = 1; + pat->match_index = true; + } + + safe_strcpy(pat->prefix, sizeof(pat->prefix), tmp); + } + + if (!pat->prefix) + return false; + + return true; +} + +static int path_pattern_split(const char *arg, struct path_pattern *pats) +{ + char arg_copy[MAX_PATH_LEN]; + char *tmp, *tok, *saveptr = NULL; + int n; + bool ok; + + safe_strcpy(arg_copy, sizeof(arg_copy), arg); + + tmp = arg_copy; + n = 0; + while ((tok = strtok_r(tmp, "/", &saveptr))) { + size_t len = strlen(tok); + + if (len == 0) + continue; + + if (len >= MAX_PATH_LEN) { + fprintf(stderr, "Pattern component '%s' too long\n", tok); + return -1; + } + + ok = path_pattern_parse(tok, &pats[n]); + if (!ok) + return -1; + + n++; + assert(n <= MAX_PATH_COMPONENTS); + + tmp = NULL; + } + + return n; +} + +static int path_target_find(struct pdbg_target *prev) +{ + int i; + + if (!prev) + return -1; + + for (i=0; i= 0) + return true; + + if (path_target_count == MAX_TARGETS) + return false; + + path_target[path_target_count] = target; + path_target_count++; + return true; +} + +static void path_pattern_match(struct pdbg_target *target, + struct path_pattern *pats, + int max_levels, + int level) +{ + struct pdbg_target *child; + char comp_name[MAX_PATH_COMP_LEN]; + char *tok; + int next = level; + bool found = false; + + if (target == pdbg_target_root()) { + goto end; + } + + if (!strcmp("all", pats[level].prefix)) { + if (!path_target_add(target)) + return; + goto end; + } + + safe_strcpy(comp_name, sizeof(comp_name), pdbg_target_class_name(target)); + if (pats[level].match_full) { + tok = comp_name; + } else { + tok = strtok(comp_name, "@"); + } + + if (!strcmp(tok, pats[level].prefix)) { + found = true; + + if (pats[level].match_index) { + int index = pdbg_target_index(target); + + if (pats[level].index[index] != 1) + found = false; + } + } + + if (found) { + if (level == max_levels-1) { + path_target_add(target); + return; + } else { + next = level + 1; + } + } + +end: + pdbg_for_each_child_target(target, child) { + path_pattern_match(child, pats, max_levels, next); + } +} + +bool path_target_parse(const char **arg, int arg_count) +{ + struct path_pattern pats[MAX_PATH_COMPONENTS]; + int i, n; + + for (i=0; i 0); +} + +bool path_target_selected(struct pdbg_target *target) +{ + int index; + + index = path_target_find(target); + if (index >= 0) + return true; + + return false; +} + +void path_target_dump(void) +{ + struct pdbg_target *target; + char *path; + + for_each_path_target(target) { + path = pdbg_target_path(target); + assert(path); + printf("%s\n", path); + free(path); + } +} + +struct pdbg_target *path_target_next(struct pdbg_target *prev) +{ + int index; + + index = path_target_find(prev); + return path_target_find_next(NULL, index); +} + +struct pdbg_target *path_target_next_class(const char *klass, + struct pdbg_target *prev) +{ + int index; + + index = path_target_find(prev); + return path_target_find_next(klass, index); +} diff --git a/src/path.h b/src/path.h new file mode 100644 index 0000000..c1bdb39 --- /dev/null +++ b/src/path.h @@ -0,0 +1,109 @@ +/* Copyright 2018 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __PDBG_PATH_H +#define __PDBG_PATH_H + +#include + +/** + * @brief Parse a list of path target strings + * + * @param[in] arg An array of strings + * @param[in] arg_count The number of strings + * @return true on success, false on error + */ +bool path_target_parse(const char **arg, int arg_count); + +/** + * @brief Check if there are any path targets + * + * @return true if number of path targets > 0, false otherwise + */ +bool path_target_present(void); + +/** + * @brief Add a target to the list + * + * @param[in] target pdbg target + * @return true on success, false on error + */ +bool path_target_add(struct pdbg_target *target); + +/** + * @brief Check if the specified target is selected + * + * @param[in] target pdbg target + * @return true if the target is selected, false otherwise + */ +bool path_target_selected(struct pdbg_target *target); + +/** + * @brief Print the list of path targets to stdout + */ +void path_target_dump(void); + +/** + * @brief Iterator for list of path targets + * + * @param[in] prev The last pdbg target + * @return the next pdbg target in the list, NULL otherwise + * + * If prev is NULL, then return the first pdbg target in the list. + * If there are no more pdbg targets in the list, NULL is returned. + */ +struct pdbg_target *path_target_next(struct pdbg_target *prev); + +/** + * @brief Iterator for a list of path targets of specified class + * + * @param[in] klass The class of the targets required + * @param[in] prev The last pdbg target + * @return the next matching pdbg target in the list, NULL otherwise + * + * If prev is NULL, then return the first matching pdbg target in the list. + * If there are no more matching pdbg targets, NULL is returned. + */ +struct pdbg_target *path_target_next_class(const char *klass, + struct pdbg_target *prev); + +/** + * @brief Macro for iterating through all path targets + * + * target is of type struct pdbg_target + * + * If only_enabled is true, iterate through targets that are enabled; + * otherwise iterate through all targets + */ +#define for_each_path_target(target) \ + for (target = path_target_next(NULL); \ + target; \ + target = path_target_next(target)) + +/** + * @brief Macro for iterating through all path targets of specific class + * + * class is of type char * + * target is of type struct pdbg_target + * + * If only_enabled is true, iterate through targets that are enabled; + * otherwise iterate through all targets + */ +#define for_each_path_target_class(class, target) \ + for (target = path_target_next_class(class, NULL); \ + target; \ + target = path_target_next_class(class, target)) + +#endif