Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp5139876pxj; Wed, 26 May 2021 03:55:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxS8lp0t2rxFkFLNNEk4RqoT+FUK2vAyeDGpEPoUPfbe6OSt5HoofRN3yre71AQmsnSIGRa X-Received: by 2002:a17:906:2bd0:: with SMTP id n16mr33714938ejg.110.1622026525780; Wed, 26 May 2021 03:55:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1622026525; cv=none; d=google.com; s=arc-20160816; b=sWgoo6aJrrhZbhkQFPdLPweKaXCSOBDuvPgpussYNQVv6bzaRKgzhbKPBGnOGbytPy o56nw8ChUSc9M7b3p3eycY9VY2aN51opD5OW0ey7zsCeVjSjoYypMy0m/wsvA0Tu/suR 4CXLPdEgWSNrjXAFo3sTbykG2cVj+L9q0mhEQx0pf3S1ZaFvo3hzUgCTZ3S8OFjBvEmm UUhZ6Vz1XnhzCs+Tz0pdziwWNgi1Xuybo8mIEZSqLuBA5r9X/nT6f55gcxZu/a/iHizD 8OpkfByL5cwHEKUDSwzIF6tTO3lPQO/h4vebrblIc4wtCM1kir1sxJRBvOYLqT4PFl/2 7Dkw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :ironport-sdr:ironport-sdr; bh=56XG7almtnV+6UY9crp1TKSH8ki4zMDLCz91IwYt+aU=; b=mTJBpTmeYknLT5qZZBgSuUqhlDJhrW6nINhEmbS4+EIwTKK5lZ1Xp0lumyXMxnYxiE 9AW+NyhC9olWNx0xEObBjFpFzr4vZc7kTieeuGuSHHxOBadPvM5W2PujSm6V5/w53xHd RNbHZ7Yhq4G64W04COAxuC7YYo1s4duW+pI6wqz+hQtsfTdvQZTRyKfEKyGWPuUZVFVe oEvuz2sfPPKCDhkJjupffAUFV3Y9ho5SPMEiwi9D7FhGnMbK77TRngqCAba1XbHIqXFN 7aq9qzDhBXtMGA1PWUV3Gs78lDlhHQqxEyGi43eOd+TxVzO0FDl3wS4WdNfSTf+F/5jb J0zQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id eb5si11169386edb.276.2021.05.26.03.55.01; Wed, 26 May 2021 03:55:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234262AbhEZKzU (ORCPT + 99 others); Wed, 26 May 2021 06:55:20 -0400 Received: from mga02.intel.com ([134.134.136.20]:1596 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234276AbhEZKzE (ORCPT ); Wed, 26 May 2021 06:55:04 -0400 IronPort-SDR: PNtcZF7BfupkpJKQjOzCqGJfpmg2tZ3VBVSxV2Z7kmYXHh5ZcsRVyhQtOTE0kIaLuqLZ+aeuR5 30DEex9AMHfg== X-IronPort-AV: E=McAfee;i="6200,9189,9995"; a="189556418" X-IronPort-AV: E=Sophos;i="5.82,331,1613462400"; d="scan'208";a="189556418" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 May 2021 03:53:32 -0700 IronPort-SDR: ELIydWx4IpQxYKm8vFPjf6Cu01V7HCWXzaGXlMeSe4pPAKHJgmH7e6lHW9TBhTn7RTqU1ew5F7 d5fe0sLAEuvg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.82,331,1613462400"; d="scan'208";a="436079185" Received: from nntpat99-84.inn.intel.com ([10.125.99.84]) by orsmga007.jf.intel.com with ESMTP; 26 May 2021 03:53:30 -0700 From: Alexey Bayduraev To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Alexander Shishkin , Peter Zijlstra , Ingo Molnar , linux-kernel , Andi Kleen , Adrian Hunter , Alexander Antonov , Alexei Budankov Subject: [PATCH v6 05/20] perf record: Start threads in the beginning of trace streaming Date: Wed, 26 May 2021 13:52:58 +0300 Message-Id: X-Mailer: git-send-email 2.19.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Start thread in detached state because its management is implemented via messaging to avoid any scaling issues. Block signals prior thread start so only main tool thread would be notified on external async signals during data collection. Thread affinity mask is used to assign eligible cpus for the thread to run. Wait and sync on thread start using thread ack pipe. Signed-off-by: Alexey Bayduraev --- tools/perf/builtin-record.c | 106 +++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 838c1f779849..88fad12cbe5b 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1423,6 +1423,66 @@ static void record__thread_munmap_filtered(struct fdarray *fda, int fd, perf_mmap__put(map); } +static void *record__thread(void *arg) +{ + enum thread_msg msg = THREAD_MSG__READY; + bool terminate = false; + struct fdarray *pollfd; + int err, ctlfd_pos; + + thread = arg; + thread->tid = syscall(SYS_gettid); + + err = write(thread->pipes.ack[1], &msg, sizeof(msg)); + if (err == -1) + pr_err("threads[%d]: failed to notify on start: %s", thread->tid, strerror(errno)); + + pr_debug("threads[%d]: started on cpu=%d\n", thread->tid, sched_getcpu()); + + pollfd = &thread->pollfd; + ctlfd_pos = thread->ctlfd_pos; + + for (;;) { + unsigned long long hits = thread->samples; + + if (record__mmap_read_all(thread->rec, false) < 0 || terminate) + break; + + if (hits == thread->samples) { + + err = fdarray__poll(pollfd, -1); + /* + * Propagate error, only if there's any. Ignore positive + * number of returned events and interrupt error. + */ + if (err > 0 || (err < 0 && errno == EINTR)) + err = 0; + thread->waking++; + + if (fdarray__filter(pollfd, POLLERR | POLLHUP, + record__thread_munmap_filtered, NULL) == 0) + break; + } + + if (pollfd->entries[ctlfd_pos].revents & POLLHUP) { + terminate = true; + close(thread->pipes.msg[0]); + pollfd->entries[ctlfd_pos].fd = -1; + pollfd->entries[ctlfd_pos].events = 0; + } + + pollfd->entries[ctlfd_pos].revents = 0; + } + record__mmap_read_all(thread->rec, true); + + err = write(thread->pipes.ack[1], &msg, sizeof(msg)); + if (err == -1) + pr_err("threads[%d]: failed to notify on termination: %s", + thread->tid, strerror(errno)); + + return NULL; +} + static void record__init_features(struct record *rec) { struct perf_session *session = rec->session; @@ -1886,13 +1946,57 @@ static int record__terminate_thread(struct thread_data *thread_data) static int record__start_threads(struct record *rec) { + int t, tt, ret = 0, nr_threads = rec->nr_threads; struct thread_data *thread_data = rec->thread_data; + sigset_t full, mask; + pthread_t handle; + pthread_attr_t attrs; + + sigfillset(&full); + if (sigprocmask(SIG_SETMASK, &full, &mask)) { + pr_err("Failed to block signals on threads start: %s\n", strerror(errno)); + return -1; + } + + pthread_attr_init(&attrs); + pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED); + + for (t = 1; t < nr_threads; t++) { + enum thread_msg msg = THREAD_MSG__UNDEFINED; + + pthread_attr_setaffinity_np(&attrs, + MMAP_CPU_MASK_BYTES(&(thread_data[t].mask->affinity)), + (cpu_set_t *)(thread_data[t].mask->affinity.bits)); + + if (pthread_create(&handle, &attrs, record__thread, &thread_data[t])) { + for (tt = 1; tt < t; tt++) + record__terminate_thread(&thread_data[t]); + pr_err("Failed to start threads: %s\n", strerror(errno)); + ret = -1; + goto out_err; + } + + if (read(thread_data[t].pipes.ack[0], &msg, sizeof(msg)) > 0) + pr_debug2("threads[%d]: sent %s\n", rec->thread_data[t].tid, + thread_msg_tags[msg]); + } + + if (nr_threads > 1) { + sched_setaffinity(0, MMAP_CPU_MASK_BYTES(&thread_data[0].mask->affinity), + (cpu_set_t *)thread_data[0].mask->affinity.bits); + } thread = &thread_data[0]; pr_debug("threads[%d]: started on cpu=%d\n", thread->tid, sched_getcpu()); - return 0; +out_err: + if (sigprocmask(SIG_SETMASK, &mask, NULL)) { + pr_err("Failed to unblock signals on threads start: %s\n", strerror(errno)); + ret = -1; + } + + return ret; } static int record__stop_threads(struct record *rec, unsigned long *waking) -- 2.19.0