From patchwork Mon Jul 6 20:52:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 73339 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6068BA00C5; Mon, 6 Jul 2020 22:52:59 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 27F2A1DD76; Mon, 6 Jul 2020 22:52:58 +0200 (CEST) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by dpdk.org (Postfix) with ESMTP id 57CE01DD73 for ; Mon, 6 Jul 2020 22:52:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594068775; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3luDOuHXL6VcGyghlQR4RLAC2QnAHL+q7tYCfyn7LmA=; b=P66RNV0FemzqfuJ8beLDSDEqvcbjYJ3YjXagIcC+qrJ7oVw/8c/y0jGm6tAGN4co0Rk/Do h6DjTuSSXA5LveE4EXXA7HknhOz2e1+CMNhqeFNGdjvcVzvcqoeY6q5G572rzBUIB9kxeS eh2C/u3eARD0zXW8E5n0BetaNEJnBYU= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-343-6eYUrWXKOJmhNeDHBBk2dA-1; Mon, 06 Jul 2020 16:52:54 -0400 X-MC-Unique: 6eYUrWXKOJmhNeDHBBk2dA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B09F4107ACCA; Mon, 6 Jul 2020 20:52:51 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.195.188]) by smtp.corp.redhat.com (Postfix) with ESMTP id D0A7F10013D7; Mon, 6 Jul 2020 20:52:46 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: jerinjacobk@gmail.com, bruce.richardson@intel.com, mdr@ashroe.eu, thomas@monjalon.net, arybchenko@solarflare.com, ktraynor@redhat.com, ian.stokes@intel.com, i.maximets@ovn.org, olivier.matz@6wind.com, konstantin.ananyev@intel.com, Harini Ramakrishnan , Omar Cardona , Pallavi Kadam , Ranjit Menon Date: Mon, 6 Jul 2020 22:52:25 +0200 Message-Id: <20200706205234.8040-2-david.marchand@redhat.com> In-Reply-To: <20200706205234.8040-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> <20200706205234.8040-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [dpdk-dev] [PATCH v6 01/10] eal: relocate per thread symbols to common X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" We have per lcore thread symbols scattered in OS implementations but common code relies on them. Move all of them in common. RTE_PER_LCORE(_socket_id) and RTE_PER_LCORE(_cpuset) have public accessors and are not exported through the library map, they can be made static. Signed-off-by: David Marchand Reviewed-by: Olivier Matz --- lib/librte_eal/common/eal_common_thread.c | 5 ++++- lib/librte_eal/freebsd/eal_thread.c | 4 ---- lib/librte_eal/include/rte_lcore.h | 1 - lib/librte_eal/linux/eal_thread.c | 4 ---- lib/librte_eal/windows/eal_thread.c | 4 ---- 5 files changed, 4 insertions(+), 14 deletions(-) diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c index a341070926..7be80c292e 100644 --- a/lib/librte_eal/common/eal_common_thread.c +++ b/lib/librte_eal/common/eal_common_thread.c @@ -21,7 +21,10 @@ #include "eal_private.h" #include "eal_thread.h" -RTE_DECLARE_PER_LCORE(unsigned , _socket_id); +RTE_DEFINE_PER_LCORE(unsigned int, _lcore_id) = LCORE_ID_ANY; +static RTE_DEFINE_PER_LCORE(unsigned int, _socket_id) = + (unsigned int)SOCKET_ID_ANY; +static RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset); unsigned rte_socket_id(void) { diff --git a/lib/librte_eal/freebsd/eal_thread.c b/lib/librte_eal/freebsd/eal_thread.c index b52019782a..40676d9ef5 100644 --- a/lib/librte_eal/freebsd/eal_thread.c +++ b/lib/librte_eal/freebsd/eal_thread.c @@ -25,10 +25,6 @@ #include "eal_private.h" #include "eal_thread.h" -RTE_DEFINE_PER_LCORE(unsigned, _lcore_id) = LCORE_ID_ANY; -RTE_DEFINE_PER_LCORE(unsigned, _socket_id) = (unsigned)SOCKET_ID_ANY; -RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset); - /* * Send a message to a slave lcore identified by slave_id to call a * function f with argument arg. Once the execution is done, the diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h index 339046bc86..5c1d1926e9 100644 --- a/lib/librte_eal/include/rte_lcore.h +++ b/lib/librte_eal/include/rte_lcore.h @@ -23,7 +23,6 @@ extern "C" { #define LCORE_ID_ANY UINT32_MAX /**< Any lcore. */ RTE_DECLARE_PER_LCORE(unsigned, _lcore_id); /**< Per thread "lcore id". */ -RTE_DECLARE_PER_LCORE(rte_cpuset_t, _cpuset); /**< Per thread "cpuset". */ /** * Get a lcore's role. diff --git a/lib/librte_eal/linux/eal_thread.c b/lib/librte_eal/linux/eal_thread.c index cd9d6e0ebf..a52ebef3a4 100644 --- a/lib/librte_eal/linux/eal_thread.c +++ b/lib/librte_eal/linux/eal_thread.c @@ -25,10 +25,6 @@ #include "eal_private.h" #include "eal_thread.h" -RTE_DEFINE_PER_LCORE(unsigned, _lcore_id) = LCORE_ID_ANY; -RTE_DEFINE_PER_LCORE(unsigned, _socket_id) = (unsigned)SOCKET_ID_ANY; -RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset); - /* * Send a message to a slave lcore identified by slave_id to call a * function f with argument arg. Once the execution is done, the diff --git a/lib/librte_eal/windows/eal_thread.c b/lib/librte_eal/windows/eal_thread.c index 3dd56519c9..f12a2ec6ad 100644 --- a/lib/librte_eal/windows/eal_thread.c +++ b/lib/librte_eal/windows/eal_thread.c @@ -16,10 +16,6 @@ #include "eal_private.h" #include "eal_windows.h" -RTE_DEFINE_PER_LCORE(unsigned int, _lcore_id) = LCORE_ID_ANY; -RTE_DEFINE_PER_LCORE(unsigned int, _socket_id) = (unsigned int)SOCKET_ID_ANY; -RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset); - /* * Send a message to a slave lcore identified by slave_id to call a * function f with argument arg. Once the execution is done, the From patchwork Mon Jul 6 20:52:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 73341 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id CFD2BA00C5; Mon, 6 Jul 2020 22:53:15 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 0B41C1DD98; Mon, 6 Jul 2020 22:53:04 +0200 (CEST) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by dpdk.org (Postfix) with ESMTP id 9C1931DDA0 for ; Mon, 6 Jul 2020 22:53:02 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594068782; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=IjQH3o5vrTe6Zpd/Fs4V4CyF2gqsWVvqVq9M2ax0z+o=; b=F/M3S6a1AqbmQLc1lJ3NfJkhGX4HWFAFJkHxKw3/VcJukznujn137oScMUN+jcAMPxe/SE 6mrPdPXjjAM2m7Ab7ieM6A/a1liVwGFrcuO4BRh4oV3HyW1QLhWFYYG+mYCRKe76xMfFv+ CO5CYkOmppzdwPcZ5XjTCoMm5DxMXSQ= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-299-IN6uaA1vPLOOI3q_PAocJg-1; Mon, 06 Jul 2020 16:52:58 -0400 X-MC-Unique: IN6uaA1vPLOOI3q_PAocJg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9C96619057A1; Mon, 6 Jul 2020 20:52:56 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.195.188]) by smtp.corp.redhat.com (Postfix) with ESMTP id 73B1610013D7; Mon, 6 Jul 2020 20:52:52 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: jerinjacobk@gmail.com, bruce.richardson@intel.com, mdr@ashroe.eu, thomas@monjalon.net, arybchenko@solarflare.com, ktraynor@redhat.com, ian.stokes@intel.com, i.maximets@ovn.org, olivier.matz@6wind.com, konstantin.ananyev@intel.com, Neil Horman , Cunming Liang Date: Mon, 6 Jul 2020 22:52:26 +0200 Message-Id: <20200706205234.8040-3-david.marchand@redhat.com> In-Reply-To: <20200706205234.8040-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> <20200706205234.8040-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [dpdk-dev] [PATCH v6 02/10] eal: fix multiple definition of per lcore thread id X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Because of the inline accessor + static declaration in rte_gettid(), we end up with multiple symbols for RTE_PER_LCORE(_thread_id). Each compilation unit will pay a cost when accessing this information for the first time. $ nm build/app/dpdk-testpmd | grep per_lcore__thread_id 0000000000000054 d per_lcore__thread_id.5037 0000000000000040 d per_lcore__thread_id.5103 0000000000000048 d per_lcore__thread_id.5259 000000000000004c d per_lcore__thread_id.5259 0000000000000044 d per_lcore__thread_id.5933 0000000000000058 d per_lcore__thread_id.6261 0000000000000050 d per_lcore__thread_id.7378 000000000000005c d per_lcore__thread_id.7496 000000000000000c d per_lcore__thread_id.8016 0000000000000010 d per_lcore__thread_id.8431 Make it global as part of the DPDK_21 stable ABI. Fixes: ef76436c6834 ("eal: get unique thread id") Signed-off-by: David Marchand Acked-by: Ray Kinsella Reviewed-by: Olivier Matz --- lib/librte_eal/common/eal_common_thread.c | 1 + lib/librte_eal/include/rte_eal.h | 3 ++- lib/librte_eal/rte_eal_version.map | 7 +++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c index 7be80c292e..fd13453fee 100644 --- a/lib/librte_eal/common/eal_common_thread.c +++ b/lib/librte_eal/common/eal_common_thread.c @@ -22,6 +22,7 @@ #include "eal_thread.h" RTE_DEFINE_PER_LCORE(unsigned int, _lcore_id) = LCORE_ID_ANY; +RTE_DEFINE_PER_LCORE(int, _thread_id) = -1; static RTE_DEFINE_PER_LCORE(unsigned int, _socket_id) = (unsigned int)SOCKET_ID_ANY; static RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset); diff --git a/lib/librte_eal/include/rte_eal.h b/lib/librte_eal/include/rte_eal.h index 2f9ed298de..2edf8c6556 100644 --- a/lib/librte_eal/include/rte_eal.h +++ b/lib/librte_eal/include/rte_eal.h @@ -447,6 +447,8 @@ enum rte_intr_mode rte_eal_vfio_intr_mode(void); */ int rte_sys_gettid(void); +RTE_DECLARE_PER_LCORE(int, _thread_id); + /** * Get system unique thread id. * @@ -456,7 +458,6 @@ int rte_sys_gettid(void); */ static inline int rte_gettid(void) { - static RTE_DEFINE_PER_LCORE(int, _thread_id) = -1; if (RTE_PER_LCORE(_thread_id) == -1) RTE_PER_LCORE(_thread_id) = rte_sys_gettid(); return RTE_PER_LCORE(_thread_id); diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map index 196eef5afa..0d42d44ce9 100644 --- a/lib/librte_eal/rte_eal_version.map +++ b/lib/librte_eal/rte_eal_version.map @@ -221,6 +221,13 @@ DPDK_20.0 { local: *; }; +DPDK_21 { + global: + + per_lcore__thread_id; + +} DPDK_20.0; + EXPERIMENTAL { global: From patchwork Mon Jul 6 20:52:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 73342 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0CF73A00C5; Mon, 6 Jul 2020 22:53:24 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 3E4E31DDAC; Mon, 6 Jul 2020 22:53:10 +0200 (CEST) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by dpdk.org (Postfix) with ESMTP id 989A51DD75 for ; Mon, 6 Jul 2020 22:53:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594068788; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=E54v03bb2+hpUh6ihJTcG8VCcAwR1+8C1shjD5kYdQA=; b=hCEOmRTR7jiFXrDa4tgQLCu6QX/JCbr/yzT7ovZ/ffdnSR7K6KhYG3dl8KpWrqWSpxYXAk t+0VoJfbnARORkAnrGV43pBqBqT1A0c6fmJPKJf306LKavD02215ohIAgzvExRU2avAI+a zr8Z1t3EeY0jRna8QWVtKzOBfkgVCc4= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-104-oopeFXeiNFCG8Y6bd4UmPA-1; Mon, 06 Jul 2020 16:53:04 -0400 X-MC-Unique: oopeFXeiNFCG8Y6bd4UmPA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 53AAF19057A0; Mon, 6 Jul 2020 20:53:02 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.195.188]) by smtp.corp.redhat.com (Postfix) with ESMTP id 837CE10013D7; Mon, 6 Jul 2020 20:52:57 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: jerinjacobk@gmail.com, bruce.richardson@intel.com, mdr@ashroe.eu, thomas@monjalon.net, arybchenko@solarflare.com, ktraynor@redhat.com, ian.stokes@intel.com, i.maximets@ovn.org, olivier.matz@6wind.com, konstantin.ananyev@intel.com, Harini Ramakrishnan , Omar Cardona , Pallavi Kadam , Ranjit Menon Date: Mon, 6 Jul 2020 22:52:27 +0200 Message-Id: <20200706205234.8040-4-david.marchand@redhat.com> In-Reply-To: <20200706205234.8040-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> <20200706205234.8040-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [dpdk-dev] [PATCH v6 03/10] eal: introduce thread init helper X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Introduce a helper responsible for initialising the per thread context. We can then have a unified context for EAL and non-EAL threads and remove copy/paste'd OS-specific helpers. Per EAL thread CPU affinity setting is separated from the thread init. It is to accommodate with Windows EAL where CPU affinity is not set at the moment. Besides, having affinity set by the master lcore in FreeBSD and Linux will make it possible to detect errors rather than panic in the child thread. But the cleanup when such an event happens is left for later. A side-effect of this patch is that control threads can now use recursive locks (rte_gettid() was not called before). Signed-off-by: David Marchand --- Changes since v4: - renamed rte_thread_init as __rte_thread_init and moved to eal_private.h, Changes since v1: - rebased on master, removed Windows workarounds wrt gettid and traces support, --- lib/librte_eal/common/eal_common_thread.c | 50 ++++++++++++++--------- lib/librte_eal/common/eal_private.h | 10 +++++ lib/librte_eal/common/eal_thread.h | 8 ---- lib/librte_eal/freebsd/eal.c | 14 ++++++- lib/librte_eal/freebsd/eal_thread.c | 32 +-------------- lib/librte_eal/linux/eal.c | 15 ++++++- lib/librte_eal/linux/eal_thread.c | 32 +-------------- lib/librte_eal/windows/eal.c | 3 +- lib/librte_eal/windows/eal_thread.c | 10 +---- 9 files changed, 71 insertions(+), 103 deletions(-) diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c index fd13453fee..fb06f8f802 100644 --- a/lib/librte_eal/common/eal_common_thread.c +++ b/lib/librte_eal/common/eal_common_thread.c @@ -71,20 +71,10 @@ eal_cpuset_socket_id(rte_cpuset_t *cpusetp) return socket_id; } -int -rte_thread_set_affinity(rte_cpuset_t *cpusetp) +static void +thread_update_affinity(rte_cpuset_t *cpusetp) { - int s; - unsigned lcore_id; - pthread_t tid; - - tid = pthread_self(); - - s = pthread_setaffinity_np(tid, sizeof(rte_cpuset_t), cpusetp); - if (s != 0) { - RTE_LOG(ERR, EAL, "pthread_setaffinity_np failed\n"); - return -1; - } + unsigned int lcore_id = rte_lcore_id(); /* store socket_id in TLS for quick access */ RTE_PER_LCORE(_socket_id) = @@ -94,14 +84,24 @@ rte_thread_set_affinity(rte_cpuset_t *cpusetp) memmove(&RTE_PER_LCORE(_cpuset), cpusetp, sizeof(rte_cpuset_t)); - lcore_id = rte_lcore_id(); if (lcore_id != (unsigned)LCORE_ID_ANY) { /* EAL thread will update lcore_config */ lcore_config[lcore_id].socket_id = RTE_PER_LCORE(_socket_id); memmove(&lcore_config[lcore_id].cpuset, cpusetp, sizeof(rte_cpuset_t)); } +} + +int +rte_thread_set_affinity(rte_cpuset_t *cpusetp) +{ + if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t), + cpusetp) != 0) { + RTE_LOG(ERR, EAL, "pthread_setaffinity_np failed\n"); + return -1; + } + thread_update_affinity(cpusetp); return 0; } @@ -147,6 +147,19 @@ eal_thread_dump_affinity(char *str, unsigned size) return ret; } +void +__rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset) +{ + /* set the lcore ID in per-lcore memory area */ + RTE_PER_LCORE(_lcore_id) = lcore_id; + + /* acquire system unique id */ + rte_gettid(); + + thread_update_affinity(cpuset); + + __rte_trace_mem_per_thread_alloc(); +} struct rte_thread_ctrl_params { void *(*start_routine)(void *); @@ -154,7 +167,7 @@ struct rte_thread_ctrl_params { pthread_barrier_t configured; }; -static void *rte_thread_init(void *arg) +static void *ctrl_thread_init(void *arg) { int ret; struct internal_config *internal_conf = @@ -164,8 +177,7 @@ static void *rte_thread_init(void *arg) void *(*start_routine)(void *) = params->start_routine; void *routine_arg = params->arg; - /* Store cpuset in TLS for quick access */ - memmove(&RTE_PER_LCORE(_cpuset), cpuset, sizeof(rte_cpuset_t)); + __rte_thread_init(rte_lcore_id(), cpuset); ret = pthread_barrier_wait(¶ms->configured); if (ret == PTHREAD_BARRIER_SERIAL_THREAD) { @@ -173,8 +185,6 @@ static void *rte_thread_init(void *arg) free(params); } - __rte_trace_mem_per_thread_alloc(); - return start_routine(routine_arg); } @@ -198,7 +208,7 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name, pthread_barrier_init(¶ms->configured, NULL, 2); - ret = pthread_create(thread, attr, rte_thread_init, (void *)params); + ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params); if (ret != 0) { free(params); return -ret; diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index 46bcae9305..5d8b53882d 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -699,4 +699,14 @@ eal_get_internal_configuration(void); rte_usage_hook_t eal_get_application_usage_hook(void); +/** + * Init per-lcore info in current thread. + * + * @param lcore_id + * identifier of lcore. + * @param cpuset + * CPU affinity for this thread. + */ +void __rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset); + #endif /* _EAL_PRIVATE_H_ */ diff --git a/lib/librte_eal/common/eal_thread.h b/lib/librte_eal/common/eal_thread.h index b40ed249ed..dc1fc6eb99 100644 --- a/lib/librte_eal/common/eal_thread.h +++ b/lib/librte_eal/common/eal_thread.h @@ -15,14 +15,6 @@ */ __rte_noreturn void *eal_thread_loop(void *arg); -/** - * Init per-lcore info for master thread - * - * @param lcore_id - * identifier of master lcore - */ -void eal_thread_init_master(unsigned lcore_id); - /** * Get the NUMA socket id from cpu id. * This function is private to EAL. diff --git a/lib/librte_eal/freebsd/eal.c b/lib/librte_eal/freebsd/eal.c index 8c75cba79a..fd577daf44 100644 --- a/lib/librte_eal/freebsd/eal.c +++ b/lib/librte_eal/freebsd/eal.c @@ -845,7 +845,14 @@ rte_eal_init(int argc, char **argv) eal_check_mem_on_local_socket(); - eal_thread_init_master(config->master_lcore); + if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t), + &lcore_config[config->master_lcore].cpuset) != 0) { + rte_eal_init_alert("Cannot set affinity"); + rte_errno = EINVAL; + return -1; + } + __rte_thread_init(config->master_lcore, + &lcore_config[config->master_lcore].cpuset); ret = eal_thread_dump_affinity(cpuset, sizeof(cpuset)); @@ -876,6 +883,11 @@ rte_eal_init(int argc, char **argv) snprintf(thread_name, sizeof(thread_name), "lcore-slave-%d", i); rte_thread_setname(lcore_config[i].thread_id, thread_name); + + ret = pthread_setaffinity_np(lcore_config[i].thread_id, + sizeof(rte_cpuset_t), &lcore_config[i].cpuset); + if (ret != 0) + rte_panic("Cannot set affinity\n"); } /* diff --git a/lib/librte_eal/freebsd/eal_thread.c b/lib/librte_eal/freebsd/eal_thread.c index 40676d9ef5..0788a54fe6 100644 --- a/lib/librte_eal/freebsd/eal_thread.c +++ b/lib/librte_eal/freebsd/eal_thread.c @@ -66,29 +66,6 @@ rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned slave_id) return rc; } -/* set affinity for current thread */ -static int -eal_thread_set_affinity(void) -{ - unsigned lcore_id = rte_lcore_id(); - - /* acquire system unique id */ - rte_gettid(); - - /* update EAL thread core affinity */ - return rte_thread_set_affinity(&lcore_config[lcore_id].cpuset); -} - -void eal_thread_init_master(unsigned lcore_id) -{ - /* set the lcore ID in per-lcore memory area */ - RTE_PER_LCORE(_lcore_id) = lcore_id; - - /* set CPU affinity */ - if (eal_thread_set_affinity() < 0) - rte_panic("cannot set affinity\n"); -} - /* main loop of threads */ __rte_noreturn void * eal_thread_loop(__rte_unused void *arg) @@ -113,19 +90,12 @@ eal_thread_loop(__rte_unused void *arg) m2s = lcore_config[lcore_id].pipe_master2slave[0]; s2m = lcore_config[lcore_id].pipe_slave2master[1]; - /* set the lcore ID in per-lcore memory area */ - RTE_PER_LCORE(_lcore_id) = lcore_id; - - /* set CPU affinity */ - if (eal_thread_set_affinity() < 0) - rte_panic("cannot set affinity\n"); + __rte_thread_init(lcore_id, &lcore_config[lcore_id].cpuset); ret = eal_thread_dump_affinity(cpuset, sizeof(cpuset)); - RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=%p;cpuset=[%s%s])\n", lcore_id, thread_id, cpuset, ret == 0 ? "" : "..."); - __rte_trace_mem_per_thread_alloc(); rte_eal_trace_thread_lcore_ready(lcore_id, cpuset); /* read on our pipe to get commands */ diff --git a/lib/librte_eal/linux/eal.c b/lib/librte_eal/linux/eal.c index 3b56d14da1..bd089cdd44 100644 --- a/lib/librte_eal/linux/eal.c +++ b/lib/librte_eal/linux/eal.c @@ -1184,10 +1184,16 @@ rte_eal_init(int argc, char **argv) eal_check_mem_on_local_socket(); - eal_thread_init_master(config->master_lcore); + if (pthread_setaffinity_np(pthread_self(), sizeof(rte_cpuset_t), + &lcore_config[config->master_lcore].cpuset) != 0) { + rte_eal_init_alert("Cannot set affinity"); + rte_errno = EINVAL; + return -1; + } + __rte_thread_init(config->master_lcore, + &lcore_config[config->master_lcore].cpuset); ret = eal_thread_dump_affinity(cpuset, sizeof(cpuset)); - RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%zx;cpuset=[%s%s])\n", config->master_lcore, (uintptr_t)thread_id, cpuset, ret == 0 ? "" : "..."); @@ -1219,6 +1225,11 @@ rte_eal_init(int argc, char **argv) if (ret != 0) RTE_LOG(DEBUG, EAL, "Cannot set name for lcore thread\n"); + + ret = pthread_setaffinity_np(lcore_config[i].thread_id, + sizeof(rte_cpuset_t), &lcore_config[i].cpuset); + if (ret != 0) + rte_panic("Cannot set affinity\n"); } /* diff --git a/lib/librte_eal/linux/eal_thread.c b/lib/librte_eal/linux/eal_thread.c index a52ebef3a4..e0440c0000 100644 --- a/lib/librte_eal/linux/eal_thread.c +++ b/lib/librte_eal/linux/eal_thread.c @@ -66,29 +66,6 @@ rte_eal_remote_launch(int (*f)(void *), void *arg, unsigned slave_id) return rc; } -/* set affinity for current EAL thread */ -static int -eal_thread_set_affinity(void) -{ - unsigned lcore_id = rte_lcore_id(); - - /* acquire system unique id */ - rte_gettid(); - - /* update EAL thread core affinity */ - return rte_thread_set_affinity(&lcore_config[lcore_id].cpuset); -} - -void eal_thread_init_master(unsigned lcore_id) -{ - /* set the lcore ID in per-lcore memory area */ - RTE_PER_LCORE(_lcore_id) = lcore_id; - - /* set CPU affinity */ - if (eal_thread_set_affinity() < 0) - rte_panic("cannot set affinity\n"); -} - /* main loop of threads */ __rte_noreturn void * eal_thread_loop(__rte_unused void *arg) @@ -113,19 +90,12 @@ eal_thread_loop(__rte_unused void *arg) m2s = lcore_config[lcore_id].pipe_master2slave[0]; s2m = lcore_config[lcore_id].pipe_slave2master[1]; - /* set the lcore ID in per-lcore memory area */ - RTE_PER_LCORE(_lcore_id) = lcore_id; - - /* set CPU affinity */ - if (eal_thread_set_affinity() < 0) - rte_panic("cannot set affinity\n"); + __rte_thread_init(lcore_id, &lcore_config[lcore_id].cpuset); ret = eal_thread_dump_affinity(cpuset, sizeof(cpuset)); - RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=%zx;cpuset=[%s%s])\n", lcore_id, (uintptr_t)thread_id, cpuset, ret == 0 ? "" : "..."); - __rte_trace_mem_per_thread_alloc(); rte_eal_trace_thread_lcore_ready(lcore_id, cpuset); /* read on our pipe to get commands */ diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c index eb10b4ef96..9f5d019e64 100644 --- a/lib/librte_eal/windows/eal.c +++ b/lib/librte_eal/windows/eal.c @@ -333,7 +333,8 @@ rte_eal_init(int argc, char **argv) return -1; } - eal_thread_init_master(config->master_lcore); + __rte_thread_init(config->master_lcore, + &lcore_config[config->master_lcore].cpuset); bscan = rte_bus_scan(); if (bscan < 0) { diff --git a/lib/librte_eal/windows/eal_thread.c b/lib/librte_eal/windows/eal_thread.c index f12a2ec6ad..20889b6196 100644 --- a/lib/librte_eal/windows/eal_thread.c +++ b/lib/librte_eal/windows/eal_thread.c @@ -53,13 +53,6 @@ rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned int slave_id) return 0; } -void -eal_thread_init_master(unsigned int lcore_id) -{ - /* set the lcore ID in per-lcore memory area */ - RTE_PER_LCORE(_lcore_id) = lcore_id; -} - /* main loop of threads */ void * eal_thread_loop(void *arg __rte_unused) @@ -84,8 +77,7 @@ eal_thread_loop(void *arg __rte_unused) m2s = lcore_config[lcore_id].pipe_master2slave[0]; s2m = lcore_config[lcore_id].pipe_slave2master[1]; - /* set the lcore ID in per-lcore memory area */ - RTE_PER_LCORE(_lcore_id) = lcore_id; + __rte_thread_init(lcore_id, &lcore_config[lcore_id].cpuset); RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=%zx;cpuset=[%s])\n", lcore_id, (uintptr_t)thread_id, cpuset); From patchwork Mon Jul 6 20:52:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 73343 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8F87EA00C5; Mon, 6 Jul 2020 22:53:33 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 447C31DDBA; Mon, 6 Jul 2020 22:53:16 +0200 (CEST) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by dpdk.org (Postfix) with ESMTP id ED3D71DDB2 for ; Mon, 6 Jul 2020 22:53:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594068794; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ED4q3Pdx0l6mBkvLKMsv27ndbihL6yPAg0JeujBn7Eg=; b=LXflOfDIWQs1pI28G5KqtaxzoUoHRoLHUeqZNCiTZolFNGnxzqh8J71V+f66aO4JXuzdPE FO7Dd+53LT38ySlTUvOIGB2zosaEHdqIaZ7aowbiYiZzUmeOjN8kn4pyje5q52dXAC8alT a2UWI6XCPEGbWFtOzFvi6qSUWvrcaOs= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-147-VaaJtE0MOiW20SscaOXETw-1; Mon, 06 Jul 2020 16:53:10 -0400 X-MC-Unique: VaaJtE0MOiW20SscaOXETw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 78362107B7C5; Mon, 6 Jul 2020 20:53:08 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.195.188]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1079A10013D7; Mon, 6 Jul 2020 20:53:02 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: jerinjacobk@gmail.com, bruce.richardson@intel.com, mdr@ashroe.eu, thomas@monjalon.net, arybchenko@solarflare.com, ktraynor@redhat.com, ian.stokes@intel.com, i.maximets@ovn.org, olivier.matz@6wind.com, konstantin.ananyev@intel.com, Jerin Jacob , Sunil Kumar Kori , Harini Ramakrishnan , Omar Cardona , Pallavi Kadam , Ranjit Menon Date: Mon, 6 Jul 2020 22:52:28 +0200 Message-Id: <20200706205234.8040-5-david.marchand@redhat.com> In-Reply-To: <20200706205234.8040-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> <20200706205234.8040-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [dpdk-dev] [PATCH v6 04/10] eal: introduce thread uninit helper X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This is a preparation step for dynamically unregistering threads. Since we explicitly allocate a per thread trace buffer in __rte_thread_init, add an internal helper to free this buffer. Signed-off-by: David Marchand --- Changes since v5: - fixed windows build, Changes since v4: - renamed rte_thread_uninit and moved to eal_private.h, - hid freeing helper, Changes since v2: - added missing stub for windows tracing support, - moved free symbol to exported (experimental) ABI as a counterpart of the alloc symbol we already had, Changes since v1: - rebased on master, removed Windows workaround wrt traces support, --- lib/librte_eal/common/eal_common_thread.c | 9 +++++ lib/librte_eal/common/eal_common_trace.c | 49 +++++++++++++++++++---- lib/librte_eal/common/eal_private.h | 5 +++ lib/librte_eal/common/eal_trace.h | 1 + lib/librte_eal/windows/eal.c | 7 +++- 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c index fb06f8f802..6d1c87b1c2 100644 --- a/lib/librte_eal/common/eal_common_thread.c +++ b/lib/librte_eal/common/eal_common_thread.c @@ -20,6 +20,7 @@ #include "eal_internal_cfg.h" #include "eal_private.h" #include "eal_thread.h" +#include "eal_trace.h" RTE_DEFINE_PER_LCORE(unsigned int, _lcore_id) = LCORE_ID_ANY; RTE_DEFINE_PER_LCORE(int, _thread_id) = -1; @@ -161,6 +162,14 @@ __rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset) __rte_trace_mem_per_thread_alloc(); } +void +__rte_thread_uninit(void) +{ + trace_mem_per_thread_free(); + + RTE_PER_LCORE(_lcore_id) = LCORE_ID_ANY; +} + struct rte_thread_ctrl_params { void *(*start_routine)(void *); void *arg; diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c index 875553d7e5..b6da5537fe 100644 --- a/lib/librte_eal/common/eal_common_trace.c +++ b/lib/librte_eal/common/eal_common_trace.c @@ -101,7 +101,7 @@ eal_trace_fini(void) { if (!rte_trace_is_enabled()) return; - trace_mem_per_thread_free(); + trace_mem_free(); trace_metadata_destroy(); eal_trace_args_free(); } @@ -370,24 +370,59 @@ __rte_trace_mem_per_thread_alloc(void) rte_spinlock_unlock(&trace->lock); } +static void +trace_mem_per_thread_free_unlocked(struct thread_mem_meta *meta) +{ + if (meta->area == TRACE_AREA_HUGEPAGE) + eal_free_no_trace(meta->mem); + else if (meta->area == TRACE_AREA_HEAP) + free(meta->mem); +} + void trace_mem_per_thread_free(void) +{ + struct trace *trace = trace_obj_get(); + struct __rte_trace_header *header; + uint32_t count; + + header = RTE_PER_LCORE(trace_mem); + if (header == NULL) + return; + + rte_spinlock_lock(&trace->lock); + for (count = 0; count < trace->nb_trace_mem_list; count++) { + if (trace->lcore_meta[count].mem == header) + break; + } + if (count != trace->nb_trace_mem_list) { + struct thread_mem_meta *meta = &trace->lcore_meta[count]; + + trace_mem_per_thread_free_unlocked(meta); + if (count != trace->nb_trace_mem_list - 1) { + memmove(meta, meta + 1, + sizeof(*meta) * + (trace->nb_trace_mem_list - count - 1)); + } + trace->nb_trace_mem_list--; + } + rte_spinlock_unlock(&trace->lock); +} + +void +trace_mem_free(void) { struct trace *trace = trace_obj_get(); uint32_t count; - void *mem; if (!rte_trace_is_enabled()) return; rte_spinlock_lock(&trace->lock); for (count = 0; count < trace->nb_trace_mem_list; count++) { - mem = trace->lcore_meta[count].mem; - if (trace->lcore_meta[count].area == TRACE_AREA_HUGEPAGE) - eal_free_no_trace(mem); - else if (trace->lcore_meta[count].area == TRACE_AREA_HEAP) - free(mem); + trace_mem_per_thread_free_unlocked(&trace->lcore_meta[count]); } + trace->nb_trace_mem_list = 0; rte_spinlock_unlock(&trace->lock); } diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index 5d8b53882d..a77ac7a963 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -709,4 +709,9 @@ eal_get_application_usage_hook(void); */ void __rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset); +/** + * Uninitialize per-lcore info for current thread. + */ +void __rte_thread_uninit(void); + #endif /* _EAL_PRIVATE_H_ */ diff --git a/lib/librte_eal/common/eal_trace.h b/lib/librte_eal/common/eal_trace.h index 8f60616156..92c5951c3a 100644 --- a/lib/librte_eal/common/eal_trace.h +++ b/lib/librte_eal/common/eal_trace.h @@ -106,6 +106,7 @@ int trace_metadata_create(void); void trace_metadata_destroy(void); int trace_mkdir(void); int trace_epoch_time_save(void); +void trace_mem_free(void); void trace_mem_per_thread_free(void); /* EAL interface */ diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c index 9f5d019e64..addac62ae5 100644 --- a/lib/librte_eal/windows/eal.c +++ b/lib/librte_eal/windows/eal.c @@ -17,10 +17,10 @@ #include #include #include -#include #include #include "eal_hugepages.h" +#include "eal_trace.h" #include "eal_windows.h" #define MEMSIZE_IF_NO_HUGE_PAGE (64ULL * 1024ULL * 1024ULL) @@ -215,6 +215,11 @@ __rte_trace_mem_per_thread_alloc(void) { } +void +trace_mem_per_thread_free(void) +{ +} + void __rte_trace_point_emit_field(size_t sz, const char *field, const char *type) From patchwork Mon Jul 6 20:52:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 73344 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 64D9CA00C5; Mon, 6 Jul 2020 22:53:45 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 07F0A1DDCB; Mon, 6 Jul 2020 22:53:19 +0200 (CEST) Received: from us-smtp-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by dpdk.org (Postfix) with ESMTP id 9699D1DDB2 for ; Mon, 6 Jul 2020 22:53:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594068796; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Y5UmPDetSguFHR7+Q6HgUR9fIKdBU6knHAb/1PE6gVg=; b=ZHW949MJq+UDCzT5Xqj9tOMyOqolKsAHsNizVI3jsq+KIFaAU0Kzwqqhz3avCr0N32EPZ0 DGXJJqkHULY7MPoV3rCE0tRKUCGtHB7mUVCSG6SFw6FIGxj3cuRdDHkDQ1hNFWEy3QPpeT URMTgJ+EFQ+wt4eeaxc7B/fVSLK8HQg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-17-AnpXXKGrOSW0jv0XcyCXRQ-1; Mon, 06 Jul 2020 16:53:14 -0400 X-MC-Unique: AnpXXKGrOSW0jv0XcyCXRQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id AC843107ACCA; Mon, 6 Jul 2020 20:53:12 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.195.188]) by smtp.corp.redhat.com (Postfix) with ESMTP id EF98C10013D7; Mon, 6 Jul 2020 20:53:08 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: jerinjacobk@gmail.com, bruce.richardson@intel.com, mdr@ashroe.eu, thomas@monjalon.net, arybchenko@solarflare.com, ktraynor@redhat.com, ian.stokes@intel.com, i.maximets@ovn.org, olivier.matz@6wind.com, konstantin.ananyev@intel.com Date: Mon, 6 Jul 2020 22:52:29 +0200 Message-Id: <20200706205234.8040-6-david.marchand@redhat.com> In-Reply-To: <20200706205234.8040-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> <20200706205234.8040-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [dpdk-dev] [PATCH v6 05/10] eal: move lcore role code X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" For consistency sake, move all lcore role code in the dedicated compilation unit / header. Signed-off-by: David Marchand Reviewed-by: Olivier Matz --- lib/librte_eal/common/eal_common_lcore.c | 11 +++++++ lib/librte_eal/common/eal_common_thread.c | 11 ------- lib/librte_eal/include/rte_eal.h | 9 ------ lib/librte_eal/include/rte_lcore.h | 37 ++++++++++++++--------- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/lib/librte_eal/common/eal_common_lcore.c b/lib/librte_eal/common/eal_common_lcore.c index 5404922a87..86d32a3dd7 100644 --- a/lib/librte_eal/common/eal_common_lcore.c +++ b/lib/librte_eal/common/eal_common_lcore.c @@ -63,6 +63,17 @@ rte_eal_lcore_role(unsigned int lcore_id) return cfg->lcore_role[lcore_id]; } +int +rte_lcore_has_role(unsigned int lcore_id, enum rte_lcore_role_t role) +{ + struct rte_config *cfg = rte_eal_get_configuration(); + + if (lcore_id >= RTE_MAX_LCORE) + return -EINVAL; + + return cfg->lcore_role[lcore_id] == role; +} + int rte_lcore_is_enabled(unsigned int lcore_id) { struct rte_config *cfg = rte_eal_get_configuration(); diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c index 6d1c87b1c2..b1b69ea58c 100644 --- a/lib/librte_eal/common/eal_common_thread.c +++ b/lib/librte_eal/common/eal_common_thread.c @@ -33,17 +33,6 @@ unsigned rte_socket_id(void) return RTE_PER_LCORE(_socket_id); } -int -rte_lcore_has_role(unsigned int lcore_id, enum rte_lcore_role_t role) -{ - struct rte_config *cfg = rte_eal_get_configuration(); - - if (lcore_id >= RTE_MAX_LCORE) - return -EINVAL; - - return cfg->lcore_role[lcore_id] == role; -} - static int eal_cpuset_socket_id(rte_cpuset_t *cpusetp) { diff --git a/lib/librte_eal/include/rte_eal.h b/lib/librte_eal/include/rte_eal.h index 2edf8c6556..0913d1947c 100644 --- a/lib/librte_eal/include/rte_eal.h +++ b/lib/librte_eal/include/rte_eal.h @@ -31,15 +31,6 @@ extern "C" { /* Maximum thread_name length. */ #define RTE_MAX_THREAD_NAME_LEN 16 -/** - * The lcore role (used in RTE or not). - */ -enum rte_lcore_role_t { - ROLE_RTE, - ROLE_OFF, - ROLE_SERVICE, -}; - /** * The type of process in a linux, multi-process setup */ diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h index 5c1d1926e9..3968c40693 100644 --- a/lib/librte_eal/include/rte_lcore.h +++ b/lib/librte_eal/include/rte_lcore.h @@ -24,6 +24,15 @@ extern "C" { RTE_DECLARE_PER_LCORE(unsigned, _lcore_id); /**< Per thread "lcore id". */ +/** + * The lcore role (used in RTE or not). + */ +enum rte_lcore_role_t { + ROLE_RTE, + ROLE_OFF, + ROLE_SERVICE, +}; + /** * Get a lcore's role. * @@ -34,6 +43,20 @@ RTE_DECLARE_PER_LCORE(unsigned, _lcore_id); /**< Per thread "lcore id". */ */ enum rte_lcore_role_t rte_eal_lcore_role(unsigned int lcore_id); +/** + * Test if the core supplied has a specific role + * + * @param lcore_id + * The identifier of the lcore, which MUST be between 0 and + * RTE_MAX_LCORE-1. + * @param role + * The role to be checked against. + * @return + * Boolean value: positive if test is true; otherwise returns 0. + */ +int +rte_lcore_has_role(unsigned int lcore_id, enum rte_lcore_role_t role); + /** * Return the Application thread ID of the execution unit. * @@ -283,20 +306,6 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); -/** - * Test if the core supplied has a specific role - * - * @param lcore_id - * The identifier of the lcore, which MUST be between 0 and - * RTE_MAX_LCORE-1. - * @param role - * The role to be checked against. - * @return - * Boolean value: positive if test is true; otherwise returns 0. - */ -int -rte_lcore_has_role(unsigned int lcore_id, enum rte_lcore_role_t role); - #ifdef __cplusplus } #endif From patchwork Mon Jul 6 20:52:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 73345 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id CA3FFA00C5; Mon, 6 Jul 2020 22:53:53 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 4C8871DDCE; Mon, 6 Jul 2020 22:53:29 +0200 (CEST) Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by dpdk.org (Postfix) with ESMTP id 1EEEA1DDCE for ; Mon, 6 Jul 2020 22:53:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594068807; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7GnBLaBgohnmmMWWfUZKbaGzOT3iZtxW1Iw49Yb2uT0=; b=iASDCLVv6V8XQ35BTP5eu3bnXmx/vtjQZQ1x163GjHgTae3utQKfW7isdEJFd9X2hD/Ndd ynmFtzb2WhtN5xRaCBmigGiqRYDknTpgLqTQ8pwiSH+CZYfQlaPYIF3DjdnYK5K6aNMPPN QwmP5nFjWP4n6cuB94xb2eNYo6MzBzY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-243--sLRaC3APZm6YcESMdx_iQ-1; Mon, 06 Jul 2020 16:53:23 -0400 X-MC-Unique: -sLRaC3APZm6YcESMdx_iQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 64CA2107ACCD; Mon, 6 Jul 2020 20:53:21 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.195.188]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7D66E1001B07; Mon, 6 Jul 2020 20:53:13 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: jerinjacobk@gmail.com, bruce.richardson@intel.com, mdr@ashroe.eu, thomas@monjalon.net, arybchenko@solarflare.com, ktraynor@redhat.com, ian.stokes@intel.com, i.maximets@ovn.org, olivier.matz@6wind.com, konstantin.ananyev@intel.com, John McNamara , Marko Kovacevic , Anatoly Burakov , Neil Horman , Harini Ramakrishnan , Omar Cardona , Pallavi Kadam , Ranjit Menon Date: Mon, 6 Jul 2020 22:52:30 +0200 Message-Id: <20200706205234.8040-7-david.marchand@redhat.com> In-Reply-To: <20200706205234.8040-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> <20200706205234.8040-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [dpdk-dev] [PATCH v6 06/10] eal: register non-EAL threads as lcores X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" DPDK allows calling some part of its API from a non-EAL thread but this has some limitations. OVS (and other applications) has its own thread management but still want to avoid such limitations by hacking RTE_PER_LCORE(_lcore_id) and faking EAL threads potentially unknown of some DPDK component. Introduce a new API to register non-EAL thread and associate them to a free lcore with a new NON_EAL role. This role denotes lcores that do not run DPDK mainloop and as such prevents use of rte_eal_wait_lcore() and consorts. Multiprocess is not supported as the need for cohabitation with this new feature is unclear at the moment. Signed-off-by: David Marchand Acked-by: Andrew Rybchenko Acked-by: Thomas Monjalon --- Changes since v5: - added release notes, - fixed windows build, Changes since v4: - returned an error when rte_thread_register fails + set rte_errno, - prefixed unit tests logs with Error: when applicable, Changes since v2: - refused multiprocess init once rte_thread_register got called, and vice versa, - added warning on multiprocess in rte_thread_register doxygen, Changes since v1: - moved cleanup on lcore role code in patch 5, - added unit test, - updated documentation, - changed naming from "external thread" to "registered non-EAL thread" --- MAINTAINERS | 1 + app/test/Makefile | 1 + app/test/autotest_data.py | 6 + app/test/meson.build | 2 + app/test/test_lcores.c | 143 ++++++++++++++++++ doc/guides/howto/debug_troubleshoot.rst | 5 +- .../prog_guide/env_abstraction_layer.rst | 22 +-- doc/guides/prog_guide/mempool_lib.rst | 2 +- doc/guides/rel_notes/release_20_08.rst | 6 + lib/librte_eal/common/eal_common_lcore.c | 45 +++++- lib/librte_eal/common/eal_common_proc.c | 42 +++++ lib/librte_eal/common/eal_common_thread.c | 49 +++++- lib/librte_eal/common/eal_memcfg.h | 2 + lib/librte_eal/common/eal_private.h | 28 ++++ lib/librte_eal/freebsd/eal.c | 4 + lib/librte_eal/include/rte_lcore.h | 28 +++- lib/librte_eal/linux/eal.c | 4 + lib/librte_eal/rte_eal_version.map | 4 + lib/librte_eal/windows/eal.c | 6 + lib/librte_mempool/rte_mempool.h | 11 +- 20 files changed, 388 insertions(+), 23 deletions(-) create mode 100644 app/test/test_lcores.c diff --git a/MAINTAINERS b/MAINTAINERS index 27a7be8e64..5a0e1b48b2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -182,6 +182,7 @@ F: app/test/test_cycles.c F: app/test/test_debug.c F: app/test/test_eal* F: app/test/test_errno.c +F: app/test/test_lcores.c F: app/test/test_logs.c F: app/test/test_memcpy* F: app/test/test_per_lcore.c diff --git a/app/test/Makefile b/app/test/Makefile index e5440774b1..f4065271e4 100644 --- a/app/test/Makefile +++ b/app/test/Makefile @@ -98,6 +98,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_FLOW_CLASSIFY) += test_flow_classify.c endif SRCS-y += test_rwlock.c +SRCS-y += test_lcores.c SRCS-$(CONFIG_RTE_LIBRTE_STACK) += test_stack.c SRCS-$(CONFIG_RTE_LIBRTE_STACK) += test_stack_perf.c diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py index 238ab631b4..4b7da45e09 100644 --- a/app/test/autotest_data.py +++ b/app/test/autotest_data.py @@ -62,6 +62,12 @@ "Func": rwlock_autotest, "Report": None, }, + { + "Name": "Lcores autotest", + "Command": "lcores_autotest", + "Func": default_autotest, + "Report": None, + }, { "Name": "Logs autotest", "Command": "logs_autotest", diff --git a/app/test/meson.build b/app/test/meson.build index 56591db4e0..86b4d4d490 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -67,6 +67,7 @@ test_sources = files('commands.c', 'test_ipsec_perf.c', 'test_kni.c', 'test_kvargs.c', + 'test_lcores.c', 'test_logs.c', 'test_lpm.c', 'test_lpm6.c', @@ -207,6 +208,7 @@ fast_tests = [ ['hash_autotest', true], ['interrupt_autotest', true], ['ipfrag_autotest', false], + ['lcores_autotest', true], ['logs_autotest', true], ['lpm_autotest', true], ['lpm6_autotest', true], diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c new file mode 100644 index 0000000000..afb9cdd444 --- /dev/null +++ b/app/test/test_lcores.c @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2020 Red Hat, Inc. + */ + +#include +#include + +#include +#include + +#include "test.h" + +struct thread_context { + enum { INIT, ERROR, DONE } state; + bool lcore_id_any; + pthread_t id; + unsigned int *registered_count; +}; + +static void *thread_loop(void *arg) +{ + struct thread_context *t = arg; + unsigned int lcore_id; + + lcore_id = rte_lcore_id(); + if (lcore_id != LCORE_ID_ANY) { + printf("Error: incorrect lcore id for new thread %u\n", lcore_id); + t->state = ERROR; + } + if (rte_thread_register() < 0) + printf("Warning: could not register new thread (this might be expected during this test), reason %s\n", + rte_strerror(rte_errno)); + lcore_id = rte_lcore_id(); + if ((t->lcore_id_any && lcore_id != LCORE_ID_ANY) || + (!t->lcore_id_any && lcore_id == LCORE_ID_ANY)) { + printf("Error: could not register new thread, got %u while %sexpecting %u\n", + lcore_id, t->lcore_id_any ? "" : "not ", LCORE_ID_ANY); + t->state = ERROR; + } + /* Report register happened to the control thread. */ + __atomic_add_fetch(t->registered_count, 1, __ATOMIC_RELEASE); + + /* Wait for release from the control thread. */ + while (__atomic_load_n(t->registered_count, __ATOMIC_ACQUIRE) != 0) + ; + rte_thread_unregister(); + lcore_id = rte_lcore_id(); + if (lcore_id != LCORE_ID_ANY) { + printf("Error: could not unregister new thread, %u still assigned\n", + lcore_id); + t->state = ERROR; + } + + if (t->state != ERROR) + t->state = DONE; + + return NULL; +} + +static int +test_non_eal_lcores(unsigned int eal_threads_count) +{ + struct thread_context thread_contexts[RTE_MAX_LCORE]; + unsigned int non_eal_threads_count; + unsigned int registered_count; + struct thread_context *t; + unsigned int i; + int ret; + + non_eal_threads_count = 0; + registered_count = 0; + + /* Try to create as many threads as possible. */ + for (i = 0; i < RTE_MAX_LCORE - eal_threads_count; i++) { + t = &thread_contexts[i]; + t->state = INIT; + t->registered_count = ®istered_count; + t->lcore_id_any = false; + if (pthread_create(&t->id, NULL, thread_loop, t) != 0) + break; + non_eal_threads_count++; + } + printf("non-EAL threads count: %u\n", non_eal_threads_count); + /* Wait all non-EAL threads to register. */ + while (__atomic_load_n(®istered_count, __ATOMIC_ACQUIRE) != + non_eal_threads_count) + ; + + /* We managed to create the max number of threads, let's try to create + * one more. This will allow one more check. + */ + if (eal_threads_count + non_eal_threads_count < RTE_MAX_LCORE) + goto skip_lcore_any; + t = &thread_contexts[non_eal_threads_count]; + t->state = INIT; + t->registered_count = ®istered_count; + t->lcore_id_any = true; + if (pthread_create(&t->id, NULL, thread_loop, t) == 0) { + non_eal_threads_count++; + printf("non-EAL threads count: %u\n", non_eal_threads_count); + while (__atomic_load_n(®istered_count, __ATOMIC_ACQUIRE) != + non_eal_threads_count) + ; + } + +skip_lcore_any: + /* Release all threads, and check their states. */ + __atomic_store_n(®istered_count, 0, __ATOMIC_RELEASE); + ret = 0; + for (i = 0; i < non_eal_threads_count; i++) { + t = &thread_contexts[i]; + pthread_join(t->id, NULL); + if (t->state != DONE) + ret = -1; + } + + return ret; +} + +static int +test_lcores(void) +{ + unsigned int eal_threads_count = 0; + unsigned int i; + + for (i = 0; i < RTE_MAX_LCORE; i++) { + if (!rte_lcore_has_role(i, ROLE_OFF)) + eal_threads_count++; + } + if (eal_threads_count == 0) { + printf("Error: something is broken, no EAL thread detected.\n"); + return TEST_FAILED; + } + printf("EAL threads count: %u, RTE_MAX_LCORE=%u\n", eal_threads_count, + RTE_MAX_LCORE); + + if (test_non_eal_lcores(eal_threads_count) < 0) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +REGISTER_TEST_COMMAND(lcores_autotest, test_lcores); diff --git a/doc/guides/howto/debug_troubleshoot.rst b/doc/guides/howto/debug_troubleshoot.rst index cef016b2fe..5a46f5fba3 100644 --- a/doc/guides/howto/debug_troubleshoot.rst +++ b/doc/guides/howto/debug_troubleshoot.rst @@ -307,8 +307,9 @@ Custom worker function :numref:`dtg_distributor_worker`. #. Configuration issue isolation - * Identify core role using ``rte_eal_lcore_role`` to identify RTE, OFF and - SERVICE. Check performance functions are mapped to run on the cores. + * Identify core role using ``rte_eal_lcore_role`` to identify RTE, OFF, + SERVICE and NON_EAL. Check performance functions are mapped to run on the + cores. * For high-performance execution logic ensure running it on correct NUMA and non-master core. diff --git a/doc/guides/prog_guide/env_abstraction_layer.rst b/doc/guides/prog_guide/env_abstraction_layer.rst index 48a2fec066..f64ae953d1 100644 --- a/doc/guides/prog_guide/env_abstraction_layer.rst +++ b/doc/guides/prog_guide/env_abstraction_layer.rst @@ -564,9 +564,13 @@ It's also compatible with the pattern of corelist('-l') option. non-EAL pthread support ~~~~~~~~~~~~~~~~~~~~~~~ -It is possible to use the DPDK execution context with any user pthread (aka. Non-EAL pthreads). -In a non-EAL pthread, the *_lcore_id* is always LCORE_ID_ANY which identifies that it is not an EAL thread with a valid, unique, *_lcore_id*. -Some libraries will use an alternative unique ID (e.g. TID), some will not be impacted at all, and some will work but with limitations (e.g. timer and mempool libraries). +It is possible to use the DPDK execution context with any user pthread (aka. non-EAL pthreads). +There are two kinds of non-EAL pthreads: + +- a registered non-EAL pthread with a valid *_lcore_id* that was successfully assigned by calling ``rte_thread_register()``, +- a non registered non-EAL pthread with a LCORE_ID_ANY, + +For non registered non-EAL pthread (with a LCORE_ID_ANY *_lcore_id*), some libraries will use an alternative unique ID (e.g. TID), some will not be impacted at all, and some will work but with limitations (e.g. timer and mempool libraries). All these impacts are mentioned in :ref:`known_issue_label` section. @@ -613,9 +617,9 @@ Known Issues + rte_mempool The rte_mempool uses a per-lcore cache inside the mempool. - For non-EAL pthreads, ``rte_lcore_id()`` will not return a valid number. - So for now, when rte_mempool is used with non-EAL pthreads, the put/get operations will bypass the default mempool cache and there is a performance penalty because of this bypass. - Only user-owned external caches can be used in a non-EAL context in conjunction with ``rte_mempool_generic_put()`` and ``rte_mempool_generic_get()`` that accept an explicit cache parameter. + For unregistered non-EAL pthreads, ``rte_lcore_id()`` will not return a valid number. + So for now, when rte_mempool is used with unregistered non-EAL pthreads, the put/get operations will bypass the default mempool cache and there is a performance penalty because of this bypass. + Only user-owned external caches can be used in an unregistered non-EAL context in conjunction with ``rte_mempool_generic_put()`` and ``rte_mempool_generic_get()`` that accept an explicit cache parameter. + rte_ring @@ -660,15 +664,15 @@ Known Issues + rte_timer - Running ``rte_timer_manage()`` on a non-EAL pthread is not allowed. However, resetting/stopping the timer from a non-EAL pthread is allowed. + Running ``rte_timer_manage()`` on an unregistered non-EAL pthread is not allowed. However, resetting/stopping the timer from a non-EAL pthread is allowed. + rte_log - In non-EAL pthreads, there is no per thread loglevel and logtype, global loglevels are used. + In unregistered non-EAL pthreads, there is no per thread loglevel and logtype, global loglevels are used. + misc - The debug statistics of rte_ring, rte_mempool and rte_timer are not supported in a non-EAL pthread. + The debug statistics of rte_ring, rte_mempool and rte_timer are not supported in an unregistered non-EAL pthread. cgroup control ~~~~~~~~~~~~~~ diff --git a/doc/guides/prog_guide/mempool_lib.rst b/doc/guides/prog_guide/mempool_lib.rst index f8b430d656..e3e1f940be 100644 --- a/doc/guides/prog_guide/mempool_lib.rst +++ b/doc/guides/prog_guide/mempool_lib.rst @@ -103,7 +103,7 @@ The maximum size of the cache is static and is defined at compilation time (CONF Alternatively to the internal default per-lcore local cache, an application can create and manage external caches through the ``rte_mempool_cache_create()``, ``rte_mempool_cache_free()`` and ``rte_mempool_cache_flush()`` calls. These user-owned caches can be explicitly passed to ``rte_mempool_generic_put()`` and ``rte_mempool_generic_get()``. The ``rte_mempool_default_cache()`` call returns the default internal cache if any. -In contrast to the default caches, user-owned caches can be used by non-EAL threads too. +In contrast to the default caches, user-owned caches can be used by unregistered non-EAL threads too. Mempool Handlers ------------------------ diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst index c0f81d8d40..1cb44be626 100644 --- a/doc/guides/rel_notes/release_20_08.rst +++ b/doc/guides/rel_notes/release_20_08.rst @@ -56,6 +56,12 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= +* **Added non-EAL threads registration API.** + + Added a new API to register non-EAL threads as lcores. This can be used by + applications to have its threads known of DPDK without suffering from the + non-EAL previous limitations in terms of performance. + * **Updated PCAP driver.** Updated PCAP driver with new features and improvements, including: diff --git a/lib/librte_eal/common/eal_common_lcore.c b/lib/librte_eal/common/eal_common_lcore.c index 86d32a3dd7..2b7d262372 100644 --- a/lib/librte_eal/common/eal_common_lcore.c +++ b/lib/librte_eal/common/eal_common_lcore.c @@ -6,13 +6,15 @@ #include #include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include "eal_memcfg.h" #include "eal_private.h" #include "eal_thread.h" @@ -220,3 +222,38 @@ rte_socket_id_by_idx(unsigned int idx) } return config->numa_nodes[idx]; } + +static rte_spinlock_t lcore_lock = RTE_SPINLOCK_INITIALIZER; + +unsigned int +eal_lcore_non_eal_allocate(void) +{ + struct rte_config *cfg = rte_eal_get_configuration(); + unsigned int lcore_id; + + rte_spinlock_lock(&lcore_lock); + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (cfg->lcore_role[lcore_id] != ROLE_OFF) + continue; + cfg->lcore_role[lcore_id] = ROLE_NON_EAL; + cfg->lcore_count++; + break; + } + if (lcore_id == RTE_MAX_LCORE) + RTE_LOG(DEBUG, EAL, "No lcore available.\n"); + rte_spinlock_unlock(&lcore_lock); + return lcore_id; +} + +void +eal_lcore_non_eal_release(unsigned int lcore_id) +{ + struct rte_config *cfg = rte_eal_get_configuration(); + + rte_spinlock_lock(&lcore_lock); + if (cfg->lcore_role[lcore_id] == ROLE_NON_EAL) { + cfg->lcore_role[lcore_id] = ROLE_OFF; + cfg->lcore_count--; + } + rte_spinlock_unlock(&lcore_lock); +} diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c index c649789a52..10142683f8 100644 --- a/lib/librte_eal/common/eal_common_proc.c +++ b/lib/librte_eal/common/eal_common_proc.c @@ -29,6 +29,7 @@ #include #include +#include "eal_memcfg.h" #include "eal_private.h" #include "eal_filesystem.h" #include "eal_internal_cfg.h" @@ -1232,3 +1233,44 @@ rte_mp_reply(struct rte_mp_msg *msg, const char *peer) return mp_send(msg, peer, MP_REP); } + +/* Internally, the status of the mp feature is represented as a three-state: + * - "unknown" as long as no secondary process attached to a primary process + * and there was no call to eal_disable_multiprocess yet, + * - "enabled" as soon as a secondary process attaches to a primary process, + * - "disabled" when a primary process successfully called + * eal_disable_multiprocess, + */ +enum mp_status { + MP_STATUS_UNKNOWN, + MP_STATUS_DISABLED, + MP_STATUS_ENABLED, +}; + +static bool +set_mp_status(enum mp_status status) +{ + struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; + uint8_t expected; + uint8_t desired; + + expected = MP_STATUS_UNKNOWN; + desired = status; + if (__atomic_compare_exchange_n(&mcfg->mp_status, &expected, desired, + false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) + return true; + + return __atomic_load_n(&mcfg->mp_status, __ATOMIC_RELAXED) == desired; +} + +bool +eal_disable_multiprocess(void) +{ + return set_mp_status(MP_STATUS_DISABLED); +} + +bool +eal_enable_multiprocess(void) +{ + return set_mp_status(MP_STATUS_ENABLED); +} diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c index b1b69ea58c..cead8ea5cf 100644 --- a/lib/librte_eal/common/eal_common_thread.c +++ b/lib/librte_eal/common/eal_common_thread.c @@ -12,9 +12,10 @@ #include #include +#include #include -#include #include +#include #include #include "eal_internal_cfg.h" @@ -241,3 +242,49 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name, pthread_join(*thread, NULL); return -ret; } + +int +rte_thread_register(void) +{ + unsigned int lcore_id; + rte_cpuset_t cpuset; + + /* EAL init flushes all lcores, we can't register before. */ + if (eal_get_internal_configuration()->init_complete != 1) { + RTE_LOG(DEBUG, EAL, "Called %s before EAL init.\n", __func__); + rte_errno = EINVAL; + return -1; + } + if (!eal_disable_multiprocess()) { + RTE_LOG(ERR, EAL, "Multiprocess in use, registering non-EAL threads is not supported.\n"); + rte_errno = EINVAL; + return -1; + } + if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset), + &cpuset) != 0) + CPU_ZERO(&cpuset); + lcore_id = eal_lcore_non_eal_allocate(); + if (lcore_id >= RTE_MAX_LCORE) + lcore_id = LCORE_ID_ANY; + __rte_thread_init(lcore_id, &cpuset); + if (lcore_id == LCORE_ID_ANY) { + rte_errno = ENOMEM; + return -1; + } + RTE_LOG(DEBUG, EAL, "Registered non-EAL thread as lcore %u.\n", + lcore_id); + return 0; +} + +void +rte_thread_unregister(void) +{ + unsigned int lcore_id = rte_lcore_id(); + + if (lcore_id != LCORE_ID_ANY) + eal_lcore_non_eal_release(lcore_id); + __rte_thread_uninit(); + if (lcore_id != LCORE_ID_ANY) + RTE_LOG(DEBUG, EAL, "Unregistered non-EAL thread (was lcore %u).\n", + lcore_id); +} diff --git a/lib/librte_eal/common/eal_memcfg.h b/lib/librte_eal/common/eal_memcfg.h index 583fcb5953..ea013a9daf 100644 --- a/lib/librte_eal/common/eal_memcfg.h +++ b/lib/librte_eal/common/eal_memcfg.h @@ -41,6 +41,8 @@ struct rte_mem_config { rte_rwlock_t memory_hotplug_lock; /**< Indicates whether memory hotplug request is in progress. */ + uint8_t mp_status; /**< Multiprocess status. */ + /* memory segments and zones */ struct rte_fbarray memzones; /**< Memzone descriptors. */ diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index a77ac7a963..e82fb80aa0 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -396,6 +396,24 @@ uint64_t get_tsc_freq(void); */ uint64_t get_tsc_freq_arch(void); +/** + * Allocate a free lcore to associate to a non-EAL thread. + * + * @return + * - the id of a lcore with role ROLE_NON_EAL on success. + * - RTE_MAX_LCORE if none was available. + */ +unsigned int eal_lcore_non_eal_allocate(void); + +/** + * Release the lcore used by a non-EAL thread. + * Counterpart of eal_lcore_non_eal_allocate(). + * + * @param lcore_id + * The lcore with role ROLE_NON_EAL to release. + */ +void eal_lcore_non_eal_release(unsigned int lcore_id); + /** * Prepare physical memory mapping * i.e. hugepages on Linux and @@ -714,4 +732,14 @@ void __rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset); */ void __rte_thread_uninit(void); +/** + * Mark primary process as not supporting multi-process. + */ +bool eal_disable_multiprocess(void); + +/** + * Instruct primary process that a secondary process wants to attach. + */ +bool eal_enable_multiprocess(void); + #endif /* _EAL_PRIVATE_H_ */ diff --git a/lib/librte_eal/freebsd/eal.c b/lib/librte_eal/freebsd/eal.c index fd577daf44..7e5001a864 100644 --- a/lib/librte_eal/freebsd/eal.c +++ b/lib/librte_eal/freebsd/eal.c @@ -400,6 +400,10 @@ rte_config_init(void) } if (rte_eal_config_reattach() < 0) return -1; + if (!eal_enable_multiprocess()) { + RTE_LOG(ERR, EAL, "Primary process refused secondary attachment\n"); + return -1; + } eal_mcfg_update_internal(); break; case RTE_PROC_AUTO: diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h index 3968c40693..2fd1a03275 100644 --- a/lib/librte_eal/include/rte_lcore.h +++ b/lib/librte_eal/include/rte_lcore.h @@ -31,6 +31,7 @@ enum rte_lcore_role_t { ROLE_RTE, ROLE_OFF, ROLE_SERVICE, + ROLE_NON_EAL, }; /** @@ -67,7 +68,8 @@ rte_lcore_has_role(unsigned int lcore_id, enum rte_lcore_role_t role); * to run threads with lcore IDs 0, 1, 2 and 3 on physical core 10.. * * @return - * Logical core ID (in EAL thread) or LCORE_ID_ANY (in non-EAL thread) + * Logical core ID (in EAL thread or registered non-EAL thread) or + * LCORE_ID_ANY (in unregistered non-EAL thread) */ static inline unsigned rte_lcore_id(void) @@ -279,6 +281,30 @@ int rte_thread_setname(pthread_t id, const char *name); __rte_experimental int rte_thread_getname(pthread_t id, char *name, size_t len); +/** + * Register current non-EAL thread as a lcore. + * + * @note This API is not compatible with the multi-process feature: + * - if a primary process registers a non-EAL thread, then no secondary process + * will initialise. + * - if a secondary process initialises successfully, trying to register a + * non-EAL thread from either primary or secondary processes will always end + * up with the thread getting LCORE_ID_ANY as lcore. + * + * @return + * On success, return 0; otherwise return -1 with rte_errno set. + */ +__rte_experimental +int +rte_thread_register(void); + +/** + * Unregister current thread and release lcore if one was associated. + */ +__rte_experimental +void +rte_thread_unregister(void); + /** * Create a control thread. * diff --git a/lib/librte_eal/linux/eal.c b/lib/librte_eal/linux/eal.c index bd089cdd44..f4daf46c4e 100644 --- a/lib/librte_eal/linux/eal.c +++ b/lib/librte_eal/linux/eal.c @@ -492,6 +492,10 @@ rte_config_init(void) } if (rte_eal_config_reattach() < 0) return -1; + if (!eal_enable_multiprocess()) { + RTE_LOG(ERR, EAL, "Primary process refused secondary attachment\n"); + return -1; + } eal_mcfg_update_internal(); break; case RTE_PROC_AUTO: diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map index 0d42d44ce9..5503dd7620 100644 --- a/lib/librte_eal/rte_eal_version.map +++ b/lib/librte_eal/rte_eal_version.map @@ -393,6 +393,10 @@ EXPERIMENTAL { rte_trace_point_lookup; rte_trace_regexp; rte_trace_save; + + # added in 20.08 + rte_thread_register; + rte_thread_unregister; }; INTERNAL { diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c index addac62ae5..9fc831fe6f 100644 --- a/lib/librte_eal/windows/eal.c +++ b/lib/librte_eal/windows/eal.c @@ -66,6 +66,12 @@ eal_proc_type_detect(void) return ptype; } +bool +eal_disable_multiprocess(void) +{ + return true; +} + /* display usage */ static void eal_usage(const char *prgname) diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h index 652d19f9f1..9e0ee052b3 100644 --- a/lib/librte_mempool/rte_mempool.h +++ b/lib/librte_mempool/rte_mempool.h @@ -28,9 +28,9 @@ * rte_mempool_get() or rte_mempool_put() are designed to be called from an EAL * thread due to the internal per-lcore cache. Due to the lack of caching, * rte_mempool_get() or rte_mempool_put() performance will suffer when called - * by non-EAL threads. Instead, non-EAL threads should call - * rte_mempool_generic_get() or rte_mempool_generic_put() with a user cache - * created with rte_mempool_cache_create(). + * by unregistered non-EAL threads. Instead, unregistered non-EAL threads + * should call rte_mempool_generic_get() or rte_mempool_generic_put() with a + * user cache created with rte_mempool_cache_create(). */ #include @@ -1233,7 +1233,7 @@ void rte_mempool_dump(FILE *f, struct rte_mempool *mp); /** * Create a user-owned mempool cache. * - * This can be used by non-EAL threads to enable caching when they + * This can be used by unregistered non-EAL threads to enable caching when they * interact with a mempool. * * @param size @@ -1264,7 +1264,8 @@ rte_mempool_cache_free(struct rte_mempool_cache *cache); * @param lcore_id * The logical core id. * @return - * A pointer to the mempool cache or NULL if disabled or non-EAL thread. + * A pointer to the mempool cache or NULL if disabled or unregistered non-EAL + * thread. */ static __rte_always_inline struct rte_mempool_cache * rte_mempool_default_cache(struct rte_mempool *mp, unsigned lcore_id) From patchwork Mon Jul 6 20:52:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 73346 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8D229A00C5; Mon, 6 Jul 2020 22:54:05 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 5064C1DDDB; Mon, 6 Jul 2020 22:53:32 +0200 (CEST) Received: from us-smtp-delivery-1.mimecast.com (us-smtp-2.mimecast.com [207.211.31.81]) by dpdk.org (Postfix) with ESMTP id B92181DDD3 for ; Mon, 6 Jul 2020 22:53:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594068810; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FMrx449Dp+quLDBDMJF8y8dcyqGH2sxdRWZlr/F+WV0=; b=FTiNu3vH/jm9M6m5zQSGYhP9202pyOi+ftGpsYZTYJVJ6QmR3xthtGbBZbITZIqKjjdL3C AFg56l8LVAjpqL9HcBoT7DXsL14uNopgl7DN1Tq+LKFJ+uz9Xg4Ipb0ybp+9ucJYqkrNsP mBwtZewGQF4DaW3X3SYzwsRBMOXV3a0= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-23-ELdl3-PyOSmmDV87xG-JWw-1; Mon, 06 Jul 2020 16:53:28 -0400 X-MC-Unique: ELdl3-PyOSmmDV87xG-JWw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2099F8014D4; Mon, 6 Jul 2020 20:53:26 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.195.188]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1BEEC10013D7; Mon, 6 Jul 2020 20:53:21 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: jerinjacobk@gmail.com, bruce.richardson@intel.com, mdr@ashroe.eu, thomas@monjalon.net, arybchenko@solarflare.com, ktraynor@redhat.com, ian.stokes@intel.com, i.maximets@ovn.org, olivier.matz@6wind.com, konstantin.ananyev@intel.com, Neil Horman Date: Mon, 6 Jul 2020 22:52:31 +0200 Message-Id: <20200706205234.8040-8-david.marchand@redhat.com> In-Reply-To: <20200706205234.8040-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> <20200706205234.8040-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [dpdk-dev] [PATCH v6 07/10] eal: add lcore init callbacks X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" DPDK components and applications can have their say when a new lcore is initialized. For this, they can register a callback for initializing and releasing their private data. Signed-off-by: David Marchand --- Changes since v4: - fixed leak on callback register failure, - fixed nits from Konstantin and Olivier, - prefixed unit tests logs with Error: when applicable, Changes since v2: - added missing test, - fixed rollback on lcore register, Changes since v1: - added unit test (since missing some coverage, for v3), - preferred callback and removed mention of notification, --- app/test/test_lcores.c | 227 +++++++++++++++++++++++ lib/librte_eal/common/eal_common_lcore.c | 146 ++++++++++++++- lib/librte_eal/common/eal_private.h | 3 +- lib/librte_eal/include/rte_lcore.h | 70 +++++++ lib/librte_eal/rte_eal_version.map | 2 + 5 files changed, 442 insertions(+), 6 deletions(-) diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c index afb9cdd444..7df827b4e8 100644 --- a/app/test/test_lcores.c +++ b/app/test/test_lcores.c @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -117,6 +118,226 @@ test_non_eal_lcores(unsigned int eal_threads_count) return ret; } +struct limit_lcore_context { + unsigned int init; + unsigned int max; + unsigned int uninit; +}; + +static int +limit_lcores_init(unsigned int lcore_id __rte_unused, void *arg) +{ + struct limit_lcore_context *l = arg; + + l->init++; + if (l->init > l->max) + return -1; + return 0; +} + +static void +limit_lcores_uninit(unsigned int lcore_id __rte_unused, void *arg) +{ + struct limit_lcore_context *l = arg; + + l->uninit++; +} + +static int +test_lcores_callback(unsigned int eal_threads_count) +{ + struct limit_lcore_context l; + void *handle; + + /* Refuse last lcore => callback register error. */ + memset(&l, 0, sizeof(l)); + l.max = eal_threads_count - 1; + handle = rte_lcore_callback_register("limit", limit_lcores_init, + limit_lcores_uninit, &l); + if (handle != NULL) { + printf("Error: lcore callback register should have failed\n"); + goto error; + } + /* Refusal happens at the n th call to the init callback. + * Besides, n - 1 were accepted, so we expect as many uninit calls when + * the rollback happens. + */ + if (l.init != eal_threads_count) { + printf("Error: lcore callback register failed but incorrect init calls, expected %u, got %u\n", + eal_threads_count, l.init); + goto error; + } + if (l.uninit != eal_threads_count - 1) { + printf("Error: lcore callback register failed but incorrect uninit calls, expected %u, got %u\n", + eal_threads_count - 1, l.uninit); + goto error; + } + + /* Accept all lcore and unregister. */ + memset(&l, 0, sizeof(l)); + l.max = eal_threads_count; + handle = rte_lcore_callback_register("limit", limit_lcores_init, + limit_lcores_uninit, &l); + if (handle == NULL) { + printf("Error: lcore callback register failed\n"); + goto error; + } + if (l.uninit != 0) { + printf("Error: lcore callback register succeeded but incorrect uninit calls, expected 0, got %u\n", + l.uninit); + goto error; + } + rte_lcore_callback_unregister(handle); + handle = NULL; + if (l.init != eal_threads_count) { + printf("Error: lcore callback unregister done but incorrect init calls, expected %u, got %u\n", + eal_threads_count, l.init); + goto error; + } + if (l.uninit != eal_threads_count) { + printf("Error: lcore callback unregister done but incorrect uninit calls, expected %u, got %u\n", + eal_threads_count, l.uninit); + goto error; + } + + return 0; + +error: + if (handle != NULL) + rte_lcore_callback_unregister(handle); + + return -1; +} + +static int +test_non_eal_lcores_callback(unsigned int eal_threads_count) +{ + struct thread_context thread_contexts[2]; + unsigned int non_eal_threads_count = 0; + struct limit_lcore_context l[2] = {}; + unsigned int registered_count = 0; + struct thread_context *t; + void *handle[2] = {}; + unsigned int i; + int ret; + + /* This test requires two empty slots to be sure lcore init refusal is + * because of callback execution. + */ + if (eal_threads_count + 2 >= RTE_MAX_LCORE) + return 0; + + /* Register two callbacks: + * - first one accepts any lcore, + * - second one accepts all EAL lcore + one more for the first non-EAL + * thread, then refuses the next lcore. + */ + l[0].max = UINT_MAX; + handle[0] = rte_lcore_callback_register("no_limit", limit_lcores_init, + limit_lcores_uninit, &l[0]); + if (handle[0] == NULL) { + printf("Error: lcore callback [0] register failed\n"); + goto error; + } + l[1].max = eal_threads_count + 1; + handle[1] = rte_lcore_callback_register("limit", limit_lcores_init, + limit_lcores_uninit, &l[1]); + if (handle[1] == NULL) { + printf("Error: lcore callback [1] register failed\n"); + goto error; + } + if (l[0].init != eal_threads_count || l[1].init != eal_threads_count) { + printf("Error: lcore callbacks register succeeded but incorrect init calls, expected %u, %u, got %u, %u\n", + eal_threads_count, eal_threads_count, + l[0].init, l[1].init); + goto error; + } + if (l[0].uninit != 0 || l[1].uninit != 0) { + printf("Error: lcore callbacks register succeeded but incorrect uninit calls, expected 0, 1, got %u, %u\n", + l[0].uninit, l[1].uninit); + goto error; + } + /* First thread that expects a valid lcore id. */ + t = &thread_contexts[0]; + t->state = INIT; + t->registered_count = ®istered_count; + t->lcore_id_any = false; + if (pthread_create(&t->id, NULL, thread_loop, t) != 0) + goto cleanup_threads; + non_eal_threads_count++; + while (__atomic_load_n(®istered_count, __ATOMIC_ACQUIRE) != + non_eal_threads_count) + ; + if (l[0].init != eal_threads_count + 1 || + l[1].init != eal_threads_count + 1) { + printf("Error: incorrect init calls, expected %u, %u, got %u, %u\n", + eal_threads_count + 1, eal_threads_count + 1, + l[0].init, l[1].init); + goto cleanup_threads; + } + if (l[0].uninit != 0 || l[1].uninit != 0) { + printf("Error: incorrect uninit calls, expected 0, 0, got %u, %u\n", + l[0].uninit, l[1].uninit); + goto cleanup_threads; + } + /* Second thread, that expects LCORE_ID_ANY because of init refusal. */ + t = &thread_contexts[1]; + t->state = INIT; + t->registered_count = ®istered_count; + t->lcore_id_any = true; + if (pthread_create(&t->id, NULL, thread_loop, t) != 0) + goto cleanup_threads; + non_eal_threads_count++; + while (__atomic_load_n(®istered_count, __ATOMIC_ACQUIRE) != + non_eal_threads_count) + ; + if (l[0].init != eal_threads_count + 2 || + l[1].init != eal_threads_count + 2) { + printf("Error: incorrect init calls, expected %u, %u, got %u, %u\n", + eal_threads_count + 2, eal_threads_count + 2, + l[0].init, l[1].init); + goto cleanup_threads; + } + if (l[0].uninit != 1 || l[1].uninit != 0) { + printf("Error: incorrect uninit calls, expected 1, 0, got %u, %u\n", + l[0].uninit, l[1].uninit); + goto cleanup_threads; + } + /* Release all threads, and check their states. */ + __atomic_store_n(®istered_count, 0, __ATOMIC_RELEASE); + ret = 0; + for (i = 0; i < non_eal_threads_count; i++) { + t = &thread_contexts[i]; + pthread_join(t->id, NULL); + if (t->state != DONE) + ret = -1; + } + if (ret < 0) + goto error; + if (l[0].uninit != 2 || l[1].uninit != 1) { + printf("Error: threads reported having successfully registered and unregistered, but incorrect uninit calls, expected 2, 1, got %u, %u\n", + l[0].uninit, l[1].uninit); + goto error; + } + rte_lcore_callback_unregister(handle[0]); + rte_lcore_callback_unregister(handle[1]); + return 0; + +cleanup_threads: + /* Release all threads */ + __atomic_store_n(®istered_count, 0, __ATOMIC_RELEASE); + for (i = 0; i < non_eal_threads_count; i++) { + t = &thread_contexts[i]; + pthread_join(t->id, NULL); + } +error: + if (handle[1] != NULL) + rte_lcore_callback_unregister(handle[1]); + if (handle[0] != NULL) + rte_lcore_callback_unregister(handle[0]); + return -1; +} + static int test_lcores(void) { @@ -137,6 +358,12 @@ test_lcores(void) if (test_non_eal_lcores(eal_threads_count) < 0) return TEST_FAILED; + if (test_lcores_callback(eal_threads_count) < 0) + return TEST_FAILED; + + if (test_non_eal_lcores_callback(eal_threads_count) < 0) + return TEST_FAILED; + return TEST_SUCCESS; } diff --git a/lib/librte_eal/common/eal_common_lcore.c b/lib/librte_eal/common/eal_common_lcore.c index 2b7d262372..90139c77ff 100644 --- a/lib/librte_eal/common/eal_common_lcore.c +++ b/lib/librte_eal/common/eal_common_lcore.c @@ -224,11 +224,122 @@ rte_socket_id_by_idx(unsigned int idx) } static rte_spinlock_t lcore_lock = RTE_SPINLOCK_INITIALIZER; +struct lcore_callback { + TAILQ_ENTRY(lcore_callback) next; + char *name; + rte_lcore_init_cb init; + rte_lcore_uninit_cb uninit; + void *arg; +}; +static TAILQ_HEAD(lcore_callbacks_head, lcore_callback) lcore_callbacks = + TAILQ_HEAD_INITIALIZER(lcore_callbacks); + +static int +callback_init(struct lcore_callback *callback, unsigned int lcore_id) +{ + if (callback->init == NULL) + return 0; + RTE_LOG(DEBUG, EAL, "Call init for lcore callback %s, lcore_id %u\n", + callback->name, lcore_id); + return callback->init(lcore_id, callback->arg); +} + +static void +callback_uninit(struct lcore_callback *callback, unsigned int lcore_id) +{ + if (callback->uninit == NULL) + return; + RTE_LOG(DEBUG, EAL, "Call uninit for lcore callback %s, lcore_id %u\n", + callback->name, lcore_id); + callback->uninit(lcore_id, callback->arg); +} + +static void +free_callback(struct lcore_callback *callback) +{ + free(callback->name); + free(callback); +} + +void * +rte_lcore_callback_register(const char *name, rte_lcore_init_cb init, + rte_lcore_uninit_cb uninit, void *arg) +{ + struct rte_config *cfg = rte_eal_get_configuration(); + struct lcore_callback *callback; + unsigned int lcore_id; + + if (name == NULL) + return NULL; + callback = calloc(1, sizeof(*callback)); + if (callback == NULL) + return NULL; + if (asprintf(&callback->name, "%s-%p", name, arg) == -1) { + free(callback); + return NULL; + } + callback->init = init; + callback->uninit = uninit; + callback->arg = arg; + rte_spinlock_lock(&lcore_lock); + if (callback->init == NULL) + goto no_init; + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (cfg->lcore_role[lcore_id] == ROLE_OFF) + continue; + if (callback_init(callback, lcore_id) == 0) + continue; + /* Callback refused init for this lcore, uninitialize all + * previous lcore. + */ + while (lcore_id-- != 0) { + if (cfg->lcore_role[lcore_id] == ROLE_OFF) + continue; + callback_uninit(callback, lcore_id); + } + free_callback(callback); + callback = NULL; + goto out; + } +no_init: + TAILQ_INSERT_TAIL(&lcore_callbacks, callback, next); + RTE_LOG(DEBUG, EAL, "Registered new lcore callback %s (%sinit, %suninit).\n", + callback->name, callback->init == NULL ? "NO " : "", + callback->uninit == NULL ? "NO " : ""); +out: + rte_spinlock_unlock(&lcore_lock); + return callback; +} + +void +rte_lcore_callback_unregister(void *handle) +{ + struct rte_config *cfg = rte_eal_get_configuration(); + struct lcore_callback *callback = handle; + unsigned int lcore_id; + + rte_spinlock_lock(&lcore_lock); + if (callback->uninit == NULL) + goto no_uninit; + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (cfg->lcore_role[lcore_id] == ROLE_OFF) + continue; + callback_uninit(callback, lcore_id); + } +no_uninit: + TAILQ_REMOVE(&lcore_callbacks, callback, next); + rte_spinlock_unlock(&lcore_lock); + RTE_LOG(DEBUG, EAL, "Unregistered lcore callback %s-%p.\n", + callback->name, callback->arg); + free_callback(callback); +} unsigned int eal_lcore_non_eal_allocate(void) { struct rte_config *cfg = rte_eal_get_configuration(); + struct lcore_callback *callback; + struct lcore_callback *prev; unsigned int lcore_id; rte_spinlock_lock(&lcore_lock); @@ -239,8 +350,29 @@ eal_lcore_non_eal_allocate(void) cfg->lcore_count++; break; } - if (lcore_id == RTE_MAX_LCORE) + if (lcore_id == RTE_MAX_LCORE) { RTE_LOG(DEBUG, EAL, "No lcore available.\n"); + goto out; + } + TAILQ_FOREACH(callback, &lcore_callbacks, next) { + if (callback_init(callback, lcore_id) == 0) + continue; + /* Callback refused init for this lcore, call uninit for all + * previous callbacks. + */ + prev = TAILQ_PREV(callback, lcore_callbacks_head, next); + while (prev != NULL) { + callback_uninit(prev, lcore_id); + prev = TAILQ_PREV(prev, lcore_callbacks_head, next); + } + RTE_LOG(DEBUG, EAL, "Initialization refused for lcore %u.\n", + lcore_id); + cfg->lcore_role[lcore_id] = ROLE_OFF; + cfg->lcore_count--; + lcore_id = RTE_MAX_LCORE; + goto out; + } +out: rte_spinlock_unlock(&lcore_lock); return lcore_id; } @@ -249,11 +381,15 @@ void eal_lcore_non_eal_release(unsigned int lcore_id) { struct rte_config *cfg = rte_eal_get_configuration(); + struct lcore_callback *callback; rte_spinlock_lock(&lcore_lock); - if (cfg->lcore_role[lcore_id] == ROLE_NON_EAL) { - cfg->lcore_role[lcore_id] = ROLE_OFF; - cfg->lcore_count--; - } + if (cfg->lcore_role[lcore_id] != ROLE_NON_EAL) + goto out; + TAILQ_FOREACH(callback, &lcore_callbacks, next) + callback_uninit(callback, lcore_id); + cfg->lcore_role[lcore_id] = ROLE_OFF; + cfg->lcore_count--; +out: rte_spinlock_unlock(&lcore_lock); } diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index e82fb80aa0..535e008474 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -401,7 +401,8 @@ uint64_t get_tsc_freq_arch(void); * * @return * - the id of a lcore with role ROLE_NON_EAL on success. - * - RTE_MAX_LCORE if none was available. + * - RTE_MAX_LCORE if none was available or initializing was refused (see + * rte_lcore_callback_register). */ unsigned int eal_lcore_non_eal_allocate(void); diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h index 2fd1a03275..6e7206c79f 100644 --- a/lib/librte_eal/include/rte_lcore.h +++ b/lib/librte_eal/include/rte_lcore.h @@ -229,6 +229,76 @@ unsigned int rte_get_next_lcore(unsigned int i, int skip_master, int wrap); i X-Patchwork-Id: 73347 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id E6906A00C5; Mon, 6 Jul 2020 22:54:13 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id C28911DDE0; Mon, 6 Jul 2020 22:53:38 +0200 (CEST) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by dpdk.org (Postfix) with ESMTP id 5D0691DDC9 for ; Mon, 6 Jul 2020 22:53:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594068816; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lP/RlyO0gO14dK15+pFMq13vKAYGtDwpOmN5W2Dopxc=; b=ap4Twm/LnpNY6EWJlEodnaQNt8tgrXkq9F0/9ShtQAVM9EIc6+lIXqTOmYMDVi5ugctmsZ uqfC2iMxbl13L/cfl/tEzjloLg5+tsuk4LzVUojVwLKKsrsohY9W/L+oLYdbjZvggOu+Uf WsuduMlpdC7DdUPEU5torI1mzGMROqM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-244-kEaT6eYBMiaahPznRIzMMQ-1; Mon, 06 Jul 2020 16:53:33 -0400 X-MC-Unique: kEaT6eYBMiaahPznRIzMMQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6FEA380040C; Mon, 6 Jul 2020 20:53:31 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.195.188]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9C57B10013D7; Mon, 6 Jul 2020 20:53:26 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: jerinjacobk@gmail.com, bruce.richardson@intel.com, mdr@ashroe.eu, thomas@monjalon.net, arybchenko@solarflare.com, ktraynor@redhat.com, ian.stokes@intel.com, i.maximets@ovn.org, olivier.matz@6wind.com, konstantin.ananyev@intel.com, Neil Horman Date: Mon, 6 Jul 2020 22:52:32 +0200 Message-Id: <20200706205234.8040-9-david.marchand@redhat.com> In-Reply-To: <20200706205234.8040-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> <20200706205234.8040-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [dpdk-dev] [PATCH v6 08/10] eal: add lcore iterators X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add a helper to iterate all lcores. The iterator callback is read-only wrt the lcores list. Implement a dump function on top of this for debugging. Signed-off-by: David Marchand Reviewed-by: Olivier Matz --- Changes since v2: - added rte_lcore_dump calls in unit test, for basic check, Changes since v1: - introduced lcore iterators and implemented rte_lcore_dump, this iterator mechanism can then be used outside of EAL, --- app/test/test_lcores.c | 3 + lib/librte_eal/common/eal_common_lcore.c | 77 ++++++++++++++++++++--- lib/librte_eal/common/eal_common_thread.c | 16 +++-- lib/librte_eal/common/eal_thread.h | 13 +++- lib/librte_eal/freebsd/eal.c | 2 +- lib/librte_eal/freebsd/eal_thread.c | 2 +- lib/librte_eal/include/rte_lcore.h | 47 +++++++++++++- lib/librte_eal/linux/eal.c | 2 +- lib/librte_eal/linux/eal_thread.c | 2 +- lib/librte_eal/rte_eal_version.map | 2 + 10 files changed, 143 insertions(+), 23 deletions(-) diff --git a/app/test/test_lcores.c b/app/test/test_lcores.c index 7df827b4e8..19a7ab9fce 100644 --- a/app/test/test_lcores.c +++ b/app/test/test_lcores.c @@ -303,6 +303,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count) l[0].uninit, l[1].uninit); goto cleanup_threads; } + rte_lcore_dump(stdout); /* Release all threads, and check their states. */ __atomic_store_n(®istered_count, 0, __ATOMIC_RELEASE); ret = 0; @@ -314,6 +315,7 @@ test_non_eal_lcores_callback(unsigned int eal_threads_count) } if (ret < 0) goto error; + rte_lcore_dump(stdout); if (l[0].uninit != 2 || l[1].uninit != 1) { printf("Error: threads reported having successfully registered and unregistered, but incorrect uninit calls, expected 2, 1, got %u, %u\n", l[0].uninit, l[1].uninit); @@ -354,6 +356,7 @@ test_lcores(void) } printf("EAL threads count: %u, RTE_MAX_LCORE=%u\n", eal_threads_count, RTE_MAX_LCORE); + rte_lcore_dump(stdout); if (test_non_eal_lcores(eal_threads_count) < 0) return TEST_FAILED; diff --git a/lib/librte_eal/common/eal_common_lcore.c b/lib/librte_eal/common/eal_common_lcore.c index 90139c77ff..f2bd30c70a 100644 --- a/lib/librte_eal/common/eal_common_lcore.c +++ b/lib/librte_eal/common/eal_common_lcore.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include "eal_memcfg.h" #include "eal_private.h" @@ -223,7 +223,7 @@ rte_socket_id_by_idx(unsigned int idx) return config->numa_nodes[idx]; } -static rte_spinlock_t lcore_lock = RTE_SPINLOCK_INITIALIZER; +static rte_rwlock_t lcore_lock = RTE_RWLOCK_INITIALIZER; struct lcore_callback { TAILQ_ENTRY(lcore_callback) next; char *name; @@ -281,7 +281,7 @@ rte_lcore_callback_register(const char *name, rte_lcore_init_cb init, callback->init = init; callback->uninit = uninit; callback->arg = arg; - rte_spinlock_lock(&lcore_lock); + rte_rwlock_write_lock(&lcore_lock); if (callback->init == NULL) goto no_init; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { @@ -307,7 +307,7 @@ rte_lcore_callback_register(const char *name, rte_lcore_init_cb init, callback->name, callback->init == NULL ? "NO " : "", callback->uninit == NULL ? "NO " : ""); out: - rte_spinlock_unlock(&lcore_lock); + rte_rwlock_write_unlock(&lcore_lock); return callback; } @@ -318,7 +318,7 @@ rte_lcore_callback_unregister(void *handle) struct lcore_callback *callback = handle; unsigned int lcore_id; - rte_spinlock_lock(&lcore_lock); + rte_rwlock_write_lock(&lcore_lock); if (callback->uninit == NULL) goto no_uninit; for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { @@ -328,7 +328,7 @@ rte_lcore_callback_unregister(void *handle) } no_uninit: TAILQ_REMOVE(&lcore_callbacks, callback, next); - rte_spinlock_unlock(&lcore_lock); + rte_rwlock_write_unlock(&lcore_lock); RTE_LOG(DEBUG, EAL, "Unregistered lcore callback %s-%p.\n", callback->name, callback->arg); free_callback(callback); @@ -342,7 +342,7 @@ eal_lcore_non_eal_allocate(void) struct lcore_callback *prev; unsigned int lcore_id; - rte_spinlock_lock(&lcore_lock); + rte_rwlock_write_lock(&lcore_lock); for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { if (cfg->lcore_role[lcore_id] != ROLE_OFF) continue; @@ -373,7 +373,7 @@ eal_lcore_non_eal_allocate(void) goto out; } out: - rte_spinlock_unlock(&lcore_lock); + rte_rwlock_write_unlock(&lcore_lock); return lcore_id; } @@ -383,7 +383,7 @@ eal_lcore_non_eal_release(unsigned int lcore_id) struct rte_config *cfg = rte_eal_get_configuration(); struct lcore_callback *callback; - rte_spinlock_lock(&lcore_lock); + rte_rwlock_write_lock(&lcore_lock); if (cfg->lcore_role[lcore_id] != ROLE_NON_EAL) goto out; TAILQ_FOREACH(callback, &lcore_callbacks, next) @@ -391,5 +391,62 @@ eal_lcore_non_eal_release(unsigned int lcore_id) cfg->lcore_role[lcore_id] = ROLE_OFF; cfg->lcore_count--; out: - rte_spinlock_unlock(&lcore_lock); + rte_rwlock_write_unlock(&lcore_lock); +} + +int +rte_lcore_iterate(rte_lcore_iterate_cb cb, void *arg) +{ + struct rte_config *cfg = rte_eal_get_configuration(); + unsigned int lcore_id; + int ret = 0; + + rte_rwlock_read_lock(&lcore_lock); + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (cfg->lcore_role[lcore_id] == ROLE_OFF) + continue; + ret = cb(lcore_id, arg); + if (ret != 0) + break; + } + rte_rwlock_read_unlock(&lcore_lock); + return ret; +} + +static int +lcore_dump_cb(unsigned int lcore_id, void *arg) +{ + struct rte_config *cfg = rte_eal_get_configuration(); + char cpuset[RTE_CPU_AFFINITY_STR_LEN]; + const char *role; + FILE *f = arg; + int ret; + + switch (cfg->lcore_role[lcore_id]) { + case ROLE_RTE: + role = "RTE"; + break; + case ROLE_SERVICE: + role = "SERVICE"; + break; + case ROLE_NON_EAL: + role = "NON_EAL"; + break; + default: + role = "UNKNOWN"; + break; + } + + ret = eal_thread_dump_affinity(&lcore_config[lcore_id].cpuset, cpuset, + sizeof(cpuset)); + fprintf(f, "lcore %u, socket %u, role %s, cpuset %s%s\n", lcore_id, + rte_lcore_to_socket_id(lcore_id), role, cpuset, + ret == 0 ? "" : "..."); + return 0; +} + +void +rte_lcore_dump(FILE *f) +{ + rte_lcore_iterate(lcore_dump_cb, f); } diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c index cead8ea5cf..ea09a4f3e0 100644 --- a/lib/librte_eal/common/eal_common_thread.c +++ b/lib/librte_eal/common/eal_common_thread.c @@ -105,17 +105,14 @@ rte_thread_get_affinity(rte_cpuset_t *cpusetp) } int -eal_thread_dump_affinity(char *str, unsigned size) +eal_thread_dump_affinity(rte_cpuset_t *cpuset, char *str, unsigned int size) { - rte_cpuset_t cpuset; unsigned cpu; int ret; unsigned int out = 0; - rte_thread_get_affinity(&cpuset); - for (cpu = 0; cpu < CPU_SETSIZE; cpu++) { - if (!CPU_ISSET(cpu, &cpuset)) + if (!CPU_ISSET(cpu, cpuset)) continue; ret = snprintf(str + out, @@ -138,6 +135,15 @@ eal_thread_dump_affinity(char *str, unsigned size) return ret; } +int +eal_thread_dump_current_affinity(char *str, unsigned int size) +{ + rte_cpuset_t cpuset; + + rte_thread_get_affinity(&cpuset); + return eal_thread_dump_affinity(&cpuset, str, size); +} + void __rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset) { diff --git a/lib/librte_eal/common/eal_thread.h b/lib/librte_eal/common/eal_thread.h index dc1fc6eb99..4a49117be8 100644 --- a/lib/librte_eal/common/eal_thread.h +++ b/lib/librte_eal/common/eal_thread.h @@ -32,13 +32,15 @@ unsigned eal_cpu_socket_id(unsigned cpu_id); #define RTE_CPU_AFFINITY_STR_LEN 256 /** - * Dump the current pthread cpuset. + * Dump the cpuset as a human readable string. * This function is private to EAL. * * Note: * If the dump size is greater than the size of given buffer, * the string will be truncated and with '\0' at the end. * + * @param cpuset + * The CPU affinity object to dump. * @param str * The string buffer the cpuset will dump to. * @param size @@ -47,6 +49,13 @@ unsigned eal_cpu_socket_id(unsigned cpu_id); * 0 for success, -1 if truncation happens. */ int -eal_thread_dump_affinity(char *str, unsigned size); +eal_thread_dump_affinity(rte_cpuset_t *cpuset, char *str, unsigned int size); + +/** + * Dump the current thread cpuset. + * This is a wrapper on eal_thread_dump_affinity(). + */ +int +eal_thread_dump_current_affinity(char *str, unsigned int size); #endif /* EAL_THREAD_H */ diff --git a/lib/librte_eal/freebsd/eal.c b/lib/librte_eal/freebsd/eal.c index 7e5001a864..7d6f4aa09b 100644 --- a/lib/librte_eal/freebsd/eal.c +++ b/lib/librte_eal/freebsd/eal.c @@ -858,7 +858,7 @@ rte_eal_init(int argc, char **argv) __rte_thread_init(config->master_lcore, &lcore_config[config->master_lcore].cpuset); - ret = eal_thread_dump_affinity(cpuset, sizeof(cpuset)); + ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset)); RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%p;cpuset=[%s%s])\n", config->master_lcore, thread_id, cpuset, diff --git a/lib/librte_eal/freebsd/eal_thread.c b/lib/librte_eal/freebsd/eal_thread.c index 0788a54fe6..99b5fefc4c 100644 --- a/lib/librte_eal/freebsd/eal_thread.c +++ b/lib/librte_eal/freebsd/eal_thread.c @@ -92,7 +92,7 @@ eal_thread_loop(__rte_unused void *arg) __rte_thread_init(lcore_id, &lcore_config[lcore_id].cpuset); - ret = eal_thread_dump_affinity(cpuset, sizeof(cpuset)); + ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset)); RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=%p;cpuset=[%s%s])\n", lcore_id, thread_id, cpuset, ret == 0 ? "" : "..."); diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h index 6e7206c79f..b8b64a6252 100644 --- a/lib/librte_eal/include/rte_lcore.h +++ b/lib/librte_eal/include/rte_lcore.h @@ -261,8 +261,8 @@ typedef void (*rte_lcore_uninit_cb)(unsigned int lcore_id, void *arg); * If this step succeeds, the callbacks are put in the lcore callbacks list * that will get called for each lcore allocation/release. * - * Note: callbacks execution is serialised under a lock protecting the lcores - * and callbacks list. + * Note: callbacks execution is serialised under a write lock protecting the + * lcores and callbacks list. * * @param name * A name serving as a small description for this callback. @@ -299,6 +299,49 @@ __rte_experimental void rte_lcore_callback_unregister(void *handle); +/** + * Callback prototype for iterating over lcores. + * + * @param lcore_id + * The lcore to consider. + * @param arg + * An opaque pointer coming from the caller. + * @return + * - 0 lets the iteration continue. + * - !0 makes the iteration stop. + */ +typedef int (*rte_lcore_iterate_cb)(unsigned int lcore_id, void *arg); + +/** + * Iterate on all active lcores (ROLE_RTE, ROLE_SERVICE and ROLE_NON_EAL). + * No modification on the lcore states is allowed in the callback. + * + * Note: as opposed to init/uninit callbacks, iteration callbacks can be + * invoked in parallel as they are run under a read lock protecting the lcores + * and callbacks list. + * + * @param cb + * The callback that gets passed each lcore. + * @param arg + * An opaque pointer passed to cb. + * @return + * Same return code as the callback last invocation (see rte_lcore_iterate_cb + * description). + */ +__rte_experimental +int +rte_lcore_iterate(rte_lcore_iterate_cb cb, void *arg); + +/** + * List all lcores. + * + * @param f + * The output stream where the dump should be sent. + */ +__rte_experimental +void +rte_lcore_dump(FILE *f); + /** * Set core affinity of the current thread. * Support both EAL and non-EAL thread and update TLS. diff --git a/lib/librte_eal/linux/eal.c b/lib/librte_eal/linux/eal.c index f4daf46c4e..2cce19dd3d 100644 --- a/lib/librte_eal/linux/eal.c +++ b/lib/librte_eal/linux/eal.c @@ -1197,7 +1197,7 @@ rte_eal_init(int argc, char **argv) __rte_thread_init(config->master_lcore, &lcore_config[config->master_lcore].cpuset); - ret = eal_thread_dump_affinity(cpuset, sizeof(cpuset)); + ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset)); RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%zx;cpuset=[%s%s])\n", config->master_lcore, (uintptr_t)thread_id, cpuset, ret == 0 ? "" : "..."); diff --git a/lib/librte_eal/linux/eal_thread.c b/lib/librte_eal/linux/eal_thread.c index e0440c0000..48a2c1124b 100644 --- a/lib/librte_eal/linux/eal_thread.c +++ b/lib/librte_eal/linux/eal_thread.c @@ -92,7 +92,7 @@ eal_thread_loop(__rte_unused void *arg) __rte_thread_init(lcore_id, &lcore_config[lcore_id].cpuset); - ret = eal_thread_dump_affinity(cpuset, sizeof(cpuset)); + ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset)); RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=%zx;cpuset=[%s%s])\n", lcore_id, (uintptr_t)thread_id, cpuset, ret == 0 ? "" : "..."); diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map index c3e762c1d9..3aeb5b11ab 100644 --- a/lib/librte_eal/rte_eal_version.map +++ b/lib/librte_eal/rte_eal_version.map @@ -397,6 +397,8 @@ EXPERIMENTAL { # added in 20.08 rte_lcore_callback_register; rte_lcore_callback_unregister; + rte_lcore_dump; + rte_lcore_iterate; rte_thread_register; rte_thread_unregister; }; From patchwork Mon Jul 6 20:52:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 73348 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 9F242A00C5; Mon, 6 Jul 2020 22:54:24 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id F19C41DD9E; Mon, 6 Jul 2020 22:53:43 +0200 (CEST) Received: from us-smtp-delivery-1.mimecast.com (us-smtp-2.mimecast.com [205.139.110.61]) by dpdk.org (Postfix) with ESMTP id 442971DDD4 for ; Mon, 6 Jul 2020 22:53:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594068821; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=QaD8q7zrJoaFhamg+6+Jx2/vdX4GSNTeXrQek1CdV3U=; b=cy/D/6sb9a/ITgRlDbo+MjMce6DcFRl7sl3UI+TyqquVlC04tjku02sjgWgsc4eSppPg/q PhuXzuh4WVVR+iz+aRvnv5cLnbYdct92s6GT1X5ZAqb9RPe0bMSVcxTiL0x4lEs/rx2fgJ IX5eZZNnmHIMMVgpAz95u2gTe2HtOlE= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-312-CuXSzhAnPDqzUNYAPqq8ow-1; Mon, 06 Jul 2020 16:53:37 -0400 X-MC-Unique: CuXSzhAnPDqzUNYAPqq8ow-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A057019057A0; Mon, 6 Jul 2020 20:53:35 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.195.188]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3D37D10013D7; Mon, 6 Jul 2020 20:53:31 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: jerinjacobk@gmail.com, bruce.richardson@intel.com, mdr@ashroe.eu, thomas@monjalon.net, arybchenko@solarflare.com, ktraynor@redhat.com, ian.stokes@intel.com, i.maximets@ovn.org, olivier.matz@6wind.com, konstantin.ananyev@intel.com, "Artem V. Andreev" Date: Mon, 6 Jul 2020 22:52:33 +0200 Message-Id: <20200706205234.8040-10-david.marchand@redhat.com> In-Reply-To: <20200706205234.8040-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> <20200706205234.8040-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [dpdk-dev] [PATCH v6 09/10] mempool/bucket: handle non-EAL lcores X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Convert to new lcore API to support non-EAL lcores. Signed-off-by: David Marchand Reviewed-by: Andrew Rybchenko --- Changes since v3: - addressed Andrew comments, --- drivers/mempool/bucket/rte_mempool_bucket.c | 130 ++++++++++++-------- 1 file changed, 81 insertions(+), 49 deletions(-) diff --git a/drivers/mempool/bucket/rte_mempool_bucket.c b/drivers/mempool/bucket/rte_mempool_bucket.c index 5ce1ef16fb..8b9daa9782 100644 --- a/drivers/mempool/bucket/rte_mempool_bucket.c +++ b/drivers/mempool/bucket/rte_mempool_bucket.c @@ -55,6 +55,7 @@ struct bucket_data { struct rte_ring *shared_orphan_ring; struct rte_mempool *pool; unsigned int bucket_mem_size; + void *lcore_callback_handle; }; static struct bucket_stack * @@ -345,6 +346,23 @@ bucket_dequeue_contig_blocks(struct rte_mempool *mp, void **first_obj_table, return 0; } +struct bucket_count_per_lcore_ctx { + const struct bucket_data *bd; + unsigned int count; +}; + +static int +bucket_count_per_lcore(unsigned int lcore_id, void *arg) +{ + struct bucket_count_per_lcore_ctx *bplc = arg; + + bplc->count += bplc->bd->obj_per_bucket * + bplc->bd->buckets[lcore_id]->top; + bplc->count += + rte_ring_count(bplc->bd->adoption_buffer_rings[lcore_id]); + return 0; +} + static void count_underfilled_buckets(struct rte_mempool *mp, void *opaque, @@ -373,23 +391,64 @@ count_underfilled_buckets(struct rte_mempool *mp, static unsigned int bucket_get_count(const struct rte_mempool *mp) { - const struct bucket_data *bd = mp->pool_data; - unsigned int count = - bd->obj_per_bucket * rte_ring_count(bd->shared_bucket_ring) + - rte_ring_count(bd->shared_orphan_ring); - unsigned int i; + struct bucket_count_per_lcore_ctx bplc; - for (i = 0; i < RTE_MAX_LCORE; i++) { - if (!rte_lcore_is_enabled(i)) - continue; - count += bd->obj_per_bucket * bd->buckets[i]->top + - rte_ring_count(bd->adoption_buffer_rings[i]); - } + bplc.bd = mp->pool_data; + bplc.count = bplc.bd->obj_per_bucket * + rte_ring_count(bplc.bd->shared_bucket_ring); + bplc.count += rte_ring_count(bplc.bd->shared_orphan_ring); + rte_lcore_iterate(bucket_count_per_lcore, &bplc); rte_mempool_mem_iter((struct rte_mempool *)(uintptr_t)mp, - count_underfilled_buckets, &count); + count_underfilled_buckets, &bplc.count); + + return bplc.count; +} + +static int +bucket_init_per_lcore(unsigned int lcore_id, void *arg) +{ + char rg_name[RTE_RING_NAMESIZE]; + struct bucket_data *bd = arg; + struct rte_mempool *mp; + int rg_flags; + int rc; + + mp = bd->pool; + bd->buckets[lcore_id] = bucket_stack_create(mp, + mp->size / bd->obj_per_bucket); + if (bd->buckets[lcore_id] == NULL) + goto error; + + rc = snprintf(rg_name, sizeof(rg_name), RTE_MEMPOOL_MZ_FORMAT ".a%u", + mp->name, lcore_id); + if (rc < 0 || rc >= (int)sizeof(rg_name)) + goto error; + + rg_flags = RING_F_SC_DEQ; + if (mp->flags & MEMPOOL_F_SP_PUT) + rg_flags |= RING_F_SP_ENQ; + bd->adoption_buffer_rings[lcore_id] = rte_ring_create(rg_name, + rte_align32pow2(mp->size + 1), mp->socket_id, rg_flags); + if (bd->adoption_buffer_rings[lcore_id] == NULL) + goto error; - return count; + return 0; +error: + rte_free(bd->buckets[lcore_id]); + bd->buckets[lcore_id] = NULL; + return -1; +} + +static void +bucket_uninit_per_lcore(unsigned int lcore_id, void *arg) +{ + struct bucket_data *bd = arg; + + rte_ring_free(bd->adoption_buffer_rings[lcore_id]); + bd->adoption_buffer_rings[lcore_id] = NULL; + rte_free(bd->buckets[lcore_id]); + bd->buckets[lcore_id] = NULL; } static int @@ -399,7 +458,6 @@ bucket_alloc(struct rte_mempool *mp) int rc = 0; char rg_name[RTE_RING_NAMESIZE]; struct bucket_data *bd; - unsigned int i; unsigned int bucket_header_size; size_t pg_sz; @@ -429,36 +487,17 @@ bucket_alloc(struct rte_mempool *mp) /* eventually this should be a tunable parameter */ bd->bucket_stack_thresh = (mp->size / bd->obj_per_bucket) * 4 / 3; + bd->lcore_callback_handle = rte_lcore_callback_register("bucket", + bucket_init_per_lcore, bucket_uninit_per_lcore, bd); + if (bd->lcore_callback_handle == NULL) { + rc = -ENOMEM; + goto no_mem_for_stacks; + } + if (mp->flags & MEMPOOL_F_SP_PUT) rg_flags |= RING_F_SP_ENQ; if (mp->flags & MEMPOOL_F_SC_GET) rg_flags |= RING_F_SC_DEQ; - - for (i = 0; i < RTE_MAX_LCORE; i++) { - if (!rte_lcore_is_enabled(i)) - continue; - bd->buckets[i] = - bucket_stack_create(mp, mp->size / bd->obj_per_bucket); - if (bd->buckets[i] == NULL) { - rc = -ENOMEM; - goto no_mem_for_stacks; - } - rc = snprintf(rg_name, sizeof(rg_name), - RTE_MEMPOOL_MZ_FORMAT ".a%u", mp->name, i); - if (rc < 0 || rc >= (int)sizeof(rg_name)) { - rc = -ENAMETOOLONG; - goto no_mem_for_stacks; - } - bd->adoption_buffer_rings[i] = - rte_ring_create(rg_name, rte_align32pow2(mp->size + 1), - mp->socket_id, - rg_flags | RING_F_SC_DEQ); - if (bd->adoption_buffer_rings[i] == NULL) { - rc = -rte_errno; - goto no_mem_for_stacks; - } - } - rc = snprintf(rg_name, sizeof(rg_name), RTE_MEMPOOL_MZ_FORMAT ".0", mp->name); if (rc < 0 || rc >= (int)sizeof(rg_name)) { @@ -498,11 +537,8 @@ bucket_alloc(struct rte_mempool *mp) rte_ring_free(bd->shared_orphan_ring); cannot_create_shared_orphan_ring: invalid_shared_orphan_ring: + rte_lcore_callback_unregister(bd->lcore_callback_handle); no_mem_for_stacks: - for (i = 0; i < RTE_MAX_LCORE; i++) { - rte_free(bd->buckets[i]); - rte_ring_free(bd->adoption_buffer_rings[i]); - } rte_free(bd); no_mem_for_data: rte_errno = -rc; @@ -512,16 +548,12 @@ bucket_alloc(struct rte_mempool *mp) static void bucket_free(struct rte_mempool *mp) { - unsigned int i; struct bucket_data *bd = mp->pool_data; if (bd == NULL) return; - for (i = 0; i < RTE_MAX_LCORE; i++) { - rte_free(bd->buckets[i]); - rte_ring_free(bd->adoption_buffer_rings[i]); - } + rte_lcore_callback_unregister(bd->lcore_callback_handle); rte_ring_free(bd->shared_orphan_ring); rte_ring_free(bd->shared_bucket_ring); From patchwork Mon Jul 6 20:52:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Marchand X-Patchwork-Id: 73349 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id CD912A00C5; Mon, 6 Jul 2020 22:54:32 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 28F221DD84; Mon, 6 Jul 2020 22:53:50 +0200 (CEST) Received: from us-smtp-delivery-1.mimecast.com (us-smtp-2.mimecast.com [205.139.110.61]) by dpdk.org (Postfix) with ESMTP id 462E01DD83 for ; Mon, 6 Jul 2020 22:53:48 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594068827; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sky4Ws/9qM3UAWCKiUVnd7bjuaHfcjU1TXyFyla7Jx8=; b=Wxf7gonaXGdfLlSHI9dSod2r19WN4SSm5BHVwtDcNYgwgv4DfXbmMFO2NIMY3VHED+1acS oEZBiVKzVVlEbKTYHuvcc8dHLOWs/Jf2BTNtlAdQHQkwhtKRhXeQq7xF5rIKGEVeUmepma NabZOgKztaQ1ChtZ5MRF2+eD8OfEDEg= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-152-0213GVknNW-P42l5Qif1pw-1; Mon, 06 Jul 2020 16:53:44 -0400 X-MC-Unique: 0213GVknNW-P42l5Qif1pw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C2DD4EC1A0; Mon, 6 Jul 2020 20:53:41 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.195.188]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3DF5810013D7; Mon, 6 Jul 2020 20:53:36 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: jerinjacobk@gmail.com, bruce.richardson@intel.com, mdr@ashroe.eu, thomas@monjalon.net, arybchenko@solarflare.com, ktraynor@redhat.com, ian.stokes@intel.com, i.maximets@ovn.org, olivier.matz@6wind.com, konstantin.ananyev@intel.com, Anatoly Burakov , Neil Horman , Harini Ramakrishnan , Omar Cardona , Pallavi Kadam , Ranjit Menon Date: Mon, 6 Jul 2020 22:52:34 +0200 Message-Id: <20200706205234.8040-11-david.marchand@redhat.com> In-Reply-To: <20200706205234.8040-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> <20200706205234.8040-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=david.marchand@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [dpdk-dev] [PATCH v6 10/10] eal: add multiprocess disable API X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The multiprocess feature has been implicitly enabled so far. Applications might want to explicitly disable like when using the non-EAL threads registration API. Signed-off-by: David Marchand --- Changes since v5: - fixed windows build, --- app/test/test_mp_secondary.c | 7 +++++++ lib/librte_eal/common/eal_common_proc.c | 7 +++---- lib/librte_eal/common/eal_common_thread.c | 2 +- lib/librte_eal/common/eal_private.h | 5 ----- lib/librte_eal/include/rte_eal.h | 14 ++++++++++++++ lib/librte_eal/rte_eal_version.map | 1 + lib/librte_eal/windows/eal.c | 2 +- 7 files changed, 27 insertions(+), 11 deletions(-) diff --git a/app/test/test_mp_secondary.c b/app/test/test_mp_secondary.c index ac15ddbf20..3a655c3400 100644 --- a/app/test/test_mp_secondary.c +++ b/app/test/test_mp_secondary.c @@ -97,6 +97,13 @@ run_secondary_instances(void) (1 << rte_get_master_lcore())); ret |= launch_proc(argv1); + printf("### Testing rte_mp_disable() reject:\n"); + if (rte_mp_disable()) { + printf("Error: rte_mp_disable() has been accepted\n"); + ret |= -1; + } else { + printf("# Checked rte_mp_disable() is refused\n"); + } ret |= launch_proc(argv2); ret |= !(launch_proc(argv3)); diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c index 10142683f8..d35b9c0380 100644 --- a/lib/librte_eal/common/eal_common_proc.c +++ b/lib/librte_eal/common/eal_common_proc.c @@ -1236,10 +1236,9 @@ rte_mp_reply(struct rte_mp_msg *msg, const char *peer) /* Internally, the status of the mp feature is represented as a three-state: * - "unknown" as long as no secondary process attached to a primary process - * and there was no call to eal_disable_multiprocess yet, + * and there was no call to rte_mp_disable yet, * - "enabled" as soon as a secondary process attaches to a primary process, - * - "disabled" when a primary process successfully called - * eal_disable_multiprocess, + * - "disabled" when a primary process successfully called rte_mp_disable, */ enum mp_status { MP_STATUS_UNKNOWN, @@ -1264,7 +1263,7 @@ set_mp_status(enum mp_status status) } bool -eal_disable_multiprocess(void) +rte_mp_disable(void) { return set_mp_status(MP_STATUS_DISABLED); } diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c index ea09a4f3e0..73a055902a 100644 --- a/lib/librte_eal/common/eal_common_thread.c +++ b/lib/librte_eal/common/eal_common_thread.c @@ -261,7 +261,7 @@ rte_thread_register(void) rte_errno = EINVAL; return -1; } - if (!eal_disable_multiprocess()) { + if (!rte_mp_disable()) { RTE_LOG(ERR, EAL, "Multiprocess in use, registering non-EAL threads is not supported.\n"); rte_errno = EINVAL; return -1; diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index 535e008474..a917727e41 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -733,11 +733,6 @@ void __rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset); */ void __rte_thread_uninit(void); -/** - * Mark primary process as not supporting multi-process. - */ -bool eal_disable_multiprocess(void); - /** * Instruct primary process that a secondary process wants to attach. */ diff --git a/lib/librte_eal/include/rte_eal.h b/lib/librte_eal/include/rte_eal.h index 0913d1947c..fc7db2d427 100644 --- a/lib/librte_eal/include/rte_eal.h +++ b/lib/librte_eal/include/rte_eal.h @@ -151,6 +151,20 @@ int rte_eal_cleanup(void); */ int rte_eal_primary_proc_alive(const char *config_file_path); +/** + * Disable multiprocess. + * + * This function can be called to indicate that multiprocess won't be used for + * the rest of the application life. + * + * @return + * - true if called from a primary process that had no secondary processes + * attached, + * - false, otherwise. + */ +__rte_experimental +bool rte_mp_disable(void); + #define RTE_MP_MAX_FD_NUM 8 /* The max amount of fds */ #define RTE_MP_MAX_NAME_LEN 64 /* The max length of action name */ #define RTE_MP_MAX_PARAM_LEN 256 /* The max length of param */ diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map index 3aeb5b11ab..d17f13f8d3 100644 --- a/lib/librte_eal/rte_eal_version.map +++ b/lib/librte_eal/rte_eal_version.map @@ -399,6 +399,7 @@ EXPERIMENTAL { rte_lcore_callback_unregister; rte_lcore_dump; rte_lcore_iterate; + rte_mp_disable; rte_thread_register; rte_thread_unregister; }; diff --git a/lib/librte_eal/windows/eal.c b/lib/librte_eal/windows/eal.c index 9fc831fe6f..e50601dd36 100644 --- a/lib/librte_eal/windows/eal.c +++ b/lib/librte_eal/windows/eal.c @@ -67,7 +67,7 @@ eal_proc_type_detect(void) } bool -eal_disable_multiprocess(void) +rte_mp_disable(void) { return true; }