From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96252C433DF for ; Wed, 10 Jun 2020 14:46:38 +0000 (UTC) Received: from dpdk.org (dpdk.org [92.243.14.124]) by mail.kernel.org (Postfix) with ESMTP id 2770C20734 for ; Wed, 10 Jun 2020 14:46:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="EkOlZLjm" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2770C20734 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=dev-bounces@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 536071C027; Wed, 10 Jun 2020 16:46:05 +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 C58B51C01E for ; Wed, 10 Jun 2020 16:46:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1591800363; 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=uQwpma5QaUr9+2bvXyERhAJJ90Q0bzi5jKaYEUyTHwM=; b=EkOlZLjmMg4q1OvcxdMKFlLy/0nPbyO7cCW3Tm49PlGPSQ2vr7bEtIZLVshNPoT4MmBPQk Dl5S+bqCFhHeTclrLolKvBckAVRyTrMxjL5YZKFV4i0pqd+HRN8ohhZ+wn8fPiJQbOvDYc V8Oss+6rpjxmmFIY7JD9iLMfuY/yBGU= 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-470-Q_TJf47ZN4uOoWaOdEY1NQ-1; Wed, 10 Jun 2020 10:46:01 -0400 X-MC-Unique: Q_TJf47ZN4uOoWaOdEY1NQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 862D58015CE; Wed, 10 Jun 2020 14:46:00 +0000 (UTC) Received: from dmarchan.remote.csb (unknown [10.40.192.116]) by smtp.corp.redhat.com (Postfix) with ESMTP id 772F560BF3; Wed, 10 Jun 2020 14:45:59 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: Ray Kinsella , Neil Horman Date: Wed, 10 Jun 2020 16:45:06 +0200 Message-Id: <20200610144506.30505-8-david.marchand@redhat.com> In-Reply-To: <20200610144506.30505-1-david.marchand@redhat.com> References: <20200610144506.30505-1-david.marchand@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [PATCH 7/7] eal: add lcore hotplug notifications 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" Now that lcores can be dynamically allocated/freed, we will have to notify DPDK components and applications of such events for cases where per lcore context must be allocated/initialised. Signed-off-by: David Marchand --- lib/librte_eal/common/eal_common_lcore.c | 91 +++++++++++++++++++++++ lib/librte_eal/common/eal_common_thread.c | 11 ++- lib/librte_eal/common/eal_private.h | 26 +++++++ lib/librte_eal/include/rte_lcore.h | 49 ++++++++++++ lib/librte_eal/rte_eal_version.map | 2 + 5 files changed, 178 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/common/eal_common_lcore.c b/lib/librte_eal/common/eal_common_lcore.c index 6aca1b2fee..3a997d8115 100644 --- a/lib/librte_eal/common/eal_common_lcore.c +++ b/lib/librte_eal/common/eal_common_lcore.c @@ -212,6 +212,47 @@ rte_socket_id_by_idx(unsigned int idx) return config->numa_nodes[idx]; } +struct lcore_notifier { + TAILQ_ENTRY(lcore_notifier) next; + rte_lcore_notifier_cb cb; + void *arg; +}; +static TAILQ_HEAD(lcore_notifiers_head, lcore_notifier) lcore_notifiers = + TAILQ_HEAD_INITIALIZER(lcore_notifiers); +static rte_spinlock_t lcore_notifiers_lock = RTE_SPINLOCK_INITIALIZER; + +void * +rte_lcore_notifier_register(rte_lcore_notifier_cb cb, void *arg) +{ + struct lcore_notifier *notifier; + + if (cb == NULL) + return NULL; + + notifier = calloc(1, sizeof(*notifier)); + if (notifier == NULL) + return NULL; + + notifier->cb = cb; + notifier->arg = arg; + rte_spinlock_lock(&lcore_notifiers_lock); + TAILQ_INSERT_TAIL(&lcore_notifiers, notifier, next); + rte_spinlock_unlock(&lcore_notifiers_lock); + + return notifier; +} + +void +rte_lcore_notifier_unregister(void *handle) +{ + struct lcore_notifier *notifier = handle; + + rte_spinlock_lock(&lcore_notifiers_lock); + TAILQ_REMOVE(&lcore_notifiers, notifier, next); + rte_spinlock_unlock(&lcore_notifiers_lock); + free(notifier); +} + rte_spinlock_t external_lcore_lock = RTE_SPINLOCK_INITIALIZER; unsigned int @@ -277,3 +318,53 @@ rte_lcore_dump(FILE *f) } rte_spinlock_unlock(&external_lcore_lock); } + +int +eal_lcore_external_notify_allocated(unsigned int lcore_id) +{ + struct lcore_notifier *notifier; + int ret = 0; + + RTE_LOG(DEBUG, EAL, "New lcore %u.\n", lcore_id); + rte_spinlock_lock(&lcore_notifiers_lock); + TAILQ_FOREACH(notifier, &lcore_notifiers, next) { + if (notifier->cb(lcore_id, RTE_LCORE_EVENT_NEW_EXTERNAL, + notifier->arg) == 0) + continue; + + /* Some notifier refused the new lcore, inform all notifiers + * that acked it. + */ + RTE_LOG(DEBUG, EAL, "A lcore notifier refused new lcore %u.\n", + lcore_id); + + notifier = TAILQ_PREV(notifier, lcore_notifiers_head, next); + while (notifier != NULL) { + notifier->cb(lcore_id, + RTE_LCORE_EVENT_RELEASE_EXTERNAL, + notifier->arg); + notifier = TAILQ_PREV(notifier, lcore_notifiers_head, + next); + } + ret = -1; + break; + } + rte_spinlock_unlock(&lcore_notifiers_lock); + + return ret; +} + +void +eal_lcore_external_notify_removed(unsigned int lcore_id) +{ + struct lcore_notifier *notifier; + + RTE_LOG(DEBUG, EAL, "Released lcore %u.\n", lcore_id); + rte_spinlock_lock(&lcore_notifiers_lock); + TAILQ_FOREACH_REVERSE(notifier, &lcore_notifiers, lcore_notifiers_head, + next) { + notifier->cb(lcore_id, RTE_LCORE_EVENT_RELEASE_EXTERNAL, + notifier->arg); + } + rte_spinlock_unlock(&lcore_notifiers_lock); +} diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c index a81b192ff3..f66d1ccaef 100644 --- a/lib/librte_eal/common/eal_common_thread.c +++ b/lib/librte_eal/common/eal_common_thread.c @@ -285,6 +285,12 @@ rte_thread_register(void) rte_thread_init(lcore_id, &cpuset); + if (lcore_id != LCORE_ID_ANY && + eal_lcore_external_notify_allocated(lcore_id) < 0) { + eal_lcore_external_release(lcore_id); + RTE_PER_LCORE(_lcore_id) = lcore_id = LCORE_ID_ANY; + } + RTE_LOG(DEBUG, EAL, "Registered thread as lcore %u.\n", lcore_id); RTE_PER_LCORE(thread_registered) = true; } @@ -298,8 +304,11 @@ rte_thread_unregister(void) return; lcore_id = RTE_PER_LCORE(_lcore_id); - if (lcore_id != LCORE_ID_ANY) + if (lcore_id != LCORE_ID_ANY) { + eal_lcore_external_notify_removed(lcore_id); eal_lcore_external_release(lcore_id); + RTE_PER_LCORE(_lcore_id) = LCORE_ID_ANY; + } rte_thread_uninit(); diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index 8dd850f68a..649697c368 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -283,6 +283,21 @@ uint64_t get_tsc_freq_arch(void); */ unsigned int eal_lcore_external_reserve(void); +/** + * Evaluate all lcore notifiers with a RTE_LCORE_EVENT_NEW_EXTERNAL event for + * the passed lcore. + * If an error is returned by one of them, then this change is rolled back: + * all previous lcore notifiers that had acked the RTE_LCORE_EVENT_NEW_EXTERNAL + * event receive a RTE_LCORE_EVENT_RELEASE_EXTERNAL event for the passed lcore. + * + * @param lcore_id + * The lcore to consider. + * @return + * - 0 if all notifiers agreed on the new lcore + * - -1 if one of them refused + */ +int eal_lcore_external_notify_allocated(unsigned int lcore_id); + /** * Release an external lcore. * @@ -291,6 +306,17 @@ unsigned int eal_lcore_external_reserve(void); */ void eal_lcore_external_release(unsigned int lcore_id); +/** + * Evaluate all lcore notifiers with a RTE_LCORE_EVENT_RELEASE_EXTERNAL event + * for the passed lcore. + * This function must be called with a lcore that successfully passed + * eal_lcore_external_notify_allocated(). + * + * @param lcore_id + * The lcore with role ROLE_EXTERNAL to release. + */ +void eal_lcore_external_notify_removed(unsigned int lcore_id); + /** * Prepare physical memory mapping * i.e. hugepages on Linux and diff --git a/lib/librte_eal/include/rte_lcore.h b/lib/librte_eal/include/rte_lcore.h index 9cf34efef4..e0fec33d5a 100644 --- a/lib/librte_eal/include/rte_lcore.h +++ b/lib/librte_eal/include/rte_lcore.h @@ -238,6 +238,55 @@ __rte_experimental void rte_lcore_dump(FILE *f); +enum rte_lcore_event_type { + RTE_LCORE_EVENT_NEW_EXTERNAL, + RTE_LCORE_EVENT_RELEASE_EXTERNAL, +}; + +/** + * Callback prototype for getting lcore events. + * + * @param lcore_id + * The lcore to consider for this event. + * @param event + * The type of event on the lcore. + * @param arg + * An opaque pointer passed at notifier registration. + * @return + * - -1 when refusing this event, + * - 0 otherwise. + */ +typedef int (*rte_lcore_notifier_cb)(unsigned int lcore_id, + enum rte_lcore_event_type event, void *arg); + +/** + * Register a lcore notifier. + * + * @param cb + * The callback invoked for each lcore event with the arg argument. + * See rte_lcore_notifier_cb description. + * @param arg + * An optional argument that gets passed to the callback when it gets + * invoked. + * @return + * On success, returns an opaque pointer for the created notifier. + * NULL on failure. + */ +__rte_experimental +void * +rte_lcore_notifier_register(rte_lcore_notifier_cb cb, void *arg); + +/** + * Unregister a lcore notifier. + * + * @param handle + * The handle pointer returned by a former successful call to + * rte_lcore_notifier_register. + */ +__rte_experimental +void +rte_lcore_notifier_unregister(void *handle); + /** * Set core affinity of the current thread. * Support both EAL and non-EAL thread and update TLS. diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map index 6754d52543..1e6f2aaacc 100644 --- a/lib/librte_eal/rte_eal_version.map +++ b/lib/librte_eal/rte_eal_version.map @@ -396,6 +396,8 @@ EXPERIMENTAL { # added in 20.08 rte_lcore_dump; + rte_lcore_notifier_register; + rte_lcore_notifier_unregister; rte_thread_register; rte_thread_unregister; }; -- 2.23.0