From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 842B8A09F6; Thu, 17 Dec 2020 18:49:27 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 9BD2CCA3A; Thu, 17 Dec 2020 18:49:25 +0100 (CET) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by dpdk.org (Postfix) with ESMTP id 80BFECA30 for ; Thu, 17 Dec 2020 18:49:23 +0100 (CET) Received: from Internal Mail-Server by MTLPINE1 (envelope-from talshn@nvidia.com) with SMTP; 17 Dec 2020 19:49:19 +0200 Received: from nvidia.com (l-wincomp04-vm.mtl.labs.mlnx [10.237.1.5]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 0BHHnJuE006425; Thu, 17 Dec 2020 19:49:19 +0200 From: Tal Shnaiderman To: dev@dpdk.org Cc: thomas@monjalon.net, pallavi.kadam@intel.com, dmitry.kozliuk@gmail.com, navasile@linux.microsoft.com, dmitrym@microsoft.com, david.marchand@redhat.com Date: Thu, 17 Dec 2020 19:49:13 +0200 Message-Id: <20201217174913.14280-1-talshn@nvidia.com> X-Mailer: git-send-email 2.16.1.windows.4 In-Reply-To: <20201213202437.12880-1-talshn@nvidia.com> References: <20201213202437.12880-1-talshn@nvidia.com> Subject: [dpdk-dev] [PATCH v3] eal: add generic thread-local-storage functions 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 support for tls functionality in EAL. The following functions are added: rte_tls_create_key - function to create a tls data key. rte_tls_delete_key - function to delete a tls data key. rte_tls_set_thread_value - function to set value bound to the tls key rte_tls_get_thread_value - function to get value bound to the tls key tls key will be defied by the new type rte_tls_key_t Signed-off-by: Tal Shnaiderman --- v3: switch from pthread shim to generic eal implementation [DmitryK] --- lib/librte_eal/include/meson.build | 1 + lib/librte_eal/include/rte_tls.h | 88 ++++++++++++++++++++++++++++++++++++++ lib/librte_eal/rte_eal_exports.def | 5 +++ lib/librte_eal/unix/eal_unix_tls.c | 79 ++++++++++++++++++++++++++++++++++ lib/librte_eal/unix/meson.build | 1 + lib/librte_eal/version.map | 6 +++ lib/librte_eal/windows/eal_tls.c | 72 +++++++++++++++++++++++++++++++ lib/librte_eal/windows/meson.build | 1 + 8 files changed, 253 insertions(+) create mode 100644 lib/librte_eal/include/rte_tls.h create mode 100644 lib/librte_eal/unix/eal_unix_tls.c create mode 100644 lib/librte_eal/windows/eal_tls.c diff --git a/lib/librte_eal/include/meson.build b/lib/librte_eal/include/meson.build index dc007084ff..a307137242 100644 --- a/lib/librte_eal/include/meson.build +++ b/lib/librte_eal/include/meson.build @@ -41,6 +41,7 @@ headers += files( 'rte_string_fns.h', 'rte_tailq.h', 'rte_time.h', + 'rte_tls.h', 'rte_trace.h', 'rte_trace_point.h', 'rte_trace_point_register.h', diff --git a/lib/librte_eal/include/rte_tls.h b/lib/librte_eal/include/rte_tls.h new file mode 100644 index 0000000000..3f84c683bc --- /dev/null +++ b/lib/librte_eal/include/rte_tls.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Mellanox Technologies, Ltd + */ + +#include + +#ifndef _RTE_TLS_H_ +#define _RTE_TLS_H_ + +/** + * @file + * + * TLS functions + * + * Simple TLS functionality supplied by eal. + */ + +/** + * Opaque pointer for tls key. + */ +typedef struct eal_tls_key *rte_tls_key_t; + +/** + * Function to create a tls data key visible to all threads in the process + * function need to be called once to create a key usable by all threads. + * rte_tls_key_t is an opaque pointer used to store the allocated key. + * and optional destructor can be set to be called when a thread expires. + * + * @param key + * The rte_tls_key_t will cantain the allocated key + * @param destructor + * The function to be called when the thread expires + * Not supported on Windows OS. + * + * @return + * On success, zero. + * On failure, a negative error number -ENOMEM or -ENOEXEC + */ +__rte_experimental +int +rte_tls_create_key(rte_tls_key_t *key, void (*destructor)(void *)); + +/** + * Function to delete a tls data key visible to all threads in the process + * rte_tls_key_t is an opaque pointer used to allocated the key. + * + * @param key + * The rte_tls_key_t will cantain the allocated key + * + * @return + * On success, zero. + * On failure, a negative error number -ENOMEM or -ENOEXEC + */ +__rte_experimental +int +rte_tls_delete_key(rte_tls_key_t key); + +/** + * Function to set value bound to the tls key on behalf of the calling thread + * + * @param key + * The rte_tls_key_t key + * @param value + * The value bound to the rte_tls_key_t key for the calling thread. + * + * @return + * On success, zero. + * On failure, a negative error number -ENOMEM or -ENOEXEC + */ +__rte_experimental +int +rte_tls_set_thread_value(rte_tls_key_t key, const void *value); + +/** + * Function to get value bound to the tls key on behalf of the calling thread + * + * @param key + * The rte_tls_key_t key + * + * @return + * On success, value data pointer. + * On failure, a negative error number is set in rte_errno. + */ +__rte_experimental +void * +rte_tls_get_thread_value(rte_tls_key_t key); + +#endif /* _RTE_TLS_H_ */ diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def index 6a6be1cfa6..2d5078eb76 100644 --- a/lib/librte_eal/rte_eal_exports.def +++ b/lib/librte_eal/rte_eal_exports.def @@ -306,6 +306,11 @@ EXPORTS rte_vect_get_max_simd_bitwidth rte_vect_set_max_simd_bitwidth + rte_tls_create_key + rte_tls_delete_key + rte_tls_set_thread_value + rte_tls_get_thread_value + rte_mem_lock rte_mem_map rte_mem_page_size diff --git a/lib/librte_eal/unix/eal_unix_tls.c b/lib/librte_eal/unix/eal_unix_tls.c new file mode 100644 index 0000000000..8b99f8d701 --- /dev/null +++ b/lib/librte_eal/unix/eal_unix_tls.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2020 Mellanox Technologies, Ltd + */ + +#include +#include +#include + +#include +#include +#include +#include + +struct eal_tls_key { + pthread_key_t thread_index; +}; + +int +rte_tls_create_key(rte_tls_key_t *key, void (*destructor)(void *)) +{ + int err; + + *key = malloc(sizeof(struct eal_tls_key)); + if ((*key) == NULL) { + RTE_LOG(DEBUG, EAL, "Cannot allocate tls key."); + return -ENOMEM; + } + err = pthread_key_create(&((*key)->thread_index), destructor); + if (err) { + RTE_LOG(DEBUG, EAL, "pthread_key_create failed: %s\n", + rte_strerror(err)); + free(*key); + return -ENOEXEC; + } + return 0; +} + +int +rte_tls_delete_key(rte_tls_key_t key) +{ + int err; + + if (!key) + return -EINVAL; + err = pthread_key_delete(key->thread_index); + if (err) { + RTE_LOG(DEBUG, EAL, "pthread_key_delete failed: %s\n", + rte_strerror(err)); + free(key); + return -ENOEXEC; + } + free(key); + return 0; +} + +int +rte_tls_set_thread_value(rte_tls_key_t key, const void *value) +{ + int err; + + if (!key) + return -EINVAL; + err = pthread_setspecific(key->thread_index, value); + if (err) { + RTE_LOG(DEBUG, EAL, "pthread_setspecific failed: %s\n", + rte_strerror(err)); + free(key); + return -ENOEXEC; + } + return 0; +} + +void * +rte_tls_get_thread_value(rte_tls_key_t key) +{ + if (!key) + rte_errno = EINVAL; + return pthread_getspecific(key->thread_index); +} diff --git a/lib/librte_eal/unix/meson.build b/lib/librte_eal/unix/meson.build index d3af6b6fe2..74596a8817 100644 --- a/lib/librte_eal/unix/meson.build +++ b/lib/librte_eal/unix/meson.build @@ -5,4 +5,5 @@ sources += files( 'eal_file.c', 'eal_unix_memory.c', 'eal_unix_timer.c', + 'eal_unix_tls.c', ) diff --git a/lib/librte_eal/version.map b/lib/librte_eal/version.map index 354c068f31..3ec95d4cbb 100644 --- a/lib/librte_eal/version.map +++ b/lib/librte_eal/version.map @@ -403,6 +403,12 @@ EXPERIMENTAL { rte_service_lcore_may_be_active; rte_vect_get_max_simd_bitwidth; rte_vect_set_max_simd_bitwidth; + + # added in 21.02 + rte_tls_create_key; + rte_tls_delete_key; + rte_tls_set_thread_value; + rte_tls_get_thread_value; }; INTERNAL { diff --git a/lib/librte_eal/windows/eal_tls.c b/lib/librte_eal/windows/eal_tls.c new file mode 100644 index 0000000000..73fb17ef6d --- /dev/null +++ b/lib/librte_eal/windows/eal_tls.c @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2020 Mellanox Technologies, Ltd + */ +#include +#include +#include +#include + +struct eal_tls_key { + DWORD thread_index; +}; + +int +rte_tls_create_key(rte_tls_key_t *key, + __rte_unused void (*destructor)(void *)) +{ + *key = malloc(sizeof(struct eal_tls_key)); + if ((*key) == NULL) { + RTE_LOG(DEBUG, EAL, "Cannot allocate tls key."); + return -ENOMEM; + } + (*key)->thread_index = TlsAlloc(); + if ((*key)->thread_index == TLS_OUT_OF_INDEXES) { + RTE_LOG_WIN32_ERR("TlsAlloc()"); + free(*key); + return -ENOEXEC; + } + return 0; +} + +int +rte_tls_delete_key(rte_tls_key_t key) +{ + if (!key) + return -EINVAL; + if (!TlsFree(key->thread_index)) { + RTE_LOG_WIN32_ERR("TlsFree()"); + free(key); + return -ENOEXEC; + } + free(key); + return 0; +} + +int +rte_tls_set_thread_value(rte_tls_key_t key, const void *value) +{ + if (!key) + return -EINVAL; + /* discard const qualifier */ + char *p = (char *) (uintptr_t) value; + + if (!TlsSetValue(key->thread_index, p)) { + RTE_LOG_WIN32_ERR("TlsSetValue()"); + return -ENOEXEC; + } + return 0; +} + +void * +rte_tls_get_thread_value(rte_tls_key_t key) +{ + if (!key) + rte_errno = EINVAL; + void *output = TlsGetValue(key->thread_index); + if (GetLastError() != ERROR_SUCCESS) { + RTE_LOG_WIN32_ERR("TlsGetValue()"); + rte_errno = ENOEXEC; + return NULL; + } + return output; +} diff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build index 3b2faf29eb..38f51f8967 100644 --- a/lib/librte_eal/windows/meson.build +++ b/lib/librte_eal/windows/meson.build @@ -17,6 +17,7 @@ sources += files( 'eal_mp.c', 'eal_thread.c', 'eal_timer.c', + 'eal_tls.c', 'fnmatch.c', 'getopt.c', ) -- 2.16.1.windows.4